5

我正在使用 Glassfish 和 CDI 进行注射,(大部分)成功。我似乎无法让 Quartz 工作与注入注释的 bean 一起工作,@Inject从未被注入。

Quartz 是否使用了某种不同的类加载器来阻止注入的发生?

我在 web.xml 中像这样配置 Quartz:

<context-param>
    <param-name>quartz:config-file</param-name>
    <param-value>quartz.properties</param-value>
</context-param>
<context-param>
    <param-name>quartz:shutdown-on-unload</param-name>
    <param-value>true</param-value>
</context-param>
<context-param>
    <param-name>quartz:wait-on-shutdown</param-name>
    <param-value>false</param-value>
</context-param>
<context-param>
    <param-name>quartz:start-scheduler-on-load</param-name>
    <param-value>true</param-value>
</context-param>

<listener>
    <listener-class>
        org.quartz.ee.servlet.QuartzInitializerListener
    </listener-class>
</listener>

我的quartz.properties 看起来像:

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.scheduler.instanceId = 1
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false

org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = quartz-config.xml
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
4

3 回答 3

3

我查看了@george-armhold 提到的 github 库,但发现它并不成熟。

不过,我找到了另一个解决方案。

查看这篇博文:DevSoap:将 CDI 托管 Bean 注入 Quartz 作业。它描述了一个类CdiJobFactory.java,它将完成这项工作(用 Groovy 或 Scala 编写,但不是 kotlin 或 java)。

java中的实现

支持 CDI 的作业工厂

java中的相同CdiJobFactory:

/**
 * CDI Job factory. Quartz will produce CDI managed beans.
 */
@ApplicationScoped
public class CdiJobFactory implements JobFactory {

  @Inject
  BeanManager beanManager;

  @Override
  public Job newJob(final TriggerFiredBundle bundle, final Scheduler scheduler) throws SchedulerException {
    final Class<Job> jobClazz = (Class<Job>) bundle.getJobDetail().getJobClass();
    final Bean<Job> bean = (Bean<Job>) beanManager.getBeans(jobClazz).stream().findAny().orElseThrow(IllegalStateException::new);
    final CreationalContext<Job> ctx = beanManager.createCreationalContext(bean);

    return (Job) beanManager.getReference(bean, jobClazz, ctx);
  }

}

在侦听器类中注入 CDI 作业工厂

现在在启动时加载的 Listener 类中,执行以下操作:

@ApplicationScoped
public class Listener implements ServletContextListener {

  @Inject
  public Listener(final CdiJobFactory jobFactory) {
    this.jobFactory = jobFactory;
  }

  @Override
  public void contextInitialized(final ServletContextEvent servletEvent) {
    LOG.info("Initializing Listener");

    try {
      scheduler = StdSchedulerFactory.getDefaultScheduler();
      scheduler.setJobFactory(jobFactory);
    } catch (final SchedulerException | RuntimeException schedEx) {
      LOG.error("Problem loading Quartz!", schedEx);
    }

   // register your jobs here
  }
}

创造就业机会

再看博文。只需用@Dependentor注释它们@ApplicationScoped(取决于您的用例)就可以了。

不要忘记创建两个构造函数:一个公共的无参数构造函数和一个用@Inject所需的 bean 注释的公共构造函数作为参数。为简洁起见,我对第一个构造函数进行了全面介绍。

如果您要使用 进行测试needle4j,则只会使用带注释的字段进行注入@Inject。但你可以两者兼得,焊接不会抱怨。

其他选择

您还可以查看Apache Deltaspike。它还将处理其他 CDI 实现。如果您在具有不同实现(如 JBoss、Websphere、Liberty Profile、TomEE、Glassfish 等)的各种应用程序服务器上运行应用程序,这将非常有用。

于 2018-05-16T11:40:36.757 回答
2

You will need to make your own implementation of org.quartz.spi.JobFactory that knows how to use your application's CDI to instantiate the jobs classes and inject them.

于 2011-01-29T03:10:17.210 回答
0

github上有一个 Quartz CDI 集成库。还没试过。

于 2011-12-13T05:32:46.647 回答