2012-07-19 9 views
7

que tienen un flujo de primavera integración desencadenada por la expresión de cron como sigue:integración de primavera + cron + cuarzo en el clúster?

<int-ftp:inbound-channel-adapter id="my-input-endpoint" ...> 
    <int:poller trigger="my-trigger"/> 
</int-ftp:inbound-channel-adapter> 

<bean id="my-trigger" 
    class="org.springframework.scheduling.support.CronTrigger"> 
    <constructor-arg value="0 * * * * *" /> 
</bean> 

Trabaja muy bien. Pero ahora tengo que extender la implementación para que esté lista para el clúster (ejecución del trabajo en solo un nodo del clúster en el mismo punto de tiempo).

Mi deseo sería utilizar el marco de Quartz en el modo de clúster (persistiendo el estado del trabajo en la base de datos) para desencadenar este flujo de integración. Quartz proporciona una solución preciosa lista para usar. El único problema es cómo integrar el Cuarzo con el adaptador in-channer existente? El atributo "desencadenar" del "sondeador" acepta solo las subclases de org.springframework.scheduling.Trigger. No pude encontrar ningún puente entre el "disparador de sondeo" y el marco de Quartz.

muchas gracias de antemano!

Respuesta

6

Ésta es una forma ...

Establecer el atributo de inicio automático en la entrada del adaptador a falso.

crear un disparador a medida que sólo se activa una vez, inmediatamente ...

public static class FireOnceTrigger implements Trigger { 

    boolean done; 

    public Date nextExecutionTime(TriggerContext triggerContext) { 
     if (done) { 
      return null; 
     } 
     done = true; 
     return new Date(); 
    } 

    public void reset() { 
     done = false; 
    } 
} 

En su trabajo de cuarzo, obtener una referencia al gatillo y la SourcePollingChannelAdapter.

Cuando se dispara el gatillo de cuarzo, tienen la tarea de cuarzo

  1. adapter.stop()
  2. trigger.reset()
  3. adapter.start()
+0

En caso de que alguien se tropiece con esto, la implementación de la solución de Gary, junto con una prueba para demostrar el uso, se puede encontrar en [este informe] (https://github.com/vpavic/spring-integration-quartz -puente). –

0

tratado de integrar el cuarzo y la primavera como usted propuso, pero se enfrentaron a otros dos problemas:

1.) IncompatibleClassChangeError excepción cuando se usa Quartz 2.x y Spring 3.x. Es un problema conocido, pero no encontré ninguna solución para eso.

2.) Inyección de otro grano de primavera en la instancia de trabajo de Quarz. Encontré algunas soluciones, pero nadie funciona para mí. He probado el uno con el uso de

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
    <property name="jobFactory"> 
     <bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" /> 
    </property> 

    <property name="triggers"> 
     ... 
    </property> 

    <property name="schedulerContextAsMap"> 
     <map> 
      <entry key="inputEndpoint" value-ref="my-endpoint" /> 
     </map> 
    </property> 
</bean> 

para inyectar otros granos en el trabajo, pero después de añadir esta propiedad en el SchedulerFactoryBean no se está ejecutando los trabajos (y no veo ninguna excepción). Al eliminar la propiedad "schedulerContextAsMap", el trabajo se ejecuta nuevamente.

+0

solución temporal para el problema 1) degradación del cuarzo a v1.8.5 2) mi observación: si hay alguna excepción durante la inyección de beans desde el contexto al trabajo utilizando el método "schedulerContextAsMap" (como ClassCastException) no hay excepción lanzado por Spring framework y no se registra ningún error. El trabajo simplemente no se inició. En mi caso, esperaba que la clase del punto final de entrada inyectado fuese FtpInboundFileSynchronizingMessageSource, pero el objeto inyectado es del tipo SourcePollingChannelAdapter. – marc7

+0

Sí, lo siento, mi error tipográfico, corregido. –

2

la solución de Gary funciona.Este contexto mi primavera:

<int-ftp:inbound-channel-adapter id="my-endpoint" 
     auto-startup="false"> 
    <int:poller trigger="my-endpoint-trigger"/> 
</int-ftp:inbound-channel-adapter> 


<bean id="my-endpoint-trigger" class="com.my.FireOnceTrigger"/> 

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 

    <property name="triggers"> 
     <list> 
      <ref bean="my-job-trigger" /> 
     </list> 
    </property> 

    <property name="schedulerContextAsMap"> 
     <map> 
      <entry key="inputEndpoint"><ref bean="my-input-endpoint" /></entry> 
      <entry key="inputEndpointTrigger"><ref bean="my-endpoint-trigger" /></entry> 
     </map> 
    </property> 
</bean> 

<bean id="my-job-trigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> 
    <property name="cronExpression" value="0 * * * * ?" /> 
    <property name="jobDetail" ref="my-job" /> 
</bean> 

<bean name="my-job" class="org.springframework.scheduling.quartz.JobDetailBean"> 
    <property name="jobClass" value="com.my.MyActivatorJob " /> 
</bean> 

y la clase MyActivatorJob:

public class MyActivatorJob extends QuartzJobBean implements { 

private AbstractEndpoint inputEndpoint; 

private FireOnceTrigger inputEndpointTrigger; 

public void setInputEndpoint(final AbstractEndpoint pInputEndpoint) { 
    this.inputEndpoint = pInputEndpoint; 
} 

public void setInputEndpointTrigger(final FireOnceTrigger pInputEndpointTrigger) { 
    this.inputEndpointTrigger = pInputEndpointTrigger; 
} 

@Override 
protected void executeInternal(final JobExecutionContext pParamJobExecutionContext) 
throws JobExecutionException { 

    inputEndpoint.stop(); 
    inputEndpointTrigger.reset(); 
    inputEndpoint.start(); 
} 

}

Como siguiente paso de este contexto la primavera tendría que ser reprogramado para reemplazar el uso de schedulerContextAsMap con algo más flexible y poder definir más trabajos activando y desactivando muchos puntos finales diferentes.

¡Gracias Gary hasta ahora!

+0

BTW, para cualquiera que tropiece con esto: Quartz 2 funciona con Spring 3, siga este enlace: http://stackoverflow.com/a/9866152/767530 –

Cuestiones relacionadas