Sí, puede mezclar libremente CDI y EJB y lograr excelentes resultados. Parece que está usando @WebService
y @Schedule
, que son buenas razones para agregar EJB a la mezcla.
Existe mucha confusión, por lo que aquí hay información general sobre EJB y CDI, ya que se relacionan con cada uno.
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 cierto (todavía). Así que definitivamente no se acostumbre a 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. ¿Qué significa la alineación está permitiendo a la gente a hacer lo que ya pueden hacer, sólo que sin el @Stateful
, @Stateless
o @Singleton
la anotación en la parte superior.
EJB y CDI en términos de implementación
En última instancia, 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 se le da 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., así como también se encargará de cualquier transacción o control de seguridad. Una vez hecho todo esto, la llamada finalmente va al objeto real y el resultado se devuelve a través del proxy a la persona que llama.
La diferencia solo radica 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 mapa de hash que vive durante un período de tiempo específico (por solicitud @RequestScoped
, por sesión HTTP @SessionScoped
, por aplicación @ApplicationScoped
, conversación JSF @ConversationScoped
o por su implementación de alcance personalizado).
En EJB, el contenedor también busca en un mapa hash si el bean es de tipo @Stateful
. Un @Stateful
bean también puede usar cualquiera de las anotaciones de alcance anteriores, lo que hace que viva y muera con todos los demás beans del alcance. En EJB @Stateful
es esencialmente el bean "cualquier ámbito". El @Stateless
es básicamente una piscina ejemplo - se obtiene una instancia de la piscina 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 poder hacer con un bean "CDI". Debajo de las sábanas es muy difícil distinguirlos. Toda la plomería es la misma con la 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 proxy, pero como digo, estamos trabajando en el nivel de especificación de Java EE.
Nota de rendimiento
Haga caso omiso de las imágenes mentales "ligeras" o "pesadas" que pueda tener. Eso es todo marketing. Tienen el mismo diseño interno en su mayor parte. La resolución de la instancia CDI es quizás un poco más compleja porque es un poco más dinámica y contextual. La resolución de la instancia de EJB es bastante estática, tonta y simple en comparación.
Puedo decirle, desde una perspectiva de implementación en TomEE, que hay una diferencia de rendimiento nula entre invocar un EJB o invocar un bean CDI.
Por defecto a POJO, luego CDI, luego EJB
Por supuesto, no use CDI o EJB cuando no haya ningún beneficio. Agregue CDI cuando comience a querer inyección, eventos, interceptores, decoradores, seguimiento del ciclo de vida y cosas por el estilo. Esa es la mayor parte del tiempo.
Más allá de los conceptos básicos, hay una serie de servicios de contenedores útiles sólo tiene la opción de usar si usted hace su grano de CDI también un EJB mediante la adición de @Stateful
, @Stateless
o @Singleton
en él.
Aquí hay una breve lista de cuándo analizo los EJB.
Usando JAX-WS
Exponiendo un JAX-WS @WebService
. Soy perezoso. Cuando @WebService
también es un EJB, no es necesario enumerarlo y asignarlo como servlet en el web.xml
archivo. Eso es trabajo para mí. Además, tengo la opción de usar cualquiera de las otras funciones que se mencionan a continuación. Así que es una obviedad para mí.
Disponible para @Stateless
y @Singleton
solo.
Usando JAX-RS
Exponer un recurso JAX-RS a través de @Path
. Todavía soy vago. Cuando el servicio RESTful también es un EJB, nuevamente obtiene el descubrimiento automático y no tiene que agregarlo a una Application
subclase JAX-RS ni nada de eso. Además, puedo exponer exactamente el mismo bean que un @WebService
si quiero o usar cualquiera de las excelentes funciones que se mencionan a continuación.
Disponible para @Stateless
y @Singleton
solo.
Lógica de inicio
Cargar al inicio a través de @Startup
. Actualmente no existe un equivalente a esto en CDI. De alguna manera nos perdimos agregar algo como un AfterStartup
evento en el ciclo de vida del contenedor. Si hubiéramos hecho esto, simplemente podría haber tenido un @ApplicationScoped
bean que lo escuchara y eso sería efectivamente lo mismo que un @Singleton
with @Startup
. Está en la lista de CDI 1.1.
Disponible @Singleton
solo para .
Trabajando en Paralelo
@Asynchronous
invocación del método. Iniciar subprocesos es un no-no en cualquier entorno del lado del servidor. Tener demasiados subprocesos es un serio asesino del rendimiento. Esta anotación le permite paralelizar las cosas que hace utilizando el grupo de subprocesos del contenedor. Esto es asombroso.
Disponible a @Stateful
, @Stateless
y @Singleton
.
Programación del trabajo
@Schedule
o ScheduleExpression
es básicamente un cron o una Quartz
funcionalidad. También muy impresionante. La mayoría de los contenedores solo usan Quartz debajo de las cubiertas para esto. Sin embargo, la mayoría de la gente no sabe que programar el trabajo en Java EE es transaccional. Si actualiza una base de datos, luego programa algún trabajo y uno de ellos falla, ambos se limpiarán automáticamente. Si la EntityManager
llamada persistente falla o hay un problema de descarga, no es necesario cancelar la programación del trabajo. Bien, transacciones.
Disponible para @Stateless
y @Singleton
solo.
Usando EntityManagers en una transacción JTA
La nota anterior sobre transacciones, por supuesto, requiere que utilice un JTA
archivo EntityManager
. Puede usarlos con "CDI" simple, pero sin las transacciones administradas por el contenedor puede volverse realmente monótono duplicar la UserTransaction
lógica de compromiso / retroceso.
Disponible para todos los componentes de Java EE incluyendo CDI, JSF @ManagedBean
, @WebServlet
, @WebListener
, @WebFilter
, etc. La @TransactionAttribute
anotación, sin embargo, está disponible para @Stateful
, @Stateless
y @Singleton
solamente.
Mantener JTA administrado EntityManager
El EXTENDED
administrado le EntityManager
permite mantener una EntityManager
apertura entre JTA
transacciones y no perder los datos almacenados en caché. Buena característica para el momento y el lugar adecuados. Utilice responsablemente :)
Disponible @Stateful
solo para .
Fácil sincronización
Cuando necesita sincronización, las anotaciones @Lock(READ)
y @Lock(WRITE)
son bastante excelentes. Le permite obtener una gestión de acceso concurrente de forma gratuita. Omita todas las tuberías ReentrantReadWriteLock. En el mismo depósito está @AccessTimeout
, lo que le permite decir cuánto tiempo debe esperar un hilo para obtener acceso a la instancia del bean antes de darse por vencido.
Disponible @Singleton
solo para frijoles.