JTA o Java Transaction API es la encarga de administrar las transacciones del lado del servidor, abstrayendo casi en su totalidad al programador de abrir o cerrar las transacciones, de esta forma el programador únicamente se preocupa por la lógica de negocio aumentando drásticamente la productividad y los errores de Runtime.
JTA es sin duda unas de las API menos conocidas del Estándar de Java, pues si funcionamiento es abstraído casi en la totalidad por el Application Server, sin embargo, no puedo hacer todo el solo, y es necesario conocer cómo funciona y como indicarle a JTA como trabajar con las tracciones.
Lo primero que debemos de saber es que JTA trabajo de la mano con los Enterprise Java Beans (EJB) a partir de la versión 3.0, mediante la unión de EJB + JPA + JTA, es posible crear componentes de negocio súper potentes y lo más interesantes, totalmente transaccionales. Esto quiere decir que todas las operaciones que realicemos en la invocación de un EJB queda envuelto es una transacción, sin importar cuantos EJB se ejecuten en la misma invocación o en varías. Te recomiendo repasar la sección anterior, EntityManager & PersistenceContext ya que te pondrá un poco en contexto sobre los Transaction-Scope.
En la imagen anterior podemos apreciar cómo es que JTA administra las transacciones. El cliente invoca un servicio de negocio, antes de que el Application Server inicie la ejecución del EJB, este abre una transacción, seguido se ejecuta una serie de EJB los cuales pueden hacer múltiples operaciones sobre la base de datos. Cuando la ejecución de todo el flujo termina, el Servidor realiza un Commit y regresa los resultados al cliente.
Cabe mencionar que lo explicaremos a continuación requiere de conocimientos previos de EJB, pues JTA se integra junto con JPA para crear una amalgama perfecta, donde es difícil entender dónde empieza uno y termina el otro. Además, esta no es una guía de EJB por lo que nos detendremos en explicar la teoría de EJB.
Java Transaction API (JTA)
Antes de empezar debemos de dejas claro que JTA solo funciona en ambientes de Java EE, pues es el Application Server quien administra las transacciones a través de JPA. En la siguiente sección hablaremos de cómo administrar las transacciones en Ambientes Java SE, por lo que por ahora lo dejaremos hasta aquí. Para configurar JPA para que utilice JPA, tendremos que regresar al archivo persistence.xml y ajustar la línea:
<persistence-unit name=”JPA_PU” transaction-type=”JTA”>
Si bien JTA administrara las transacciones es importante decirle como, es por eso que aquí entra en juego la anotación @TransactionAttribute , la cual pude ser declarada en cada método de negocio o a nivel de clase. Existen 6 posibles valores, los cuales harán que el EJB Container funcione de forma diferente. Los valores son los siguientes:
- NOT_SUPPORTED: Indica que la operación no soporta transacciones, por lo que, si el método es ejecutado dentro de una transacción, esta se suspende durante la ejecución del método y se restaura una vez finalizado, por lo que todos los cambios realizados en estos métodos no serán persistentes.
- SUPPORTS: Indica que el método soporta transacciones, por lo que sí es ejecutado dentro de una transacción, este se unirá a la misma. Por otro lado, si es ejecutado fuera de una transacción este no creara ninguna transacción y todos los cambios realizados no se persistirán.
- REQUIRES_NEW: Indica que el método requiere forzosamente una nueva transacción para funcionar, por lo que se creará una nueva transacción independientemente de si es ejecutado dentro o fuera de una transacción existente.
- MANDATORY: Estas operaciones deberán ser ejecutadas forzosamente dentro de una transacción existente. En caso contrario se lanzará una Exception de tipo javax.ejb.EJBTransactionRequiredException.
- REQUIRED: Le indicamos que la operación requieres de una transacción, por lo que, si es ejecutado dentro de una transacción existente, este se unirá a la mima. Por otro lado, si no existe una transacción este creará una nueva.
- NEVER: Le indicamos que la operación por ningún motivo deberá ser ejecutado dentro de una transacción existente, ya que lanzará una Exception de tipo javax.ejb.EJBException. Si es ejecutado fuera de una transacción, tampoco creara una nueva.
Cuando @TransactionAttribute es declarada a nivel de clase, afectará a todas las operaciones definidas en el EJB, por otra parte, si es definida a nivel de método, solo afectara al método anotado. Cabe mencionar que se puede combinar definiendo la anotación a nivel de clase y luego en los métodos. El resultado será que la definición a nivel de método sobre escribirá a la de clase.
El siguiente código es un ejemplo rápido de cómo se apreciaría un EJB con la anotación @TransactionAttribute.
@EJB @Stateful @TransactionAttribute(TransactionAttributeType.REQUIRED) public class EmployeeExtendedDAO implements IEmployeeDAO{ @TransactionAttribute(TransactionAttributeType.NEVER) public Employee getEmployeeById(Long empId){ //Se consulta el empleado mediante el ID return manager.find(Employee.class, empId); } }
Podrías pensar que configurar las transacciones es muchos más complicado que solo anotar los métodos, pero la realidad es que tan solo eso es necesario, ya que el Application Server se encargará del resto. No voy a entrar un mucho detalle de cómo utilizarlas, pues tan solo es necesario definir la anotación en la clase o en los métodos, el resto queda del lado de EJB, por lo que dejaremos hasta aquí esta sección. y en la siguiente parte hablaremos de cómo gestionar las transacciones con Java SE.
Excelente material, muy buena la explicación. Se toman los conceptos mas relevantes del tema, se resumen y se muestran de una forma entendible . Te felicito excelente dominio de los temas !
Gracias Juan, te agradezco el comentario y que bueno el material es de utilidad 🙂
Hola sr Oscar Habra alguna forma de bajar en PDF como trabajar con JPA osea este tutorial ?
Hola Edgar, no tengo el contenido en PDF, solo quedaría que lo vieras desde la WEB.
saludos.
Hola de nuevo, Oscar.
Yo tengo una pequeña aplicación que utiliza JPA. Uso Java SE 8 en NetBeans 8.2 y GlassFish 5. No utilizo EJBs, pero si un “ArticulosJPAController.java”, creado por asistente de NetBeans a partir de una tabla y su Entidad correspondiente. En ese JPAController están los métodos CRUD que yo llamo desde otras clases de negocio. Sin embargo, he observado que el código generado en esas operaciones utiliza transacciones de usuario UTX que son iniciadas y paradas con “begin”, “end”, etc. ¿Podría yo cambiar el código y usar JTA?. En el persistence.xml así lo indica, pero parece que no se usa y que se instancia una UserTransaction. Enhorabuena por todos tus contenidos y comentarios.
Hola Pedro,
Las transacciones JTA son gestionadas por el Application Server o el EJB container, pero para eso, debes indicar en el persistence.xml que vas a usar JTA, además, debes de inyectar el EntityManager en lugar de crearlos manualmente, de esta forma, al terminar la operación el servidor commitiará la transacción por tí o ejecutará el rollback en caso de error.