2012-05-29 8 views
5

Sto lavorando su un'applicazione standalone che utilizza sia JMS che Hibernate.Sincronizzazione molla Operazioni Hibernate e JMS

La documentazione suggerisce che JTA deve essere utilizzato se voglio avere transazioni su entrambe le risorse.

Tuttavia, al momento con un metodo DAO annotato @Transaction (e HibernateTransactionManager), questo sembra già funzionare. Quando chiamo send() su JmsTemplate, il messaggio non viene inviato immediatamente, ma la sessione JMS viene impegnata con la sessione di Hibernate al ritorno del metodo.

Non sapevo come fosse possibile senza JtaTransactionManager, quindi ho controllato il codice sorgente. Risulta che sia il wrapper per Hibernate che JmsTemplate registra le sessioni con TransactionSynchronizationManager e la sessione JMS verrà impegnata quando si esegue la sessione di Hibernate.

Qual è il diverso tra questa e una transazione JTA. Posso usare questo per sostituire il secondo ??

+0

Hai controllato cosa succede quando uno di loro fallisce? Entrambi rollback? –

risposta

12

In breve no, non è possibile ottenere il supporto per il commit a 2 fasi senza un data source JTATransactionManager e XA.

Quello a cui si sta assistendo è un coordinamento di due Transazioni locali che supporta solo il commit monofase. Circa l'esecuzione di questa sequenza di eventi ...

  1. Inizio JMS Transaction
  2. Leggi JMS messaggio
  3. Inizio JDBC Transaction
  4. scrittura al database
  5. Commit Transaction JDBC
  6. Commit/Riconoscimento JMS

La transazione JMS verrà avviata per prima cosa la transazione JDBC nidificata, in modo che la coda JMS esegua il rollback se il commit Hibernate/JDBC ha esito negativo. Il contenitore del listener JMS deve essere impostato su non suacknowledge="auto" e attendere che la transazione di Hibernate sia completata prima di inviare il riconoscimento.

Se si dispone solo di queste due risorse, il problema che si dovrà considerare è quando Hibernate riesce a continuare a ricevere un'eccezione prima di poter riconoscere il server JMS. Non è un grosso problema in quanto il messaggio JMS non è perso e lo leggerete di nuovo.

Tuttavia

  1. È necessario scrivere il MessageListener per gestire i messaggi duplicati dal server

  2. È inoltre necessario gestire un messaggio che non può essere elaborato a causa di dati danneggiati e finire in un ciclo infinito di provare a farlo.In questo caso il server può essere configurato per spostare il messaggio in una "coda di messaggi morto", o si affronta da soli nel MessageListener

Altre opzioni e ulteriori letture

Se i JMS il server non supporta transazioni XA (globali), questa è praticamente l'unica soluzione.

Se il server JMS supporta le transazioni XA ma JDBC non funziona, è possibile utilizzare un JTATransactionManager e utilizzare LastResourceCommitOptimisation. Ci sono open source JTATransactionManagers che puoi utilizzare come JOTM

This JavaWorld article entra nel dettaglio del tuo spazio problematico.

+0

In un ambiente standalone ho usato Atomikos con molto successo. Un prodotto ben documentato. –