¿Cómo se comparan CDI y EJB? ¿interactuar?

106

Estoy teniendo dificultades para entender cómo interactúan los dos y dónde se encuentra el límite entre ellos. ¿Se superponen? ¿Hay redundancias entre ellos?

Sé que hay anotaciones asociadas con ambos, pero no he podido encontrar una lista completa de ambos con descripciones breves. No estoy seguro de si esto ayudaría a aclarar en qué se diferencian o dónde se superponen.

Realmente confundido. (Creo que) entiendo a EJB razonablemente bien, supongo que me está costando entender exactamente qué aporta CDI y cómo sustituye o mejora lo que ya ofrece EJB.

Tim
fuente
3
Esta pregunta se clasifica en la parte superior de la búsqueda de Google "EJB CDI difference", pero encontré la respuesta en stackoverflow.com/questions/13487987/… más clara
matt freake

Respuestas:

50

CDI: se trata de inyección de dependencia. Significa que puede inyectar la implementación de la interfaz en cualquier lugar. Este objeto puede ser cualquier cosa, no puede estar relacionado con EJB. Aquí hay un ejemplo de cómo inyectar un generador aleatorio usando CDI. No hay nada sobre EJB. Utilizará CDI cuando desee inyectar servicios que no sean EJB, diferentes implementaciones o algoritmos (por lo que no necesita EJB allí).
EJB: lo entiendes, y probablemente te confunde la @EJBanotación: te permite inyectar implementación en tu servicio o lo que sea. La idea principal es que la clase, donde inyecta, debe ser administrada por el contenedor EJB. Parece que CDI entiende qué es EJB, por lo que en el servidor compatible con Java EE 6, en su servlet puede escribir ambos

@EJB EJBService ejbService;

y

@Inject EJBService ejbService;

eso es lo que puede confundirlo, pero eso es probablemente lo único que es el puente entre EJB y CDI.

Cuando hablamos de CDI, puede inyectar otros objetos en clases administradas de CDI (solo deberían ser creados por marcos compatibles con CDI).

Qué más ofrece CDI ... Por ejemplo, usa Struts 2 como marco MVC (solo un ejemplo), y está limitado aquí, incluso usando EJB 3.1: no puede usar la @EJBanotación en la acción de Struts, no está administrado por el contenedor. Pero cuando agrega el complemento Struts2-CDI, puede escribir una @Injectanotación para lo mismo (por lo que no se necesitan más búsquedas JNDI). De esta manera mejora la potencia de EJB, pero como mencioné antes, lo que inyecta con CDI, no importa si está relacionado con EJB o no, y esa es su potencia.

PD. enlace actualizado al ejemplo

Maxym
fuente
¿Son @EJB y @Inject realmente equivalentes funcionalmente? Creo que fue la superposición de métodos de inyección entre CDI y algunos de los demás acrónimos de Java EE lo que me confundió. Más lectura parece indicar que hay esperanzas de alinear las anotaciones.
Tim
@Maxym Cuando usa @ Inject, ¿cómo puede asegurarse de que @ Stateless o cualquier otro componente del lado del servidor de EJB todavía use las características como Pooling o concurrencia que ofrece el contenedor? Espero que CDI no lo ofrezca, ¿verdad?
Bala
1
@Bala: CDI no ofrece agrupación ... mire CDI con o sin EJB3.1 , espero que responda a su pregunta ..
Maxym
@KorayTugay: CDI es una función de Java EE, por lo que cualquier servidor compatible con Java EE 6 la tiene (Glassfish 3.0.1+ no se equivoca, JBoss 6+, etc.) Puede echar un vistazo a JBoss Weld, una implementación de CDI de referencia que se puede usar, por ejemplo, en Tomcat ...
Maxym
191

De hecho, actualmente es un poco confuso, ya que ahora hay varios modelos de componentes en Java EE. Son Beans administrados CDI , EJB3 y JSF .

