2011-09-09 11 views
6

Ho questo caso d'uso.Integrazione molla: difficoltà con la transazione tra 2 attivatori

prima catena:

<int:chain input-channel="inserimentoCanaleActivate" output-channel="inserimentoCanalePreRouting">  
    <int:service-activator ref="inserimentoCanaleActivator" method="activate" />     
</int:chain> 

Questo è il codice relativo:

@Override 
@Transactional(propagation = Propagation.REQUIRES_NEW) 
public EventMessage<ModificaOperativitaRapporto> activate(EventMessage<InserimentoCanale> eventMessage) { 
    ... 
    // some Database changes 
    dao.save(myObject); 
} 

Tutto sta lavorando molto.

Poi ho un'altra catena:

<int:chain id="onlineCensimentoClienteChain" input-channel="ONLINE_CENSIMENTO_CLIENTE" output-channel="inserimentoCanaleActivate"> 
    <int:service-activator ref="onlineCensimentoClienteActivator" method="activate" /> 
    <int:splitter expression="payload.getPayload().getCanali()" /> 
</int:chain> 

E il relativo attivatore:

@Override 
public EventMessage<CensimentoCliente> activate(EventMessage<CensimentoCliente> eventMessage) { 
    ... 
    // some Database changes 
    dao.save(myObject); 
} 

Il CensimentoCliente payload come descritto qui di seguito un List di payload della prima catena, quindi con uno splitter I diviso sulla lista e riutilizzare il codice della prima catena.

public interface CensimentoCliente extends Serializable { 

    Collection<? extends InserimentoCanale> getCanali(); 

    void setCanali(Collection<? extends InserimentoCanale> canali); 
    ... 
} 

Ma dato che ogni attivatore ottiene la sua definizione di transazione (dal momento che il primo può vivere senza il secondo) Ho un caso d'uso in cui vengono separate le transazioni.

L'obiettivo è far sì che le modifiche del db delle due catene siano state parte della stessa transazione.

Qualsiasi aiuto?

Cordiali saluti Massimo

+0

Hai mai trovato una soluzione? – dMcNavish

+0

No ........... –

risposta

0

Sono queste modificano 2 database relazionali separati? Se è così, stai guardando una transazione XA. Ora se si sta eseguendo questo in un contenitore non XA come tomcat, tutto ciò deve essere fatto in un singolo thread che viene guardato da un gestore transazioni - (si dovrà fare affidamento sul gestore transazioni che attiva effettivamente questi eventi). Il gestore delle transazioni può essere un messaggio JMS o un polling contro una determinata origine dati. Anche questa elaborazione deve essere eseguita in un singolo thread in modo che Spring possa aiutarti a eseguire l'intero processo in un'unica transazione.

Come nota finale, non introdurre threadpool/code tra attivatori di servizi. Ciò può causare gli attivatori per l'esecuzione in thread separati

3

È possibile realizzare questo con la creazione di un canale personalizzato (o altro componente personalizzato, ma questo è l'approccio più semplice) che avvolge il messaggio di spedizione in un'esecuzione TransactionTemplate callback:

public class TransactionalChannel extends AbstractSubscribableChannel { 

    private final MessageDispatcher dispatcher = new UnicastingDispatcher(); 
    private final TransactionTemplate transactionTemplate; 

    TransactionalChannel(TransactionTemplate transactionTemplate) { 
     this.transactionTemplate = transactionTemplate; 
    } 

    @Override 
    protected boolean doSend(final Message<?> message, long timeout) { 
     return transactionTemplate.execute(new TransactionCallback<Boolean>() { 
      @Override 
      public Boolean doInTransaction(TransactionStatus status) { 
       return getDispatcher().dispatch(message); 
      } 
     }); 
    } 

    @Override 
    protected MessageDispatcher getDispatcher() { 
     return dispatcher; 
    } 

} 

Nel vostro XML, è possibile definire il modello di canale e la transazione e fare riferimento il vostro canale personalizzato proprio come si farebbe con qualsiasi altro canale:

<bean id="transactionalChannel" class="com.stackoverflow.TransactionalChannel"> 
     <constructor-arg> 
      <bean class="org.springframework.transaction.support.TransactionTemplate"> 
       <property name="transactionManager" ref="transactionManager"/> 
       <property name="propagationBehavior" value="#{T(org.springframework.transaction.TransactionDefinition).PROPAGATION_REQUIRES_NEW}"/> 
      </bean> 
     </constructor-arg> 
    </bean> 

per esempio, si potrebbe forse usare un ponte per passare t egli messaggio attraverso il nuovo canale:

<int:bridge input-channel="inserimentoCanaleActivate" output-channel="transactionalChannel" /> 
<int:chain input-channel="transactionalChannel" output-channel="inserimentoCanalePreRouting">  
    <int:service-activator ref="inserimentoCanaleActivator" method="activate" />     
</int:chain> 
2

È avete <service-activator> e @Transactional sul metodo di servizio, la transazione sarà delimitate solo a quella chiamata di metodo. Se si desidera avere una trascrizione per l'intero flusso di messaggi (o la sua parte), è necessario dichiarare un avviso TX da qualche parte prima. Se i canali sono diretti, tutte le chiamate di servizio verranno completate con la stessa transazione. Il modo più semplice per realizzare i tuoi desideri, scrivi un'interfaccia semplice @Gateway con @Transactional e chiamalo dall'inizio del flusso di messaggi.

Per chiarire un po 'per quanto riguarda le transazioni Understanding Transactions in Message flows

+0

potresti pubblicare o collegare qualche esempio di codice? Sto avendo lo stesso problema. Grazie! –

+0

Ho aggiunto alla mia risposta un link su TX in SI –

+0

Ho letto questo documento prima e ho ancora dei dubbi. Ho pubblicato il mio caso in http://stackoverflow.com/questions/18901510/keep-transaction-within-spring-integration-flow –

Problemi correlati