web-dev-qa-db-fra.com

Comment utiliser @Autowired dans un travail Quartz?

j'utilise du quartz avec ressort et je veux injecter/utiliser une autre classe dans la classe d'emploi et je ne sais pas comment le faire correctement

le xml:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

   <!-- Scheduler task -->
   <bean name="schedulerTask" class="com.mkyong.quartz.SchedulerTask" />

   <!-- Scheduler job -->
   <bean name="schedulerJob"
       class="org.springframework.scheduling.quartz.JobDetailBean">

     <property name="jobClass" value="com.mkyong.quartz.SchedulerJob" />

     <property name="jobDataAsMap">
        <map>
          <entry key="schedulerTask" value-ref="schedulerTask" />
         </map>
      </property>
   </bean>

   <!-- Cron Trigger -->
   <bean id="cronTrigger"
    class="org.springframework.scheduling.quartz.CronTriggerBean">

    <property name="jobDetail" ref="schedulerJob" />
    <property name="cronExpression" value="0/10 * * * * ?" />

   </bean>

   <!-- Scheduler -->
   <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobDetails">
       <list>
          <ref bean="schedulerJob" />
       </list>
    </property>

    <property name="triggers">
        <list>
        <ref bean="cronTrigger" />
        </list>
    </property>
   </bean>

</beans>

le travail du quartz:

package com.mkyong.quartz;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class SchedulerJob extends QuartzJobBean
{
    private SchedulerTask schedulerTask;

    public void setSchedulerTask(SchedulerTask schedulerTask) {
        this.schedulerTask = schedulerTask;
    }

    protected void executeInternal(JobExecutionContext context)
    throws JobExecutionException {

        schedulerTask.printSchedulerMessage();

    }
}

la tâche à exécuter:

package com.mkyong.quartz;

public class SchedulerTask {

   public void printSchedulerMessage() {

       System.out.println("Struts 2 + Spring + Quartz ......");

   }
}

je veux injecter une autre classe DTO qui traite de la base de données dans la classe de tâches pour faire un travail de base de données dans la tâche, comment faire?

33
Mahmoud Saleh

Vous ne savez pas si c'est ce que vous voulez, mais vous pouvez transmettre certaines valeurs de configuration au travail Quartz. Je crois que dans votre cas, vous pouvez profiter de la propriété jobDataAsMap que vous avez déjà configurée, par exemple:

 <property name="jobDataAsMap">
    <map>
      <entry key="schedulerTask" value-ref="schedulerTask" />
      <entry key="param1" value="com.custom.package.ClassName"/>
     </map>
  </property>

Ensuite, vous devriez pouvoir y accéder dans votre Java de manière manuelle:

protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
    schedulerTask.printSchedulerMessage();
    System.out.println(context.getJobDetail().getJobDataMap().getString("param1"));
}

Ou en utilisant l'approche Magic Spring - ayez le param1 propriété définie avec getter/setter. Vous pouvez essayer de le définir avec Java.lang.Class tapez ensuite et faites-le automatiquement (Spring le ferait pour vous):

 private Class<?> param1;

 // getter & setter

 protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
    schedulerTask.printSchedulerMessage();
    System.out.println("Class injected" + getParam1().getName());
 }     

Je ne l'ai pas testé cependant.

10
Grzegorz Oledzki

Dans votre solution, vous utilisez l'annotation spring @Autowired dans une classe qui n'est pas instanciée par Spring. Votre solution fonctionnera toujours si vous supprimez l'annotation @Autowired car Quartz définit la propriété, pas Spring.

Quartz essaiera de définir chaque clé dans JobDataMap en tant que propriété. Par exemple. puisque vous avez une clé "myDao" Quartz recherchera une méthode appelée "setMyDao" et passera la valeur de la clé dans cette méthode.

Si vous souhaitez que Spring injecte des beans Spring dans vos travaux, créez un SpringBeanJobFactory et définissez-le dans votre SchedulerFactoryBean avec le paramètre jobFactory propriété dans votre contexte de printemps.

SpringBeanJobFactory javadoc:

Applique le contexte du planificateur, le mappage de données de travail et déclenche des entrées de mappage de données en tant que valeurs de propriété de bean

14
Kieren Dixon
ApplicationContext springContext = 
    WebApplicationContextUtils.getWebApplicationContext(
        ContextLoaderListener.getCurrentWebApplicationContext().getServletContext()
    );
Bean bean = (Bean) springContext.getBean("beanName");
bean.method();
9
Damian

Comme mentionné dans injecter une référence de bean dans un travail Quartz au printemps? vous pouvez utiliser spring SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

@Named
public class SampleJob implements Job {

    @Inject
    private AService aService;

   @Override
    public void execute(JobExecutionContext context)
        throws JobExecutionException {

       //Do injection with spring
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        aService.doIt();
       }
}

Comme mentionné, il peut ne pas fonctionner sur certaines versions de printemps, mais je l'ai testé sur 4.2.1.RELEASE qui fonctionnait bien.

3
Alireza Fattahi

c'est ma solution:

    public class MySpringBeanJobFactory extends
        org.springframework.scheduling.quartz.SpringBeanJobFactory implements
        ApplicationContextAware {
      private ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.ctx = applicationContext;
    }


    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle)
            throws Exception {

        Object jobInstance = super.createJobInstance(bundle);
        ctx.getAutowireCapableBeanFactory().autowireBean(jobInstance);
        return jobInstance;
    }
}

puis configurez la classe de MySpringBeanJobFactory dans le xml:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="jobFactory">
            <bean class="com.xxxx.MySpringBeanJobFactory" />
    </property>
        <property name="configLocation" value="classpath:quartz.properties" />
        <property name="triggers">
            <list>
                <ref bean="cronTrigger"/>
            </list>
        </property>
    </bean>

Bonne chance ! :)

0
martin