EJB Timer长时间运行方法和Weblogic 10.3.4问题

时间:2011-10-22 15:22:26

标签: transactions timer ejb weblogic

我有一个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对question的建议是否可以从这个问题中解决?

1 个答案:

答案 0 :(得分:1)

在这种情况下,请使用BeanManagement Transaction。否则,bean Timerservice本身将启动一个事务来满足使用XA接口的默认持久存储上的事务(在每种情况下都是WLS上的文件存储)。 此解决方法有助于Weblogic Application Server以及其他应用程序服务器。

@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);
        }
    }
}