Dependency injection 我可以在quartz调度程序作业中使用CDI注入吗?
我正在使用Glassfish和CDI进行注射,(大部分)成功。我似乎无法让Quartz作业与注入一起工作-用Dependency injection 我可以在quartz调度程序作业中使用CDI注入吗?,dependency-injection,glassfish,quartz-scheduler,glassfish-3,cdi,Dependency Injection,Glassfish,Quartz Scheduler,Glassfish 3,Cdi,我正在使用Glassfish和CDI进行注射,(大部分)成功。我似乎无法让Quartz作业与注入一起工作-用@Inject注释的bean永远不会被注入 Quartz是否使用某种不同的类加载器来防止注入发生 我在web.xml中这样配置Quartz: <context-param> <param-name>quartz:config-file</param-name> <param-value>quartz.properties<
@Inject注释的bean永远不会被注入
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>
您需要自己实现org.quartz.spi.JobFactory,它知道如何使用应用程序的CDI实例化作业类并注入它们。上有一个quartz CDI集成库。我还没有尝试过。我查看了@george armhold提到的github库,但发现它还不成熟
然而,我找到了另一个解决办法
查看此博客帖子:。它描述了一个类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);
}
}
创造就业机会
再看看这篇博文。只需使用@Dependent
或@ApplicationScoped
对它们进行注释(取决于您的用例),就可以了
不要忘记创建两个构造函数:一个公共无参数构造函数和一个公共构造函数,用@Inject
和所需的bean作为参数进行注释。为了简洁起见,我将第一个构造函数设置为omnited
如果要使用needle4j
进行测试,则只能使用带注释的@Inject
字段进行注入。但你可以两者兼得,weld不会抱怨的
其他选择
你也可以看看。它还将处理其他CDI实现。如果您使用不同的实现(如JBoss、Websphere、Liberty Profile、TomEE、Glassfish等)在不同的应用程序服务器上运行应用程序,这将非常有用。这里是对CDI扩展的良好描述。我尝试了上面建议的JobFactory实现,但在beanManager.getBeans(jobClazz)上的应用程序中失败.stream().findAny()语句。我尝试了一些变体来调整工作和工厂,然后放弃了这条路径,加入了Apache Deltaspike(但没有使用他们的@Scheduled注释),现在它可以工作了。读起来像是CDI问题,而不是石英的问题。我已经用了三年了。可能我的用户错误比我用焊接做的IDKWTF更多。但是你关于deltaspike的建议解决了我眼前的问题,所以谢谢!
/**
* 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);
}
}
@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
}
}