2010-11-23 32 views
30

J'utilise le quartz avec ressort et je veux injecter/utiliser une autre classe dans la catégorie d'emplois et je ne sais pas comment le faire correctementComment utiliser @Autowired dans un travail à quartz?

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> 

quartz emploi:

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 avec la base de données dans la classe de tâche pour faire un travail de base de données dans la tâche, comment faire?

+1

lien ci-dessous a résolu la solution pour moi http://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz-job-in-spring/15211030#17394905 – pathfinder

Répondre

10

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 l'exemple déjà vous bien jobDataAsMap mis en place,:

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

alors vous devriez être en mesure d'y accéder dans votre code Java réelle 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 - avoir la propriété param1 définie avec getter/setter. Vous pouvez essayer de définir avec java.lang.Class alors le type et ont le fait automatiquement (printemps serait le faire 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.

+0

i vouloir être capable d'utiliser un objet DTO, et un objet de domaine dans le travail à quartz, et l'autowiring ne fonctionne pas ici, alors pouvez-vous me dire quoi faire? –

+2

Dans votre question, vous avez écrit que vous vouliez utiliser la classe, pas un objet. Quoi qu'il en soit, quelle est la différence alors? –

+0

Dans le manuel Quartz, il est indiqué (comme meilleure pratique): "Stocker uniquement les types de données primitifs dans JobDataMap pour éviter les problèmes de sérialisation des données à court et à long terme". Cette solution fonctionne-t-elle vraiment bien? Merci. – aloplop85

14

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é, et non Spring. Quartz essaiera de définir chaque propriété dans JobDataMap comme une propriété.

Par exemple. puisque vous avez une clé "myDao" Quartz cherchera une méthode appelée "setMyDao" et passera la valeur de la clé dans cette méthode. Si vous voulez que Spring injecte des haricots de printemps dans vos travaux, créez une SpringBeanJobFactory et définissez-la dans votre SchedulerFactoryBean avec la propriété jobFactory dans votre contexte de printemps.

SpringBeanJobFactory javadoc:

applique contexte planificateur, carte de données d'emploi et de carte de données de déclenchement entrées comme la valeur des propriétés de haricots

+6

Pour ceux qui sont intéressés, vous pouvez trouver une implémentation 'SpringBeanJobFactory' pour autowire automatiquement les jobs Quartz dans cette réponse (avec un exemple complet): http://stackoverflow.com/a/15211030/787375 – jelies

8
ApplicationContext springContext = 
    WebApplicationContextUtils.getWebApplicationContext(
     ContextLoaderListener.getCurrentWebApplicationContext().getServletContext() 
    ); 
Bean bean = (Bean) springContext.getBean("beanName"); 
bean.method(); 
+3

Pourquoi pensez-vous que les OP fonctionnent dans un contexte web? – kolossus

+0

@kolossus quelle autre façon de faire cette action dans d'autres types de contextes? – msangel

2

Comme mentionné dans inject bean reference into a Quartz job in Spring? vous pouvez utiliser le printemps 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é précédemment, il est possible qu'il ne fonctionne pas sur une version à ressort mais je l'ai testé sur 4.2.1.RELEASE qui a bien fonctionné.

+0

Ça ne fonctionne pas. Ressort 4.2.4.RELEASE et Quartz 2.2.1 –

+0

Quelle est l'erreur?! Vous avez également défini le ressort pour analyser automatiquement les annotations du haricot. J'ai aussi testé avec Quartz 2.2.2. –

+0

Oui, j'ai numérisation compoenent. Il dit WebApplicatinoContext non disponible, etc. Aucune exception .. Mais un message lors du déploiement. –

0

ceci 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 config 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! :)