从 Quartz 作业调用 EJB

Invoke an EJB from a Quartz job

我有一个在 Wildfly 上运行的 Java EE 应用程序,我想将它与 Quartz Scheduler 集成。这就是我设想从 Quartz 作业调用 EJB 的方式(因为我在编译时不知道 EJB 的名称 class,所以我使用查找):

public class MyJob implements Job {

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {        

        InitialContext ic = new InitialContext();
        MyInterface bean = null;
        try {
            String beanClassName  = getItFromSomewhere();
            bean = (MyInterface) ic.lookup("java:module/" + beanClassName );
        } 
        catch (NamingException e) {
            e.printStackTrace();
        }

        bean.myMethod();
     }
}

这种做法正确吗?容器不知道 Quartz 作业 已启动,有问题吗?

恕我直言,一个更简洁的替代方案是通过 JobJobExecutionContext

传递 EJB 实例

准备 Job

final JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put(MY_INTERFACE, myInterface);

final Job myJob =
    JobBuilder.newJob(MyJob.class)
              .setJobData(jobDataMap)
              .build();

里面Job#execute

final JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
final MyInterface myInterface = (MyInterface) jobDataMap.get(MY_INTERFACE);

Quartz Job 实现不应该知道它在其中运行的所有 JavaEE 容器。从长远来看,这将简化 code/architecture 的更新过程。
此外,您的 Job 应该只关心它的唯一职责,而不是获取所需的依赖项。
JobDataMap 视为一种奇怪的 依赖注入 .

这是 Quart'z 开发人员在 GitHub 上提供的答案:

https://github.com/quartz-scheduler/quartz/blob/master/quartz-jobs/src/main/java/org/quartz/jobs/ee/ejb/EJBInvokerJob.java

总而言之:您的方法是正确的,在您的 MyJob class 中您正确地创建了一个 InitialContext() 来搜索您想要调用的 EJB 实例。 您不能将 EJB 的实例放在 JobContext 中,如前一个答案所建议的那样,因为万一在作业的调度和它的调用之间有服务器重新启动,您无法保证您想要的 EJB 实例将在 JobContext 中 "injected"。