java - JEE7: ¿Los beans EJB y CDI admiten transacciones gestionadas por contenedor?
java-ee jta (2)
Java EE7 consiste en un montón de definiciones de "bean":
- Frijoles gestionados 1.0 (JSR-316 / JSR-250)
- Inyección de dependencia para Java 1.0 (JSR-330)
- CDI 1.1 (JSR-346)
- JSF Managed Beans 2.2 (JSR-344)
- EJB 3.2 (JSR-345)
Para deshacerme del caos en mi mente, estudio varios artículos de "cuándo usar qué tipo de frijol". Una de las ventajas de EJB parece ser que solo son compatibles con las transacciones declarativas administradas por contenedor (las famosas anotaciones de transacción). No estoy seguro, sin embargo, si esto es correcto. ¿Alguien puede aprobar esto?
Mientras tanto, se me ocurrió una aplicación de demostración simple para comprobar si esto era realmente cierto. Acabo de definir un bean CDI ( no un EJB, no tiene anotaciones de nivel de clase) de la siguiente manera, basado en this fragmento:
public class CdiBean {
@Resource
TransactionSynchronizationRegistry tsr;
@Transactional(Transactional.TxType.REQUIRED)
public boolean isTransactional() {
return tsr.getTransactionStatus() == Status.STATUS_ACTIVE;
}
}
Ahora, el resultado en GlassFish 4.0 es que este método realmente devuelve verdadero, lo que, según mis investigaciones, no está funcionando como se esperaba . Esperaba que el contenedor ignorara la anotación @Transactional en un método de bean CDI, o incluso lanzara una excepción. Utilizo un servidor GlassFish 4 recién instalado, por lo que no hay interferencias.
Así que mi pregunta es realmente:
- ¿Qué tipos de bean realmente soportan transacciones administradas por contenedor?
- Solo por curiosidad, ¿cómo podría probarlo con una aplicación de demostración simple si el código anterior es incorrecto?
(Por cierto: alguien describió un problema similar here , pero su solución no se aplica a mi caso.
El javadoc de transaccional dice:
La anotación javax.transaction.Transactional proporciona a la aplicación la capacidad de controlar de forma declarativa los límites de transacción en beans administrados por CDI, así como las clases definidas como beans administrados por la especificación Java EE, tanto en la clase como en el nivel de método donde las anotaciones a nivel de método prevalecen sobre las de El nivel de clase.
Entonces, tus suposiciones están equivocadas. Los EJB, hasta Java EE 6, eran los únicos tipos de componentes que soportaban transacciones declarativas. La anotación transaccional se introdujo precisamente en Java EE 7 para hacer transaccionales los beans CDI administrados que no sean EJB.
Hasta que Java EE 7 solo EJB era transaccional y la anotación @Transactional
no existía.
Desde Java EE 7 y JTA 1.2, puede utilizar el interceptor transaccional en CDI con @Transactional
anotación @Transactional
.
Para responder a su pregunta sobre el mejor tipo de bean a utilizar, la respuesta es CDI por defecto.
Los beans CDI son más ligeros que EJB y admiten una gran cantidad de funciones (incluido ser un EJB) y se activan de forma predeterminada (cuando agrega el archivo beans.xml
a su aplicación). Desde que Java EE 6 @Inject
@EJB
. Incluso si utiliza EJB remotos (característica que no existe en CDI), la práctica recomendada sugiere que @EJB
inyecte un EJB remoto y un productor de CDI para exponerlo como un bean CDI.
public class Resources {
@EJB
@Produces
MyRemoteEJB ejb;
}
Lo mismo se sugiere para los recursos de Java EE.
public class Resources2 {
@PersistenceContext
@Produces
EntityManager em;
}
Estos productores serán utilizados más tarde.
public class MyBean {
@Inject
MyRemoteEJB bean;
@Inject
EntityManager em;
}
EJB sigue teniendo sentido para ciertos servicios que incluyen como JMS o tratamiento asíncrono, pero los usará como bean CDI.