TimerTask 的创建和使用:如何避免循环依赖?

Creation and Usage of TimerTask: How not to have circular dependency?

我正在使用 Eclipse Luna 和 WildFly 8.2。1.Final。

我有一个名为 P001_EAR 的企业应用程序项目,其中包括:

  1. 一个名为 P001_WAR.
  2. Dynamic Web Project
  3. 一个名为 P001_EJB.
  4. EJB Project
  5. 名为 P001_EJBClient.
  6. EJB Client Project
  7. 一个名为 P001_SRC.
  8. Utility Project

这是每个项目引用的方式:

注意:在 P001_WAR 中,我为每个调用该 EJB 的 EJB 方法的 EJB 设置了 1 Business Delegate


我需要创建一个 java.util.TimerTask class,它将被安排到 运行(诸如首次时间和频率之类的安排信息在数据库中)。在每个 运行 上,它将调用 EJB 的几个方法。这是我想出的:

public final class FirstTimerTask extends TimerTask {
   @Override
   public void run() {
      // get EJB1
      // call method of EJB1
      // call another method of EJB1
   }
}

我需要创建一个 class,它将创建 1 个或多个 java.util.TimerTask class 并安排它们。它将有 java.util.Timer。任务的计划信息在我希望通过 EJB 获得的数据库中。这是我想出的:

public final class ScheduleTasksManager {
   private static Timer TIMER = new TIMER();

   public static void scheduleFirstTimerTask() {
      TimerTask timerTask = null;
      Date taskStartDate = null;
      long period = -1;
      // get EJB2
      // call method of EJB2 to retrieve the schedule information from database and populate taskStartDate and period
      timerTask = new FirstTimerTask();
      TIMER.scheduleAtFixedRate(timerTask, taskStartDate, period);
   }
}

我的问题是 FirstTimerTaskScheduleTasksManager class 放在哪里,这样我就没有任何循环依赖?我很难过。

我认为 FirstTimerTask 需要在引用 P001_EJBClient 的项目中,因为它需要调用 EJB。

我认为 ScheduleTasksManager 需要在引用 P001_EJBClient 的项目中,因为它需要调用 EJB。

作为一般规则,您不应在企业 java 应用程序中使用 java.util.Timer 对象,因为它们消耗的资源不受您的应用程序服务器的控制。

Java EE 7 为您提供调度和其他并发构造,以便以受控方式执行这些类型的操作。

以下是实现目标的 Java EE 方法的示例。这里没有循环依赖:

FirstTimer.java

import java.util.Calendar;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;

@Stateless
public class FirstTimer {

    @Resource
    private TimerService timerService;

    @EJB
    private Ejb2 ejb2;

    @EJB
    private Ejb1 ejb1;

    /* 
     * Call this from somewhere to start the timer.
     * Use the returned Timer object to cancel it if needed.
     */
    public Timer scheduleTask() {
        final Calendar start = ejb2.getStartDate();
        final long period = ejb2.getPeriodInMillisecs();
        return timerService.createIntervalTimer(start.getTime(), period, new TimerConfig(null, false));
    }

    @Timeout
    public void handleTimeout() {
        ejb1.method1();
        ejb1.method2();
    }

}

Ejb1.java

import javax.ejb.Stateless;

@Stateless
public class Ejb1 {

    public void method1() {
    }

    public void method2() {
    }
}

Ejb2.java

import java.util.Calendar;
import javax.ejb.Stateless;

@Stateless
public class Ejb2 {

    public Calendar getStartDate() {
        Calendar startDate = Calendar.getInstance();
        startDate.add(Calendar.MINUTE, 2);
        return startDate;
    }

    public long getPeriodInMillisecs() {
        return Duration.ofMinutes(2L).toMillis();
    }
}

Using the Timer Service

有更多有趣的东西