【问题标题】:Creation and Usage of TimerTask: How not to have circular dependency?TimerTask的创建和使用:如何不产生循环依赖?
【发布时间】:2015-12-17 15:13:04
【问题描述】:

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

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

  1. 一个名为 P001_WARDynamic Web Project
  2. 一个名为 P001_EJBEJB Project
  3. 一个名为 P001_EJBClientEJB Client Project
  4. 一个名为 P001_SRCUtility Project

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

  • P001_SRC 不引用任何其他项目。
  • P001_EJB 引用 P001_SRCP001_EJBClient
  • P001_EJBClient 引用 P001_SRC
  • P001_WAR 引用 P001_SRCP001_EJBClient

注意:在 P001_WAR 中,每个调用该 EJB 的 EJB 方法的 EJB 都有 1 个 Business Delegate


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

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

我需要创建一个类来创建 1 个或多个 java.util.TimerTask 类并安排它们。它将具有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 类放在哪里,这样我就没有任何循环依赖?我难住了。

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

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

【问题讨论】:

  • 你能画一张图来说明你做了什么吗?
  • @NorbertvanNobelen 我还没有编写FirstTimerTaskScheduleTasksManager 这两个类。这是伪代码。

标签: java eclipse jakarta-ee timer timertask


【解决方案1】:

作为一般规则,您不应在企业 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 上还有更多有趣的东西

【讨论】:

  • 谢谢。这对我有很大帮助。虽然我目前正在使用 EJB 2.1,但您的解决方案仍然让我了解如何使用 EBJ 2.1 实现它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-28
  • 2018-07-18
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 2018-09-03
相关资源
最近更新 更多