Долгосрочный метод таймера EJB и проблемы с Weblogic 10.3.4 - PullRequest
1 голос
/ 22 октября 2011

У меня есть EJB Timer 3.0, и у этого таймера есть метод, который приблизительно работает в течение 6 часов на вызов.Таймер, который я реализовал, приведен ниже:

@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class BatchJobConsumerTimer implements BatchJobConsumerTimerLocal {

@Resource
TimerService timerService;

@EJB
ModelOperationsLocal modelOperations;

private static final long ONE_DAY_IN_MILLISECONDS = 86400000L;

private static final Logger LOG = Logger
        .getLogger(BatchJobConsumerTimer.class);

public BatchJobConsumerTimer() {
}

@Timeout
public void timeout(Timer timer) {
    LOG.info("Entering timeout method.");
    if(TimerRunningChecker.isWorking()){
        LOG.warn("A TIMER ALREADY IS RUNNING, SECOND TIMER WANTS TO ENTER TIMEOUT METHOD");
        return;
    } else {
        TimerRunningChecker.setWorking(true);
    }

    TimerConfiguration timerConfiguration = (TimerConfiguration) timer
            .getInfo();
    if (timerConfiguration != null) {
        Calendar calendar = new GregorianCalendar();
        if (isWorkDay(timerConfiguration.getSelectedDays())) {
            Date startTime = new Date(System.currentTimeMillis());
            Boolean and = timerConfiguration.getAnd();
            Integer numberOfJobs = timerConfiguration.getNumberOfJobs();

            int jobConsumed = 0;

            INFINITE: while (true) {
                List<Job> findWaitingJobs = modelOperations
                        .getLatestUploadedWaitingBatchJobs((numberOfJobs == -1 || numberOfJobs > 100) ? 100
                                : numberOfJobs);
                if (findWaitingJobs != null) {
                    if(findWaitingJobs.size() == 0){
                        LOG.warn("There is no jobs to consume.");
                        break INFINITE;
                    }
                    for (Job job : findWaitingJobs) {
                        ++jobConsumed;// means successful and unsuccessful
                        LOG.info("Job Number: " + (jobConsumed));
                        if (and) {
                            if (numberOfJobs != -1) {

                                if (jobConsumed > numberOfJobs
                                        && isEqualsAfterEndSchedule(
                                                calendar,
                                                timerConfiguration)) {
                                    LOG.info("jobConsumed > numberOfJobs && isEqualsAfterEndSchedule(calendar) is true");
                                    break INFINITE;
                                }
                            } else {
                                if (isEqualsAfterEndSchedule(calendar,
                                        timerConfiguration)) {
                                    LOG.info("numberOfJobs = infinite && isEqualsAfterEndSchedule(calendar) is true");
                                    break INFINITE;
                                }
                            }
                        } else {
                            if (numberOfJobs != -1) {
                                if (jobConsumed > numberOfJobs
                                        || isEqualsAfterEndSchedule(
                                                calendar,
                                                timerConfiguration)) {
                                    LOG.info("jobConsumed > numberOfJobs || isEqualsAfterEndSchedule(calendar) is true");
                                    break INFINITE;
                                }
                            } else {
                                if (isEqualsAfterEndSchedule(calendar,
                                        timerConfiguration)) {
                                    LOG.info("numberOfJobs = infinite || isEqualsAfterEndSchedule(calendar) is true");
                                    break INFINITE;
                                }
                            }
                        }

                        try {
                            LOG.info(job.getServiceNumber()
                                    + " hizmet numarali is tuketilicek.");

                            modelOperations.update(job);
                        } catch (Exception e) {
                            LOG.error(e, e);
                        }
                    }
                } else {
                    // liste bos don method'dan
                    break INFINITE;
                }
            }

            //send email
            Date endTime = new Date(System.currentTimeMillis());
            try {
                modelOperations.sendBatchOperationMail(startTime, endTime);
            } catch (Exception e) {
                LOG.error(e, e);
            }
        } else {
            LOG.warn("Today is not the working day.");
        }
    } else {
        LOG.warn("TimerConfiguration is not set.");
    }

    if(!TimerRunningChecker.isWorking()){
        LOG.warn("A TIMER WANTS CHANGE THE STATE OF WORKING TO NOT WORKING STATE, BUT IT IS ALREADY SET NOT WORKING STATE");
        return;
    } else {
        TimerRunningChecker.setWorking(false);
    }
    LOG.info("Exiting timout method.");
}

@Override
public void createTimer(TimerConfiguration timerConfiguration)
        throws Exception {
    // stop the other timers.
    Collection<Timer> timers = timerService.getTimers();
    for (Timer timer : timers) {
        timer.cancel();
    }

    timerService.createTimer(
            getRemainingTimeToFirstExpiration(timerConfiguration),
            ONE_DAY_IN_MILLISECONDS, timerConfiguration);
}

private long getRemainingTimeToFirstExpiration(
        TimerConfiguration timerConfiguration) {
    Calendar now = new GregorianCalendar();
    Calendar nextStart = new GregorianCalendar();
    nextStart.set(Calendar.HOUR_OF_DAY, timerConfiguration.getBeginHour());
    nextStart.set(Calendar.MINUTE, timerConfiguration.getBeginMinute());
    nextStart.set(Calendar.SECOND, timerConfiguration.getBeginSecond());

    long diff = nextStart.getTimeInMillis() - now.getTimeInMillis();
    return (diff < 0 ? diff + ONE_DAY_IN_MILLISECONDS : diff);
}

private boolean isEqualsAfterEndSchedule(Calendar calendar,
        TimerConfiguration timerConfiguration) {
    calendar.setTimeInMillis(System.currentTimeMillis());
    int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
    int currentMinute = calendar.get(Calendar.MINUTE);
    int currentSecond = calendar.get(Calendar.SECOND);

    if (currentHour > timerConfiguration.getEndHour()) {
        return true;
    } else if (currentHour == timerConfiguration.getEndHour()) {
        if (currentMinute > timerConfiguration.getEndMinute()) {
            return true;
        } else if (currentMinute == timerConfiguration.getEndMinute()) {
            if (currentSecond >= timerConfiguration.getEndSecond()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
}

private boolean isWorkDay(String selectedDays) {
    if(selectedDays == null){
        LOG.error("selectedDays is NULL!");
        return false;
    }

    LOG.info("selectedDays: " + selectedDays);
    if (selectedDays.equals("?")) {
        return false;
    }

    if (selectedDays.equals("*")) {
        return true;
    }

    Calendar now = GregorianCalendar.getInstance();

    int i = now.get(Calendar.DAY_OF_WEEK);
    LOG.info("now.get(Calendar.DAY_OF_WEEK): " + i);
    if (selectedDays.contains("" + i)) {
        return true;
    } else {
        return false;
    }
}
}  

Сервер приложений, на котором мне нужно развернуть это приложение, - Weblogic 10.3.4, а настройка времени ожидания транзакции настроена на 30 секунд.

В свете того, что я упомянул выше, метод тайм-аута автоматически откатывается через 30 секунд после начала выполнения, и weblogic повторяет его непрерывно.Я пытался удалить эту транзакцию, аннотируя класс, метод, но безуспешно.Как я могу сделать этот метод без транзакций?Спасибо за ваш интерес.

Кстати, рекомендация balusC по вопросу значительна для преодоления этой проблемы?

1 Ответ

1 голос
/ 13 января 2012

В этом случае используйте транзакцию BeanManagement. В противном случае компонент Timerservice бина сам запустит транзакцию для удовлетворения транзакции в постоянном хранилище по умолчанию (которое в каждом случае является хранилищем файлов в WLS), использующем интерфейс XA. Этот обходной путь помогает на сервере приложений Weblogic, а также на других серверах приложений.

@Stateless 

@Local(TimerBusinessService.class)
@TransactionManagement(TransactionManagementType.BEAN)
public class TimerBusinessServiceImpl implements TimerBusinessService {

    @Resource
    private TimerService timerService;

    @EJB
    private NonTxService nonTxService;

    @Override
    public void doStartTimer() throws EjpdBusinessException {
        long everyDay = 86400000;...
        timerService.createTimer(0, everyDay, ...);
    }           

    @Timeout
    public void periodicalTimerMethode(Timer timer) throws EjpdBusinessException {
        try {
            nonTxService.proceedAction ();
        } catch (…Exception ex) {
            throw new RuntimeException(“..”, ex);
        }
    }
}
...