ejb 3.0 - plume - Dónde usar EJB 3.1 y CDI?
tomee 8 (2)
si realmente no está utilizando ninguna de las características de ejb 3.1, la respuesta es simple. pero adivina que tu pregunta indica que sospechas que hay conceptos de ejb 3.1 de los que te estás beneficiando sin darte cuenta de ellos. Un ejemplo podría ser que el contenedor puede mantener un grupo de slsb listo para ser utilizado, por lo que las conexiones de base de datos y jms no deben ser inyectadas como parte de la solicitud.
Estoy creando un producto basado en Java EE en el que estoy usando GlassFish 3 y EJB 3.1.
Mi aplicación tiene beans de sesión , un programador y usa servicios web. Recientemente conocí Apache TomEE , que admite Contextos e Inyección de Dependencia (CDI) . El contenedor GlassFish también es compatible con CDI.
¿Puedo reemplazar beans de sesión donde no requiera ninguna característica que CDI tampoco brinde? Y si entonces, ¿cuáles son los beneficios que puedo obtener?
Sí, puedes mezclar libremente tanto CDI como EJB y lograr grandes resultados. Parece que está utilizando @WebService
y @Schedule
, que son buenas razones para agregar EJB a la mezcla.
Hay mucha confusión, así que aquí hay información general sobre EJB y CDI, ya que se relacionan entre sí.
EJB> = CDI
Tenga en cuenta que los EJB son beans CDI y, por lo tanto, tienen todos los beneficios de CDI. Lo contrario no es verdad (todavía). Así que definitivamente no adquieras el hábito de pensar "EJB vs CDI", ya que esa lógica realmente se traduce en "EJB + CDI vs CDI", que es una ecuación extraña.
En futuras versiones de Java EE continuaremos alineándolos. Lo que significa alinearse es permitir que las personas hagan lo que ya pueden hacer, simplemente sin la @Stateful
, @Stateless
o @Singleton
en la parte superior.
EJB y CDI en términos de implementación
En definitiva, EJB y CDI comparten el mismo diseño fundamental de ser componentes proxy. Cuando obtiene una referencia a un bean EJB o CDI, no es el bean real. Más bien, el objeto que le dan es falso (un proxy). Cuando invoca un método en este objeto falso, la llamada va al contenedor que enviará la llamada a través de interceptores, decoradores, etc., y se encargará de cualquier transacción o verificación de seguridad. Una vez que todo está hecho, la llamada finalmente va al objeto real y el resultado se transfiere a través del proxy a la persona que llama.
La diferencia solo viene en cómo se resuelve el objeto a invocar. Por "resuelto" simplemente queremos decir dónde y cómo el contenedor busca la instancia real para invocar.
En CDI, el contenedor se ve en un "alcance", que básicamente será un hashmap que vive durante un período de tiempo específico (por solicitud @RequestScoped
, por sesión HTTP @SessionScoped
, por aplicación @ApplicationScoped
, JSF Conversation @ConversationScoped
, o por su implementación de alcance personalizado).
En EJB, el contenedor también se ve en un hashmap si el bean es del tipo @Stateful
. Un frijol @Stateful
también puede usar cualquiera de las anotaciones de alcance anteriores causando que viva y muera con todos los otros beans en el alcance. En EJB @Stateful
es esencialmente el bean "de cualquier ámbito". El @Stateless
es básicamente un grupo de instancias; se obtiene una instancia del grupo durante la duración de una invocación. El @Singleton
es esencialmente @ApplicationScoped
Entonces, en un nivel fundamental, cualquier cosa que pueda hacer con un bean "EJB" debería ser capaz de hacer con un bean "CDI". Bajo las sábanas es terriblemente difícil distinguirlos. Toda la fontanería es igual a excepción de cómo se resuelven las instancias.
Actualmente no son los mismos en términos de los servicios que el contenedor ofrecerá al hacer este proxying, pero como digo, estamos trabajando en el nivel de especificaciones de Java EE.
Nota de rendimiento
Haga caso omiso de las imágenes mentales "ligeras" o "pesadas" que pueda tener. Eso es todo marketing. Ellos tienen el mismo diseño interno en su mayor parte. La resolución de instancia de CDI es quizás un poco más compleja porque es un poco más dinámica y contextual. La resolución de instancia de EJB es bastante estática, estúpida y simple en comparación.
Puedo decirle desde una perspectiva de implementación en TomEE, que hay una diferencia de rendimiento de cero entre invocar un EJB e invocar un bean CDI.
Predeterminado a POJOs, luego CDI, luego EJB
Por supuesto, no use CDI o EJB cuando no haya ningún beneficio. Agregue CDI cuando empiece a querer inyección, eventos, interceptores, decoradores, seguimiento de ciclo de vida y cosas por el estilo. Esa es la mayor parte del tiempo.
Más allá de estos conceptos básicos, hay una serie de útiles servicios de contenedor que solo tiene la opción de usar si convierte su bean CDI también en EJB agregando @Stateful
, @Stateless
o @Singleton
en él.
Aquí hay una breve lista de cuando rompo los EJB.
Usando JAX-WS
Exponer un JAX-WS @WebService
. Soy perezoso. Cuando @WebService
también es un EJB, no es necesario que lo liste y lo @WebService
como un servlet en el archivo web.xml
. Eso es trabajo para mí. Además, tengo la opción de utilizar cualquiera de las otras funciones mencionadas a continuación. Así que es obvio para mí.
Disponible solo para @Stateless
y @Singleton
.
Usando JAX-RS
Exponer un recurso JAX-RS a través de @Path
. Todavía soy flojo. Cuando el servicio RESTful también es un EJB, nuevamente obtiene el descubrimiento automático y no tiene que agregarlo a una subclase de la Application
JAX-RS ni a nada de eso. Además, puedo exponer exactamente el mismo bean como @WebService
si quiero o utilizar cualquiera de las excelentes funcionalidades mencionadas a continuación.
Disponible solo para @Stateless
y @Singleton
.
Lógica de arranque
Cargar al inicio a través de @Startup
. Actualmente no hay un equivalente a esto en CDI. De alguna manera nos perdimos de agregar algo así como un evento AfterStartup
en el ciclo de vida del contenedor. Si hubiéramos hecho esto, simplemente podría haber tenido un bean @ApplicationScoped
que lo escuchó y que efectivamente sería lo mismo que @Singleton
con @Startup
. Está en la lista para CDI 1.1.
Disponible solo para @Singleton
.
Trabajando en Paralelo
@Asynchronous
Invocación de método @Asynchronous
. El inicio de los hilos es un no-no en cualquier entorno del lado del servidor. Tener demasiados hilos es un asesino serio. Esta anotación le permite paralelizar las cosas que hace usando el grupo de subprocesos del contenedor. Esto es asombroso
Disponible para @Stateful
, @Stateless
y @Singleton
.
Programando el trabajo
@Schedule
o ScheduleExpression
es básicamente una funcionalidad cron o Quartz
. También muy impresionante. La mayoría de los contenedores solo usan Quartz debajo de las fundas para esto. La mayoría de la gente no sabe, sin embargo, que programar el trabajo en Java EE es transaccional. Si actualiza una base de datos, luego programa algo de trabajo y uno de ellos falla, ambos se limpiarán automáticamente. Si la EntityManager
persistente de EntityManager
falla o hay un problema de enrojecimiento, no hay necesidad de cancelar la programación del trabajo. Yay, transacciones.
Disponible solo para @Stateless
y @Singleton
.
Usar EntityManagers en una transacción JTA
La nota anterior sobre las transacciones, por supuesto, requiere que utilice un EntityManager
administrado por JTA
. Puede usarlos con "CDI" simple, pero sin las transacciones manejadas por contenedor puede obtener una duplicación realmente monótona de la UserTransaction
confirmación / restitución de UserTransaction
.
Disponible para todos los componentes de Java EE, incluidos CDI, JSF @WebServlet
, @WebServlet
, @WebListener
, @WebFilter
, etc. La anotación @TransactionAttribute
, sin embargo, está disponible solo para @Stateful
, @Stateless
y @Singleton
.
Manteniendo EntityManager
administrado por JTA
El EntityManager
administrado EXTENDED
EntityManager
permite mantener un EntityManager
abierto entre transacciones JTA
y no perder los datos en caché. Buena característica para el momento y el lugar correctos. Usar responsablemente :)
Disponible solo para @Stateful
.
Fácil sincronización
Cuando necesita sincronización, las @Lock(READ)
y @Lock(WRITE)
son bastante excelentes. Le permite obtener administración de acceso simultáneo de forma gratuita. Omita todas las tuberías de ReentrantReadWriteLock. En el mismo cubo está @AccessTimeout
, que le permite decir cuánto debe esperar un hilo para acceder a la instancia de bean antes de darse por vencido.
Disponible solo para beans @Singleton
.