2012-05-29 24 views
5

Estoy trabajando en una aplicación independiente que utiliza tanto JMS como Hibernate.Sincronización de primavera Transacciones de Hibernate y JMS

La documentación sugiere que se debe utilizar JTA si deseo tener transacciones en ambos recursos.

Sin embargo, ahora mismo con un método DAO anotado @Transaction (y HibernateTransactionManager), esto parece funcionar. Cuando llamo send() en JmsTemplate, el mensaje no se envía inmediatamente, sino que la sesión JMS se confirma con la sesión de Hibernate a medida que el método retorna.

No sabía cómo esto es posible sin el JtaTransactionManager, así que revisé el código fuente. Resulta que tanto el contenedor para Hibernate como JmsTemplate registran las sesiones con TransactionSynchronizationManager y la sesión JMS se confirmará cuando la sesión de Hibernate se comprometa.

¿Cuál es la diferencia entre esto y una transacción JTA. ¿Puedo usar esto para reemplazar el último?

+0

¿Comprobó qué sucede cuando una de ellas falla? ¿Los dos retroceden? –

Respuesta

12

En resumen, no se puede obtener soporte para la confirmación en 2 fases sin un JTATransactionManager y fuentes de datos conscientes de XA.

Lo que está presenciando es una coordinación de dos Transacciones locales que admiten el compromiso de una fase solamente. Aproximadamente la realización de esta secuencia de eventos ...

  1. inicio JMS Transacción
  2. Leer JMS mensaje
  3. inicio JDBC Transacción
  4. de escritura a la base de datos
  5. Commit JDBC Transacción
  6. Commit/Reconocimiento JMS

La transacción JMS se iniciará primero wrapp la transacción JDBC anidada, de modo que la cola JMS se revertirá si falla la confirmación de Hibernate/JDBC. Su Contenedor de Escucha JMS debe configurarse no enacknowledge="auto" y en su lugar espere a que se complete la transacción de Hibernate antes de enviar el acuse de recibo.

Si solo tiene estos dos recursos, entonces el problema que deberá tener en cuenta es que cuando Hibernate logra persistir, obtiene una excepción antes de que pueda confirmar el servidor JMS. No es un gran problema ya que el mensaje JMS no se pierde y lo leerá nuevamente.

Sin embargo

  1. usted debe escribir su MessageListener para manejar mensajes duplicados desde el servidor

  2. También debe manejar un mensaje que no puede ser procesado debido a los datos malos y terminar en una bucle infinito de tratar de comsume it.En este caso, el servidor puede ser configurado para mover el mensaje a una "cola de mensajes inactivos", o que lidiar con esto por sí mismo en el MessageListener

Otras opciones y lecturas adicionales

Si sus JMS el servidor no admite transacciones XA (globales) esta es prácticamente la única solución.

Si el servidor JMS admite transacciones XA pero JDBC no, entonces puede usar un JTATransactionManager y usar el LastResourceCommitOptimisation. Hay JTATransactionManagers de código abierto que puede usar como JOTM

This JavaWorld article para obtener más detalles sobre su espacio con problemas.

+0

En un entorno independiente, he utilizado Atomikos con mucho éxito. Un producto bien documentado. –

Cuestiones relacionadas