我正在使用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
答案 0 :(得分:2)
您需要自己实现org.quartz.spi.JobFactory,它知道如何使用应用程序的CDI来实例化作业类并注入它们。
答案 1 :(得分:1)
我查看了@george-armhold提到的github库,但发现它还不成熟。
然而,我找到了另一种解决方案。
请查看此博文:DevSoap: Injecting CDI Managed Beans into Quartz Jobs。它描述了一个类CdiJobFactory.java
,它将完成这项工作(用Groovy或Scala编写,但不能用kotlin或java编写)。
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);
}
}
现在,在启动时加载的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
}
}
再看一下博文。只需使用@Dependent
或@ApplicationScoped
对其进行注释(取决于您的使用案例),您就可以了。
不要忘记创建两个构造函数:一个公共的无参数构造函数和一个用@Inject
注释的公共构造函数以及所需的bean作为参数。为了简洁,我省略了第一个构造函数。
如果您要使用needle4j
进行测试,只会在注释@Inject
的字段中进行注射。但是你可以同时拥有两个,焊接不会抱怨。
您还可以查看Apache Deltaspike。它还将处理其他CDI实现。如果您在具有不同实现的各种应用程序服务器上运行您的应用程序(如JBoss,Websphere,Liberty Profile,TomEE,Glassfish等),这将非常有用。
答案 2 :(得分:0)
github上有一个Quartz CDI集成库。尚未尝试过。