я могу использовать инъекцию CDI в задания кварцевого планировщика? - PullRequest
3 голосов
/ 27 января 2011

Я использую Glassfish и CDI для инъекций (в основном) успешно. Кажется, я не могу заставить задания Quartz работать с инжекционными бобами, помеченными @Inject, которые никогда не вводятся.

Использует ли Quartz какой-либо другой загрузчик классов, предотвращающий инъекцию?

Я настраиваю Quartz так в моем web.xml:

<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

Ответы [ 3 ]

2 голосов
/ 29 января 2011

Вам нужно будет создать собственную реализацию org.quartz.spi.JobFactory, которая знает, как использовать CDI вашего приложения для создания экземпляров классов заданий и их внедрения.

1 голос
/ 16 мая 2018

Я заглянул в библиотеку github, упомянутую @ george-armhold, но обнаружил, что она не зрелая.

Тем не менее, я нашел другое решение.

Загляните в этот пост: DevSoap: Внедрение управляемых бобов CDI в рабочие места кварца . Он описывает класс CdiJobFactory.java, который будет выполнять эту работу (написанный на Groovy или Scala, но не на kotlin или java).

Реализация в Java

Фабрика вакансий с поддержкой CDI

Тот же CdiJobFactory в Java:

/**
 * 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 Job Factory в классы слушателей

Теперь в вашем классе 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 и необходимыми компонентами в качестве параметров. Я упустил первый конструктор для краткости.

Если вы собираетесь проводить тестирование с needle4j, инъекции будут приниматься только с помеченным полем @Inject. Но вы можете иметь оба, сварка не будет жаловаться.

Другие альтернативы

Вы также можете взглянуть на Apache Deltaspike . Он также будет обрабатывать другие реализации CDI. Это полезно, если вы запускаете свое приложение на разных серверах приложений с разными реализациями (например, JBoss, Websphere, Liberty Profile, TomEE, Glassfish и т. Д.).

0 голосов
/ 13 декабря 2011

Существует библиотека интеграции Quartz CDI на github .Еще не пробовал.

...