2010-11-23 20 views
30

i estoy usando cuarzo con muelle y quiero para inyectar/usar otra clase en la clase de trabajo y no sé cómo hacerlo correctamente¿Cómo usar @Autowired en un trabajo de Quartz?

el 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> 

el cuarzo trabajo:

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 tarea a ejecutar:

package com.mkyong.quartz; 

public class SchedulerTask { 

    public void printSchedulerMessage() { 

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

    } 
} 

Quiero inyectar otra clase de DTO que se ocupe de la Base de datos en la clase de tarea para hacer un trabajo de base de datos en la tarea, ¿cómo hacer eso?

+1

enlace de abajo ha resuelto la solución para mí http://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz-job-in-spring/15211030#17394905 – pathfinder

Respuesta

10

No estoy seguro de si esto es lo que quiere, pero puede pasar algunos valores de configuración al trabajo de Quartz. Creo que en su caso se puede tomar ventaja de la propiedad jobDataAsMap ya ha configurado, por ejemplo:

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

, entonces debería ser capaz de acceder a él en su código Java real de forma manual:

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

O utilizando el enfoque mágico de Spring: tenga la propiedad param1 definida con getter/setter. Usted podría intentar definir con java.lang.Class tipo continuación, y tienen la hace automáticamente (primavera lo haría por ti):

private Class<?> param1; 

// getter & setter 

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

Yo no lo he probado sin embargo.

+0

i desea poder utilizar un objeto DTO y un objeto de dominio en el trabajo de cuarzo, y el autoenrutamiento no funciona aquí, entonces, ¿puede decirme qué hacer entonces? –

+2

En tu pregunta, escribiste que querías usar la clase, no un objeto. De todos modos, ¿cuál es la diferencia entonces? –

+0

En el manual de Quartz dice (como mejor práctica): "Almacene únicamente tipos de datos primitivos en JobDataMap para evitar problemas de serialización de datos a corto y largo plazo". ¿Esta solución realmente funciona bien? Gracias. – aloplop85

14

En su solución, está utilizando la anotación @Autowired de primavera en una clase que Spring no ha creado una instancia. Su solución seguirá funcionando si elimina la anotación @Autowired porque Quartz está configurando la propiedad, no Spring.

Quartz intentará establecer cada clave dentro de JobDataMap como una propiedad. P.ej. ya que tiene una clave "myDao" Quartz buscará un método llamado "setMyDao" y pasará el valor de la clave a ese método.

Si desea primavera para inyectar granos de primavera en sus puestos de trabajo, crear un SpringBeanJobFactory y puso esto en su SchedulerFactoryBean con el jobFactory propiedad dentro de su contexto primavera.

SpringBeanJobFactory javadoc:

Se aplica al contexto planificador, el mapa de datos de empleo y datos de mapa de disparo entradas como propiedad de bean valora

+6

Para aquellos interesados, puede encontrar una implementación 'SpringBeanJobFactory' para autoaumentar automáticamente trabajos de Quartz en esta respuesta (incluye el ejemplo completo): http://stackoverflow.com/a/15211030/787375 – jelies

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

¿Por qué cree que los OP operan en una contexto web? – kolossus

+0

@kolossus, ¿qué otra forma es de hacer esta acción en otro tipo de contextos? – msangel

2

Como se mencionó en inject bean reference into a Quartz job in Spring? se puede usar un muelle 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(); 
     } 
} 

Como se mencionó, puede que no funcione en alguna versión de primavera, pero lo he probado en 4.2.1.RELEASE, que funcionó bien.

+0

No funciona. Spring 4.2.4.RELEASE y Quartz 2.2.1 –

+0

¿Cuál es el error? También ha definido el resorte para escanear automáticamente las anotaciones de frijol. También he probado con Quartz 2.2.2. –

+0

Sí, tengo escaneado de componentes. Dice que WebApplicatinoContext no está disponible, etc. Sin excepción ... pero un mensaje cuando se implementa. –

0

esta es mi solución:

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; 
    } 
} 

continuación config la clase de MySpringBeanJobFactory en el 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> 

Buena suerte! :)

Cuestiones relacionadas