我们必须实现EJB 3.0定时器,我们采取了以下方法:
- 我们创建了@Stateless bean,并使用@Resource注释注入了TimerService
- 我们已经实现了一个servlet,它在启动过程中调用初始化方法
以下狙击手应该能够给你一个更清晰的画面:
定时器实现:
public class TimerFacade {
@Resource
protected TimerService timerService;
public void createTimer() {
timerService.createTimer(startTime, intervall, ident);
}
}
init-servlet:
public class InitServlet extends HttpServlet {
@EJB
private transient ITimerFacade timerFacade;
@Override
public void init(final ServletConfig config) throws ServletException {
timerFacade.createTimer();
}
}
(重新)部署后,一切都很好。但在重启后,玻璃鱼(2.1)给了我们以下信息:
Rescheduling missed expiration for periodic timer ...
我们如何避免这种行为,如何保证计时器只启动一次?
我们必须尝试制作一个注入定时器服务的无状态bean,以便为当前可用的定时器提供服务。但是,将从容器重新安排的计时器没有出现在该列表中,因为容器在整个应用程序初始化结束时重新安排了持久计时器。
EJB定时器是持久的,这意味着如果您没有取消定时器,它将在服务器启动后继续工作。
您应该在应用程序关闭时取消计时器(不确定在glassfish中是如何做到的),或者在创建新计时器之前检查计时器是否已经存在。
我也遇到过类似的问题。。。。为了确保ObjectTimer一次运行一个,我使用了某种信号量,我在@Timeout方法中使用了一个静态布尔变量ENABLE_TIMER:
@Timeout
public void timerMethod(Timer timer) {
try{
if (ObjectModelSessionBean.ENABLE_TIMER ) {
timerMethod();
} else {
LOGGER.info("timer is temporary disabled - waiting....);
}
}catch (Exception ex){
LOGGER.severe("- Eccezione. "+ex.toString());
}
}
在timerMethod()开始时,我将变量ENABLE_TIMER设置为false,在结束时ENABLE_TIMER设置为true