自定义 CDIJobFactory,用于将 Quartz 与 CDI 结合使用

Custom CDIJobFactory for using Quartz with CDI

我正在 Wildfly 10.0.0 上 运行 开发 Javaee7 网络应用程序,使用 CDI 进行依赖注入,并希望使用 Quartz 安排一些作业。 这是安排作业的 class:

@Singleton
@Startup
public class ScheduledJobsManager {

    private Scheduler scheduler;

    @Inject
    private CdiJobFactory jobFactory;

    @PostConstruct
    public void postConstruct() {
        JobDetail jobDetail = null;
        CronTrigger trigger = null;
        scheduler = new StdSchedulerFactory().getScheduler();
        scheduler.setJobFactory(jobFactory);
        boolean scheduled = false;

        jobDetail = JobBuilder.newJob(ImagesProcessJob.class)
        .withIdentity("imageProcessJob", "mediaProxyJobs")
        .build();
        trigger = TriggerBuilder.newTrigger().withIdentity("imageProcessTrigger", "mediaProxyTriggers")
                .withSchedule(CronScheduleBuilder.cronSchedule(imageProcessScheduleStr)).build();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }

    @PreDestroy
    public void preDestroy() {
        if (scheduler != null && scheduler.isStarted()) {
            scheduler.shutdown(false);
        }
    }
}

这是允许在 Quartz 上使用 CDI 的自定义 JobFactory:

@Named
public class CdiJobFactory implements JobFactory {

  @Inject
  private BeanManager beanManager;

  @Override
  public Job newJob(TriggerFiredBundle bundle, Scheduler Scheduler) throws SchedulerException {
    JobDetail jobDetail = bundle.getJobDetail();
    Class<? extends Job> jobClazz = jobDetail.getJobClass();
    Bean<?> bean = beanManager.getBeans(jobClazz).iterator().next();
    CreationalContext<?> ctx = beanManager.createCreationalContext(bean);
    return (Job) beanManager.getReference(bean, jobClazz, ctx);
  }
}

这就是工作:

@Named
public class ImagesProcessJob  implements Job {
    @Inject
    private MyManager myManager;

    public ImagesProcessJob() {}

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            myManager.doTheJob();
        } catch(Exception e) {
            throw new JobExecutionException(e);
        }
    }
}

当我尝试部署 war 文件时,出现此错误:

16:03:19,524 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-3) MSC000001: Failed to start service jboss.deployment.unit."imageproxy.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."imageproxy.war".WeldStartService: Failed to start service
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type CdiJobFactory with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private cat.xavisan.imaging.imageproxy.schedule.ScheduledJobsManager.jobFactory
  at cat.xavisan.imaging.imageproxy.schedule.ScheduledJobsManager.jobFactory(ScheduledJobsManager.java:0)

    at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:359)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281)
    at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:155)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:518)
    at org.jboss.weld.bootstrap.ConcurrentValidator.doWork(ConcurrentValidator.java:68)
    at org.jboss.weld.bootstrap.ConcurrentValidator.doWork(ConcurrentValidator.java:66)
    at org.jboss.weld.executor.IterativeWorkerTaskFactory.call(IterativeWorkerTaskFactory.java:63)
    at org.jboss.weld.executor.IterativeWorkerTaskFactory.call(IterativeWorkerTaskFactory.java:56)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at org.jboss.threads.JBossThread.run(JBossThread.java:320)

这是beans.xml

的内容
 <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.2" bean-discovery-mode="annotated">

</beans>

知道出了什么问题吗?

问题是您正在使用 bean-discovery-mode="annotated" 但没有在 类 上提供 bean 定义注释。

理想情况下,@Named 仅用于 UI 类型的交互,很少有其他供应商特定的功能。它是一个预选赛。为了使这项工作有效,我将使用 @ApplicationScoped 而不是 @Named.

对其进行注释

CDI 规范中的引用:http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#bean_defining_annotations