CDI es el chico nuevo del barrio. Habas CDI cuentan dependency injection, scopingy un event bus. Los beans CDI son los más flexibles con respecto a la inyección y el alcance. El bus de eventos es muy ligero y muy adecuado incluso para las aplicaciones web más simples. Además de esto, CDI también expone una característica muy avanzada llamada portable extensions, que es una especie de mecanismo de complemento para que los proveedores proporcionen funcionalidad adicional a Java EE que puede estar disponible en todas las implementaciones (Glassfish, JBoss AS, Websphere, etc.) .

Los beans EJB3 se actualizaron a partir del antiguo modelo de componente EJB2 * heredado y fueron los primeros beans en Java EE en ser beans gestionados mediante una anotación. Cuentan con los granos de EJB3 dependency injection, declarative transactions, declarative security, pooling, concurrency control, asynchronous executiony remoting.

La inyección de dependencia en los beans EJB3 no es tan flexible como en los beans CDI y los beans EJB3 no tienen un concepto de alcance. Sin embargo, los beans EJB3 son transaccionales y agrupados de forma predeterminada ** , dos cosas muy útiles que CDI ha decidido dejar en el dominio de EJB3. Los otros elementos mencionados tampoco están disponibles en CDI. Sin embargo, EJB3 no tiene bus de eventos propio, pero tiene un tipo especial de bean para escuchar mensajes; el bean dirigido por mensajes. Esto se puede utilizar para recibir mensajes de Java Messaging System o de cualquier otro sistema que tenga un adaptador de recursos JCA. El uso de mensajería completa para eventos simples es mucho más pesado que el bus de eventos CDI y EJB3 solo define un oyente, no una API de productor.

Los beans administrados JSF han existido en Java EE desde que se incluyó JSF. Ellos también cuentan con dependency injectiony scoping. JSF Managed Beans introdujo el concepto de alcance declarativo. Originalmente, los ámbitos eran bastante limitados y en la misma versión de Java EE, donde los beans EJB3 ya se podían declarar mediante anotaciones, los beans administrados JSF todavía tenían que declararse en XML. La versión actual de JSF Managed Beans también se declara finalmente a través de una anotación y los ámbitos se amplían con un ámbito de vista y la capacidad de crear ámbitos personalizados. El alcance de la vista, que recuerda datos entre solicitudes a la misma página, es una característica única de JSF Managed Beans.

Aparte del alcance de la vista, todavía hay muy poco para JSF Managed Beans en Java EE 6. El alcance de vista que falta en CDI es lamentable, ya que de lo contrario CDI habría sido un superconjunto perfecto de lo que ofrecen JSF Managed Beans. Actualización : en Java EE 7 / JSF 2.2, se ha agregado un @ViewScoped compatible con CDI , lo que hace que CDI sea el superconjunto perfecto. Actualización 2 : en JSF2.3, los beans administrados JSF se han desaprobado en favor de los beans administrados CDI.

Con EJB3 y CDI la situación no es tan clara. El modelo de componente EJB3 y la API ofrecen muchos servicios que CDI no ofrece, por lo que normalmente EJB3 no puede ser reemplazado por CDI. Por otro lado, CDI se puede usar en combinación con EJB3, por ejemplo, agregando soporte de alcance a los EJB.

Reza Rahman, miembro del grupo de expertos e implementador de una implementación de CDI llamada CanDI, ha insinuado con frecuencia que los servicios asociados con el modelo de componente EJB3 se pueden actualizar como un conjunto de anotaciones de CDI. Si eso sucediera, todos los beans gestionados en Java EE podrían convertirse en beans CDI. Esto no significa que EJB3 desaparezca o se vuelva obsoleto, sino solo que su funcionalidad se expondrá a través de CDI en lugar de a través de las propias anotaciones de EJB como @Stateless y @EJB.

Actualizar

David Blevins de TomEE y la fama OpenEJB explica muy bien las diferencias y similitudes entre CDI y EJB en su blog: CDI, when to break out the EJBs

* Aunque es solo un incremento en el número de versión, los beans EJB3 eran en su mayor parte un tipo de bean completamente diferente: un pojo simple que se convierte en un "bean administrado" aplicando una sola anotación simple, frente al modelo en EJB2 donde un peso pesado y Se requería un descriptor de implementación XML demasiado detallado para todos y cada uno de los beans, además de que el bean era necesario para implementar varias interfaces de componentes extremadamente pesadas y, en su mayor parte, sin sentido.

