【问题标题】:How do I create several triggers for the same EJB @Timeout method?如何为同一个 EJB @Timeout 方法创建多个触发器?
【发布时间】:2014-10-18 14:24:39
【问题描述】:

JSR-000318 规范定义了 TimerService(第 18 章)。

给定一个 EJB,您可以创建一个自动计时器或一个程序化计时器

自动计时器看起来像这样

@Schedules(
{
  @Schedule(hour=”12”, dayOfWeek=”Mon-Thu”),
  @Schedule(hour=”11”, dayOfWeek=”Fri”)
})
public void sendLunchNotification() { ... }

虽然程序化计时器看起来像这样

@Resource
private TimerService timerService;

void someMethod(){
   ScheduleExpression exp = new ScheduleExpression();
   (... set exp ...)
   TimerConfig config = new TimerConfig();
   (... set config ...)
   Timer created = timerService.createCalendarTimer(exp,config);
}

当一个程序化定时器被创建时,被定时器触发的任务就是带有@Timeout注解的任务

我的问题,因为我在 JSR 中找不到明确说明,如果使用相同的 ScheduleExpression 为相同的 EJB 创建 2 个编程计时器,则容器必须调用 @Timeout 方法 两次还是一次

为了让我的问题更清楚。

假设我创建了 2 个程序化计时器。每个都有不同的元数据(存储在可序列化的计时器 INFO 属性中)。然后,我想有两个不同的计时器,当@Timeout方法执行时,它会得到这个INFO属性来选择做什么。

如果我的问题的答案是两次,那我就做不到。如果我的问题的答案是一次,那么我不能。

请注意,如果答案是一次,从性能的角度来看,这是有道理的,因为您实际上不需要在给定的时刻多次通知 EJB,即使您有几个触发器,但如果您打算独立处理这些触发器(因为每个触发器都有不同的 INFO),那么当已经有一个持续存在时,有人只是忽略了创建计时器的尝试。

【问题讨论】:

    标签: java timer ejb-3.1


    【解决方案1】:

    做这样的事情:

    @Singleton
    @Startup
    public class TestBean {
    
        // should be in a separate class
        public enum TTimer {
            FOO,
            BAR
        }
    
        @Resource
        TimerService timerService;
    
        @PostConstruct
        private void initSingleTimer() {
            removeRunningTimers();
            startInitialTimer();
        }
    
        private void removeRunningTimers() {
            for (Timer t : timerService.getTimers()) {
                if ( t.getInfo().equals(TTimer.FOO)) {
                    t.cancel();
                    log.trace("LogWatcher: Running timer canceled");                    
                }
            }
        }
    
        private void startInitialTimer() {
            ....
            timerService.createTimer(startDate, interval, TTimer.FOO);
        }
    

    【讨论】:

      【解决方案2】:

      定时器是不同的,所以如果你创建两个,那么无论调度信息是否相同,都会为两个定时器调用@Timeout方法。

      【讨论】:

      • 我也是这么想的,但这不是 apache TomEE+ 的实现方式
      • 他们声称“规范在持久性方面没有说/规定任何事情”
      • 定时器instance(createXTimer)和定时器expiration(时间X调用的超时方法)是有区别的。每个计时器实例都保证独立触发,但对于持久计时器,单个到期可能只应在一个 JVM 上成功发生。 (不成功的到期将至少重试一次。非持久性计时器到期也仅在一个成功的 JVM 上发生,但对于 @Schedule,将为每个 JVM 创建一个唯一的计时器实例。)
      • 不确定我是否得到它。我的问题是关于程序化计时器。计时器可以是编程的(不是由 Schedule 注释定义的)并且同时是持久的。我的问题是:如果我创建了 2 个编程计时器,它们当然会执行相同的 Timeout 方法,但是如果两个编程计时器具有相同的时间表,此方法会执行两次还是一次?您的第一个答案符合我的意见,但我没有收到您的最新评论。
      • 如果您创建 2 个程序化计时器,那么即使它们具有相同的时间表,它们也会独立触发。它们只是碰巧在触发时调用了相同的超时方法。
      猜你喜欢
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 1970-01-01
      相关资源
      最近更新 更多