2012-07-19 15 views
7

Ho un flusso integrazione primavera innescata dalla espressione cron come segue:integrazione molla + cron + quarzo nel cluster?

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

Funziona benissimo. Ma ora devo estendere l'implementazione per renderla pronta per il cluster (esecuzione di un lavoro su un solo nodo di cluster nello stesso momento).

Il mio desiderio sarebbe quello di utilizzare il framework Quartz in modalità cluster (mantenendo lo stato del lavoro nel database) per attivare questo flusso di integrazione. Il quarzo fornisce una bella soluzione fuori dalla scatola. L'unico problema è come integrare il quarzo con l'adattatore inbout-channer esistente? L'attributo "trigger" del "poller" accetta solo le sottoclassi di org.springframework.scheduling.Trigger. Non sono riuscito a trovare alcun ponte tra "trigger del poller" e il framework Quartz.

molte grazie in anticipo!

risposta

6

Ecco un modo ...

Impostare l'attributo di auto-avvio sul inbound-adattatore per falso.

creare un trigger personalizzato che spara solo una volta, subito ...

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

Nel vostro lavoro di quarzo, ottenere un riferimento il grilletto e il SourcePollingChannelAdapter.

Quando i fuochi di innesco di quarzo, hanno il compito di quarzo

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

Nel caso in cui qualcuno si imbatta in questo - l'implementazione della soluzione di Gary, insieme a un test per dimostrare l'uso, può essere trovato in [questo repo] (https://github.com/vpavic/spring-integration-quartz -ponte). –

0

cercato di integrare il quarzo e la molla come hai proposto, ma ha affrontato altri due problemi:

1.) Eccezione IncompatibleClassChangeError quando si utilizza Quartz 2.xe Spring 3.x. È un problema noto ma non ho trovato alcuna soluzione per questo.

2.) Iniezione di altri bean a molla nell'istanza di lavoro Quarz. Ho trovato alcune soluzioni ma nessuno lavora per me. Ho provato quello con l'utilizzo di

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

per iniettare altri bean nel lavoro, ma dopo l'aggiunta di questa proprietà nel SchedulerFactoryBean i posti di lavoro non è in corso di esecuzione (e non vedo alcuna eccezione). Rimuovendo la proprietà "schedulerContextAsMap" si riattiva il lavoro.

+0

temprary soluzione per problema 1) downgrade del quarzo a v1.8.5 2) la mia osservazione: se c'è qualche eccezione durante l'iniezione di bean dal contesto al lavoro usando il metodo "schedulerContextAsMap" (come ClassCastException) non c'è eccezione generata da Spring framework e nessun errore registrato. Il lavoro non è appena iniziato. Nel mio caso mi aspetto che la classe dell'endpoint input immesso sia FtpInboundFileSynchronizingMessageSource, ma l'oggetto iniettato è del tipo SourcePollingChannelAdapter. – marc7

+0

Sì, scusate il mio errore di battitura - risolto. –

2

la soluzione di Gary funziona.Questo contesto la mia 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> 

e la classe 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(); 
} 

}

Come passo successivo questo contesto la primavera dovrebbe essere riscritta per sostituire l'uso di schedulerContextAsMap con qualcosa di più flessibile e in grado di definire più lavori attivando e disattivando molti endpoint diversi.

Grazie Gary finora!

+0

BTW, per chi si imbatte in questo: Quartz 2 funziona con Spring 3, segui questo link: http://stackoverflow.com/a/9866152/767530 –

Problemi correlati