Jakarta Transactions ( JTA ; anteriormente Java Transaction API ), una de las API de Jakarta EE , permite realizar transacciones distribuidas en múltiples recursos X/Open XA en un entorno Java . JTA fue una especificación desarrollada en el marco del Java Community Process como JSR 907. JTA prevé:
En la arquitectura X/Open XA, un administrador de transacciones o un monitor de procesamiento de transacciones (monitor de TP) coordina las transacciones entre múltiples recursos, como bases de datos y colas de mensajes. Cada recurso tiene su propio administrador de recursos. El administrador de recursos normalmente tiene su propia API para manipular el recurso, por ejemplo, la API JDBC para trabajar con bases de datos relacionales. Además, el administrador de recursos permite que un monitor de TP coordine una transacción distribuida entre su propio administrador de recursos y otros administradores de recursos. Por último, está la aplicación que se comunica con el monitor de TP para iniciar, confirmar o revertir las transacciones. La aplicación también se comunica con los recursos individuales utilizando su propia API para modificar el recurso.
La API JTA consta de clases en dos paquetes Java :
javax.transaction
javax.transaction.xa
JTA está modelado sobre la arquitectura X/Open XA, pero define dos API diferentes para delimitar los límites de las transacciones. Distingue entre un servidor de aplicaciones , como un servidor EJB, y un componente de aplicación. Proporciona una interfaz, javax.transaction.TransactionManager
, que es utilizada por el propio servidor de aplicaciones para iniciar, confirmar y revertir las transacciones. Proporciona una interfaz diferente, , javax.transaction.UserTransaction
que es utilizada por el código de cliente general, como un servlet o un EJB, para administrar las transacciones.
La arquitectura JTA requiere que cada administrador de recursos implemente la javax.transaction.xa.XAResource
interfaz para que el monitor de TP pueda administrarlo. Como se mencionó anteriormente, cada recurso tendrá su propia API específica, por ejemplo:
La API de transacciones de Jakarta consta de tres elementos: una interfaz de demarcación de transacciones de aplicaciones de alto nivel, una interfaz de administrador de transacciones de alto nivel destinada a un servidor de aplicaciones y un mapeo Java estándar del protocolo X/Open XA destinado a un administrador de recursos transaccionales.
La javax.transaction.UserTransaction
interfaz proporciona a la aplicación la capacidad de controlar los límites de las transacciones mediante programación. Esta interfaz puede ser utilizada por programas cliente Java o beans EJB.
El UserTransaction.begin()
método inicia una transacción global y asocia la transacción con el subproceso que la llama. El administrador de transacciones administra de forma transparente la asociación entre la transacción y el subproceso.
No se requiere compatibilidad con transacciones anidadas. El método UserTransaction.begin genera la excepción NotSupportedException cuando el subproceso que realiza la llamada ya está asociado con una transacción y la implementación del administrador de transacciones no admite transacciones anidadas.
La propagación del contexto de transacción entre programas de aplicación se realiza mediante las implementaciones del administrador de transacciones subyacente en las máquinas cliente y servidor. El formato del contexto de transacción utilizado para la propagación depende del protocolo y debe negociarse entre los hosts cliente y servidor. Por ejemplo, si el administrador de transacciones es una implementación de la especificación JTS , utilizará el formato de propagación del contexto de transacción tal como se especifica en la especificación CORBA OTS 1.1. La propagación de transacciones es transparente para los programas de aplicación.
La javax.transaction.Transactional
anotación proporciona a la aplicación la capacidad de controlar los límites de las transacciones de forma declarativa. Esta anotación se puede aplicar a cualquier clase que la especificación Jakarta EE defina como un bean administrado (que incluye los beans administrados de CDI).
El siguiente ejemplo de código ilustra el uso de @Transactional
un bean administrado por CDI con ámbito de solicitud:
@RequestScoped clase pública ExampleBean { @Transactional public void foo () { // Una transacción está activa aquí // Hacer el trabajo } // Después de que el método retorna, la transacción se confirma o se revierte }
El comportamiento transaccional se puede configurar mediante un atributo en la anotación. Las opciones disponibles reflejan fielmente las de la especificación EJB .
La javax.transaction.TransactionScoped
anotación proporciona a la aplicación la capacidad de declarar que el ámbito durante el cual vive un bean está vinculado al tiempo en que una transacción determinada está activa.
El siguiente ejemplo de código ilustra el uso de @TransactionScoped
un bean administrado por CDI con ámbito de solicitud:
@TransactionScoped clase pública TxScopedBean { int público número ; public int getNumber ( ) { return numero ;} public void setNumber ( int numero ) { this.number = numero ; } } @RequestScoped clase pública ExampleBean { @Inject privado TxScopedBean txScopedBean ; @Transactional public void foo () { txScopedBean . setNumber ( 1 ); } @Transactional public void bar ( ) { System.out.print ( tXscopedBean.getNumber ( ) ) ; } }
Si primero se llama al método foo() en una instancia administrada de ExampleBean y luego se llama al método bar() , el número impreso será 0 y no 1. Esto se debe a que cada método tenía su propia transacción y, por lo tanto, su propia instancia de TxScopedBean. Por lo tanto, el número 1 que se estableció durante la llamada a foo() no se verá durante la llamada a bar() .
Los servidores EJB deben admitir la UserTransaction
interfaz para que la utilicen los beans EJB con el valor BEAN en la javax.ejb.TransactionManagement
anotación (esto se denomina transacciones administradas por bean o BMT). La UserTransaction
interfaz se expone a los componentes EJB a través de la EJBContext
interfaz mediante el getUserTransaction
método o directamente mediante inyección mediante la @Resource
anotación general. Por lo tanto, una aplicación EJB no interactúa con el administrador de transacciones directamente para la demarcación de transacciones; en cambio, el bean EJB depende del servidor EJB para brindar soporte para todo su trabajo de transacciones, tal como se define en la especificación Jakarta Enterprise Beans. (La interacción subyacente entre el servidor EJB y la TM es transparente para la aplicación; la carga de implementar la administración de transacciones recae en el contenedor EJB y el proveedor del servidor. [1] )
El siguiente ejemplo de código ilustra el uso de UserTransaction
transacciones administradas por bean en un bean de sesión EJB:
@Stateless @TransactionManagement ( BEAN ) clase pública ExampleBean { @Resource transacción de usuario privada utx ; public void foo () { // iniciar una transacción utx.begin (); // Hacer el trabajo // Confirmarlo utx . commit (); } }
Alternativamente, UserTransaction
se puede obtener de SessionContext
:
@Stateless @TransactionManagement ( BEAN ) clase pública ExampleBean { @Resource privado SessionContext ctx ; público void foo () { TransacciónUsuario utx = ctx.getTransacciónUsuario ( ) ; // iniciar una transacción utx .begin (); // Hacer el trabajo // Confirmarlo utx . commit (); } }
Sin embargo, tenga en cuenta que en el ejemplo anterior, si @TransactionManagement(BEAN)
se omite la anotación, se inicia automáticamente una transacción JTA cada vez que foo()
se llama y se confirma o revierte automáticamente cuando foo()
se sale de ella. Por lo tanto, no es necesario utilizar a UserTransaction
en la programación EJB, pero puede ser necesario para un código muy especializado.
La UserTransaction debe estar disponible en java:comp/UserTransaction
(si hay una implementación JTA instalada en el entorno).