** Los beans de sesión sin estado generalmente se agrupan, los beans de sesión con estado generalmente no (pero pueden serlo). Para ambos tipos, la agrupación es opcional y la especificación EJB no lo exige de ninguna manera.

Arjan Tijms
fuente
3
Estoy un poco confundido por sus declaraciones de que "los beans EJB3 no tienen concepto de alcance" y que "EJB3 no tiene bus de eventos propio". ¿Cómo encaja esto con la afirmación de David Blevin de que "los EJB son granos CDI y, por lo tanto, tienen todos los beneficios de CDI"? ¿Ha cambiado algo a este respecto entre cuando escribió su respuesta y cuando David escribió su entrada en el Blog?
Chris
5
Es por el concepto quizás algo confuso de que en realidad no existen realmente "beans CDI", pero hay servicios aplicados a beans administrados. En aras de la discusión, la gente (y yo también) se refiere a ellos como "beans CDI" de todos modos. Antes de CDI, los beans EJB no tenían un alcance explícito. Como explica David, Stateful es implícitamente cualquier alcance (y, por lo tanto, ningún alcance en particular). Ahora con CDI disponible, los beans EJB pueden aprovechar los ámbitos proporcionados por CDI. Sin la especificación CDI, por lo que cuando se mira únicamente la especificación EJB, no hay ámbitos explícitos.
Arjan Tijms
1
¿Puede explicar lo que quiere decir con "hay servicios aplicados a los beans gestionados"? ¿Significa que en realidad no existe un bean CDI? ¿Son solo algunas características adicionales en un POJO - EJB - o un Bean administrado JSF? ¿Te gusta poder usar la anotación Inject en un Bean administrado JSF?
Koray Tugay
3
@Chris para aclarar aún más desde una perspectiva de especificación de EJB, tomamos la decisión deliberada desde el inicio de CDI de requerir que las implementaciones de EJB admitan el 100% del conjunto de características de CDI en EJB. Todos los aspectos de CDI funcionan en EJB con la excepción de los ámbitos que tuvimos que limitar solo a los beans con estado.
David Blevins
1
Tenga en cuenta que JSF 2.2 ahora proporciona javax.faces.view.ViewScoped, una extensión CDI que es esencialmente un puerto del alcance de la vista JSF a CDI. Con esto, CDI es un reemplazo completo para JSF Managed Beans.
jdessey
-1

Albert Einstein: If you can't explain it simply, you don't understand it well enough

Ejbs y CDI son bastante simples de entender.

Ejbs:

  1. Siempre estará anotado por calificadores de alcance, por ejemplo, @Stateless, @Stateful, @Request, etc.
  2. Las instancias de Ejbs están controladas por el marco de Java EE y agrupadas. Es deber del marco de EE proporcionar las instancias para el consumidor.

@Stateless

 public class CarMaker(){
    public void createCar(Specification specs){
        Car car = new Car(specs);
    }
}

El CarMaker está anotado con un alcance Ejbs específico, por lo tanto, es Ejb

CDI:

  1. No administrado completamente por el marco de EE, las instancias deben ser creadas por usted mismo.
  2. Siempre es dependiente. déjame explicar "Dependiente" con un ejemplo:

    class Specification { private String color; private String model; //- Getter and Setter }

La Specificationclase es CDI, ya que no está anotada con ámbitos Ejb y también debe inicializarla su código, no el marco EE. Un punto que debe tenerse en cuenta aquí es que, dado que no anotamos la Specificationclase, está anotada por @Dependentanotación por defecto .

@Dependent  <- By default added 
class Specification { ... }

Further reading: Necesita estudiar más entre la anotación de alcance Ejbs y la anotación de alcance CDI, eso aclarará aún más el concepto.

TIENE
fuente
Einstein también dijo: "Todo debe hacerse lo más simple posible, pero no más simple" , puede (debe) reemplazar 'hecho' por 'explicado' aquí.
Kukeltje