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:
@Component
public class MyComponent {
@TransactionalEventListener
public void handleOrderCreatedEvent(CreationEvent<Order> creationEvent) {
// ...
}
}
@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
.
@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.