La gestión programática de transacciones normalmente solo puede ser una buena idea si tiene una pequeña cantidad de actividades transaccionales. Por ejemplo, si tiene una aplicación web que solo requiere transacciones para ciertas operaciones de actualización, es posible que no necesite configurar servidores proxy de transacciones usando Spring o cualquier otra tecnología. En este caso, el enfoque que utiliza TransactionTemplate puede ser bueno. La capacidad de especificar explícitamente un nombre de transacción solo está disponible cuando se utiliza un enfoque programático para la gestión de transacciones.

Por otro lado, si su aplicación tiene muchas actividades transaccionales, la gestión de transacciones declarativas suele tener sentido. No incluye gestión de transacciones en la lógica empresarial y no es difícil de configurar. Al utilizar Spring Framework en lugar de CMT de EJB, el costo de la configuración de gestión de transacciones declarativas se reduce significativamente.

Eventos dentro de los límites de la transacción

A partir de Spring 4.2, un detector de eventos se puede vincular a una fase de transacción. Un ejemplo típico es el manejo de un evento cuando una transacción se completa exitosamente. Esto le permite utilizar eventos de manera más flexible si el resultado de la transacción actual es realmente importante para el oyente.

Puede registrar un detector de eventos normal utilizando la anotación @EventListener. Si necesita vincularlo a una transacción, utilice la anotación @TransactionalEventListener. El oyente predeterminado se vinculará a la fase de confirmación de la transacción.

El siguiente ejemplo demuestra este concepto. Supongamos que un componente publica un evento que se genera en un orden específico y necesitamos definir un oyente que solo debe procesar ese evento después de que la transacción en la que se publicó se haya confirmado con éxito. El siguiente ejemplo configura un detector de eventos como este:

Java
@Component
public class MyComponent {
    @TransactionalEventListener
    public void handleOrderCreatedEvent(CreationEvent<Order> creationEvent) {
        // ...
    }
}
Kotlin
@Component
class MyComponent {
    @TransactionalEventListener
    fun handleOrderCreatedEvent(creationEvent: CreationEvent<Order>) {
        // ...
    }
}

La anotación @TransactionalEventListener expone el atributo phase, que le permite configurar la fase de transacción a la que debe estar vinculado el oyente. Las fases válidas son BEFORE_COMMIT, AFTER_COMMIT (predeterminada), AFTER_ROLLBACK y AFTER_COMPLETION, que combinan la finalización de la transacción. (ya sea confirmación o reversión).

Si la transacción falla, no se llama al oyente porque no podemos mantener la semántica requerida. Sin embargo, puede anular esta lógica estableciendo el atributo fallbackExecution de la anotación en true.

La anotación

@TransactionalEventListener solo funciona con transacciones vinculadas a subprocesos administradas por PlatformTransactionManager. Una transacción reactiva administrada por un ReactiveTransactionManager utiliza el contexto del Reactor en lugar de atributos locales del hilo, por lo que desde el punto de vista del detector de eventos no existe ninguna transacción activa compatible en la que pueda participar.

Integración con el servidor de aplicaciones

La abstracción de transacciones de Spring es generalmente independiente del servidor de aplicaciones. Además, la clase JtaTransactionManager de Spring (que opcionalmente puede buscar objetos UserTransaction y TransactionManager de JTA a través de JNDI) determina automáticamente la ubicación del último objeto que depende del servidor de aplicaciones. Tener acceso a TransactionManager desde JTA le permite ampliar la semántica de las transacciones; en particular, admitir la suspensión de transacciones. Para obtener más información, consulte el javadoc en JtaTransactionManager.

JtaTransactionManager de Spring es la forma típica de ejecutarse en servidores de aplicaciones Java EE y se sabe que funciona en todos los servidores comunes. La funcionalidad avanzada, como la suspensión de transacciones, también funciona en muchos servidores (incluidos GlassFish, JBoss y Geronimo) sin necesidad de una configuración especial. Sin embargo, para admitir completamente la suspensión de transacciones y una mayor integración avanzada, Spring incluye adaptadores especiales para WebLogic Server y WebSphere. Estos adaptadores se describen en las siguientes secciones.

Para escenarios estándar, incluidos WebLogic Server y WebSphere, utilice el elemento auxiliar de configuración <tx:jta-transaction-manager/>. Cuando se configura, este elemento detecta automáticamente el servidor principal y selecciona el mejor administrador de transacciones disponible para la plataforma. Esto significa que no es necesario configurar explícitamente clases de adaptadores específicas del servidor (como se describe en las siguientes secciones). Más bien, se seleccionan automáticamente, siendo el JtaTransactionManager estándar la opción de devolución predeterminada.

WebSphere de IBM

En WebSphere 6.1.0.9 y posteriores, el administrador de transacciones JTA recomendado en Spring es WebSphereUowTransactionManager. Este adaptador personalizado utiliza la API UOWManager de IBM, que está disponible en WebSphere Application Server 6.1.0.9 y posteriores. Con este adaptador, IBM admite oficialmente la suspensión de transacciones administradas por Spring (suspensión y reanudación iniciadas por PROPAGATION_REQUIRES_NEW).

Servidor WebLogic de Oracle

En WebLogic Server 9.0 o superior, es común usar WebLogicJtaTransactionManager en lugar de la clase estándar JtaTransactionManager. Esta subclase especial específica de WebLogic del JtaTransactionManager normal admite todas las funciones de las definiciones de transacciones Spring en un entorno de transacciones administrado por WebLogic, además de la semántica JTA estándar. Las características incluyen nombres de transacciones, niveles de aislamiento para cada transacción y cómo reanudar correctamente las transacciones en todos los casos.

Resolver problemas comunes

Esta sección describe soluciones a algunos problemas comunes.

Usar el administrador de transacciones incorrecto para un DataSource

específico

Utilice la implementación de PlatformTransactionManager correcta según sus opciones y requisitos de tecnología de transacciones. Cuando se usa correctamente, Spring Framework proporciona una abstracción simple y portátil. Si se utilizan transacciones globales, entonces necesita usar la clase org.springframework.transaction.jta.Jta.JtaTransactionManager (o su subclase específica del servidor de aplicaciones) para todas las operaciones transaccionales. De lo contrario, el marco de transacciones intentará realizar transacciones locales en recursos como instancias DataSource en contenedores. Estas transacciones locales no tienen significado y un servidor de aplicaciones que funcione correctamente las considera errores.

Fuentes adicionales

Para obtener más información sobre el soporte de transacciones en Spring Framework, consulte:

  • Transacciones distribuidas en Spring, con y sin XA es una presentación de JavaWorld en la que David Sayer de Spring le presenta siete patrones para transacciones distribuidas en aplicaciones Spring, tres con XA y cuatro sin XA.

  • Estrategias de diseño de transacciones Java es un libro disponible en InfoQ, que proporciona una introducción bien fundamentada a las transacciones de Java. También proporciona ejemplos paralelos de configuración y uso de transacciones tanto en Spring Framework como en EJB3.