2012-02-10 13 views
13

Tengo una aplicación web de primavera que se ejecuta en jboss que está configurada actualmente para usar HibernateTransactionManager para transacciones de db y JmsTransactionManager para jms. Para jms usamos Camel y ActiveMQ, nuestra base de datos es DB2. Dentro de una transacción, debo escribir una cantidad de registros en la base de datos y enviar dos mensajes jms asíncronos. Los mensajes jms son notificaciones de eventos y solo deseo que se envíen si la transacción de la base de datos se confirma.Sincronización de transacciones de primavera de JDBC y JMS

Estoy dispuesto a aceptar el riesgo de que la comunicación con el intermediario falle después de que la transacción jdbc ya se haya comprometido (y por lo tanto no se envíen mensajes pero se haya comprometido el db), así que no creo que necesite el XA adecuado.

Creo que lo que necesito es una gestión de transacciones de "mejores esfuerzos" utilizando la sincronización de transacciones de primavera.

La documentación de los muelles insinúa que la primavera sincronizará las dos transacciones y comprometerá la transacción jms solo después de que se haya confirmado la transacción jdbc, pero no creo que sea muy clara. La documentación de primavera aquí http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#tx-resource-synchronization no entra en detalles suficientes sobre cómo funciona.

He encontrado un par de otras fuentes que dicen que Spring hará lo que yo quiero, incluyendo algunos javadoc a continuación, y he escrito algunas pruebas de integración que también lo muestran.

http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/jms/support/JmsAccessor.html#setSessionTransacted%28boolean%29 El javadoc en setSessionTransacted aquí parece exactamente lo que quiero.

Por lo que he visto creo que la creación del camello JmsConfiguration con tramitado establecido en true como esto es suficiente:

<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration"> 
    <property name="connectionFactory" ref="pooledConnectionFactory"/> 
    <property name="transacted" value="true"/> 
    <property name="concurrentConsumers" value="10"/> 
</bean> 

Sin embargo tengo que convencer a alguien que trabajo que es un poco escéptico y piensa que mi la prueba de integración solo funciona debido a un efecto secundario mal documentado en lugar de una característica de primavera intencional.

Así que mi pregunta es: ¿estoy seguro de que la primavera se puede confiar para sincronizar las transacciones y siempre confirmar la transacción jms después de la transacción jdbc o no es algo en lo que debería confiar, y podría señalarme a cualquier documentación oficial que dice eso claramente? Y creo que, en general, ¿es este un buen enfoque para tomar o deberíamos administrar estas transacciones de una manera diferente?

+0

Hola, ¿ya tienes una respuesta a tu pregunta? – snowindy

+0

Hola, no realmente. Todavía no he visto ninguna documentación realmente clara, que es lo que quería, pero ahora la estamos utilizando en producción sin ningún problema. – laurie

Respuesta

3

Este artículo podría ser de ayuda Distributed transactions in Spring, with and without XA. No creo que cubra tu caso específicamente: envío de mensajes + actualización de la base de datos.

+0

Gracias, he leído ese artículo un par de veces.En la sección Mejores Esfuerzos 1PC, proporcionan dos ejemplos de sincronización de primavera, pero en uno configuran un TransactionAwareConnectionFactoryProxy y en el otro un ChainedTransactionManager. Si no necesito hacer ninguna configuración adicional para obtener el mismo resultado, preferiría no hacerlo. – laurie

0

Si está utilizando transacciones locales Y el caso de uso es guardar en la base de datos y luego enviar a JMS

entonces podría haber tres casos:

  1. Excepción justo después de recibir (antes de DB y JMS)

No hay problema todo va a ser retrotraído

  1. Después de salvar a DB, tenemos una excepción

Si hay una operación de inserción, habrá mutiple filas en el PP debido a retries.With cada reintento, una inserción será done.And para JMS, mensaje irá a DeadLetterQueue

  1. Después de salvar a DB y el envío de JMS, tenemos una excepción

    Si hay una operación de inserción, habrá mutiple filas en el PP debido a retries.With cada reintento, se llevará a cabo una inserción. y para JMS, el mensaje irá a DeadLetterQueue

Ahora usted no desea utilizar XA, por lo que las soluciones podría ser

1) comprobar si (desorden age.getJmsRedelivered() {...}

Si no es así, procesarla

Si su entregado de nuevo, compruebe si procesado ya

Comprobar si los datos están en la base de datos sobre la base de datos en el mensaje

Tenga en cuenta que re-entregas son raros así, esta comprobación también es raro y no hay ninguna sobrecarga

2) Si el método es idempotente, entonces usted no necesita esta comprobación

Y con respecto a XA, XA garantiza que el mensaje se entrega una sola vez y sincronizar la transacción a través de múltiples recursos

Pero con XA, que tiene sobrecarga

Así que si usted puede manejar sin XA, es preferible

Cuestiones relacionadas