如何使用 EJB 实现永久后台进程



我有一个关于 EJB 中的一般设计模式的问题。我有Java EE应用程序(EJB和Web(,我需要一种后台进程,它通过JPA永久扫描和处理特定数据。

我认为,一种解决方案是实现一个@Singleton EJB。在带有@PostConstruct注释的方法中,我可以开始我的流程。

@Singleton
@Startup
public class MyUpdateService {
    @PostConstruct
    void init() {
        while(true) {
            // scann for new data...
            // do the job.....
        }
    }
}

但这是推荐的模式吗?或者有没有更好的方法来在 EJB 容器中运行这样的类?

在 EJB 中,还有其他模式,如 @TimerService 和新的 Java EE7 批处理。但是这两个概念 - 我认为 - 都用于有限过程?

在当前项目中使用 EJB TimerService 执行定期数据修剪或后端数据同步等任务。它不仅允许单次执行,还允许间隔计时器和基于日历的时间表的计时器。

喜欢:

@Startup
@Singleton
public class SyncTimer {
    private static final long HOUR = 60 * 60 * 1000L;
    @Resource
    private TimerService timerService;
    private Timer timer;
    @PostConstruct
    public void init() {
        TimerConfig config = new TimerConfig();
        config.setPersistent(false);
        timer = timerService.createIntervalTimer(HOUR, HOUR, config);
    }
    @Timeout
    private synchronized void onTimer() {
        // every hour action
    }
}

作为自Java EE 7以来@devmind提到的TimerSerivce的替代方案,可以使用ManagedScheduledExecutorService:

    @Startup
    @Singleton
    public class Scheduler {
        static final long INITIAL_DELAY = 0;
        static final long PERIOD = 2;
        @Resource
        ManagedScheduledExecutorService scheduler;
        @PostConstruct
        public void init() {
            this.scheduler.scheduleAtFixedRate(this::invokePeriodically, 
                    INITIAL_DELAY, PERIOD, 
                    TimeUnit.SECONDS);
        }
        public void invokePeriodically() {
            System.out.println("Don't use sout in prod " + LocalTime.now());
        }
    }

与TimerSerivce不同,ExecutorService可以在单独的任务中并行运行。另请参阅Adam Bien的博客文章。

最新更新