Comment se comparent CDI et EJB? interagir?

106

J'ai du mal à comprendre comment les deux interagissent et où se situe la frontière entre eux. Se chevauchent-ils? Y a-t-il des redondances entre eux?

Je sais qu'il y a des annotations associées aux deux, mais je n'ai pas été en mesure de trouver une liste complète des deux avec de brèves descriptions. Je ne sais pas si cela aiderait à clarifier en quoi ils diffèrent ou où ils se chevauchent.

Vraiment juste confus. Je (pense que je) comprends assez bien l'EJB, je suppose que j'ai du mal à comprendre exactement ce que CDI apporte à la table et comment il supplante ou améliore ce que l'EJB propose déjà.

Tim
la source
3
Cette question est classée en tête de la recherche "Différence EJB CDI" de Google, mais j'ai trouvé la réponse sur stackoverflow.com/questions/13487987/... plus claire
matt freake

Réponses:

50

CDI: il s'agit d'injection de dépendances. Cela signifie que vous pouvez injecter une implémentation d'interface n'importe où. Cet objet peut être n'importe quoi, il ne peut pas être lié à EJB. Voici un exemple de la façon d'injecter un générateur aléatoire à l'aide de CDI. Il n'y a rien sur EJB. Vous allez utiliser CDI lorsque vous souhaitez injecter des services non-EJB, différentes implémentations ou algorithmes (vous n'avez donc pas du tout besoin d'EJB).
EJB: vous comprenez, et probablement vous êtes confus par l' @EJBannotation - cela vous permet d'injecter une implémentation dans votre service ou autre. L'idée principale est que la classe, où vous injectez, doit être gérée par le conteneur EJB. Il semble que CDI comprend ce qu'est EJB, donc dans le serveur compatible Java EE 6, dans votre servlet, vous pouvez écrire les deux

@EJB EJBService ejbService;

et

@Inject EJBService ejbService;

c'est ce qui peut vous prêter à confusion, mais c'est probablement la seule chose qui fait le pont entre EJB et CDI.

Lorsque nous parlons de CDI, vous pouvez injecter d'autres objets dans des classes gérées par CDI (ils devraient juste être créés par des frameworks prenant en charge CDI).

Qu'est-ce que CDI offre d'autre ... Par exemple, vous utilisez Struts 2 comme framework MVC (juste exemple), et vous êtes limité ici, même en utilisant EJB 3.1 - vous ne pouvez pas utiliser d' @EJBannotation dans l'action Struts, elle n'est pas gérée par conteneur. Mais lorsque vous ajoutez le plugin Struts2-CDI, vous pouvez y écrire une @Injectannotation pour la même chose (donc plus besoin de recherche JNDI). De cette façon, il améliore la puissance de l'EJB, mais comme je l'ai déjà mentionné, ce que vous injectez avec CDI - peu importe s'il est lié à l'EJB ou non, et c'est sa puissance.

PS. lien mis à jour vers l'exemple

Maxym
la source
@EJB et @Inject sont-ils vraiment fonctionnellement équivalents? Je pense que c'est le chevauchement des méthodes d'injection entre CDI et certains des autres acronymes de Java EE qui m'a dérouté. D'autres lectures semblent indiquer qu'il y a un espoir d'aligner les annotations.
Tim
@Maxym Lorsque vous utilisez @ Inject, comment pouvez-vous vous assurer que le @ Stateless ou tout autre composant côté serveur d'EJB utilise toujours les fonctionnalités telles que le pooling ou la concurrence offerte par le conteneur. J'espère que ce n'est pas offert par CDI, non?
Bala
1
@Bala: CDI n'offre pas de pooling ... regardez CDI avec ou sans EJB3.1 , espérons qu'il répond à votre question ..
Maxym
@KorayTugay: CDI est une fonctionnalité Java EE, donc tout serveur compatible Java EE 6 l'a (Glassfish 3.0.1+ ne se trompe pas, JBoss 6+ etc.) Vous pouvez jeter un œil à JBoss Weld, une implémentation CDI de référence que vous peut utiliser par exemple Tomcat ...
Maxym
191

Il est actuellement un peu déroutant car il existe maintenant plusieurs modèles de composants dans Java EE. Il s'agit de Beans gérés CDI , EJB3 et JSF .

CDI est le petit nouveau du quartier. CDI haricots disposent dependency injection, scopinget un event bus. Les beans CDI sont les plus flexibles en termes d'injection et de cadrage. Le bus d'événements est très léger et parfaitement adapté aux applications Web les plus simples. En plus de cela, CDI expose également une fonctionnalité très avancée appelée portable extensions, qui est une sorte de mécanisme de plug-in permettant aux fournisseurs de fournir des fonctionnalités supplémentaires à Java EE qui peuvent être rendues disponibles sur toutes les implémentations (Glassfish, JBoss AS, Websphere, etc.) .

Les beans EJB3 ont été modernisés à partir de l'ancien modèle de composant EJB2 hérité * et ont été les premiers beans de Java EE à être gérés via une annotation. Les haricots EJB3 disposent dependency injection, declarative transactions, declarative security, pooling, concurrency control, asynchronous executionet remoting.

L'injection de dépendances dans les beans EJB3 n'est pas aussi flexible que dans les beans CDI et les beans EJB3 n'ont aucun concept de portée. Cependant, les beans EJB3 sont transactionnels et mutualisés par défaut ** , deux choses très utilisables que CDI a choisi de laisser dans le domaine d'EJB3. Les autres éléments mentionnés ne sont pas non plus disponibles dans CDI. EJB3 n'a cependant pas de bus d'événements propre, mais il a un type spécial de bean pour écouter les messages; le bean piloté par message. Cela peut être utilisé pour recevoir des messages du système de messagerie Java ou de tout autre système doté d'un adaptateur de ressources JCA. L'utilisation d'une messagerie complète pour des événements simples est beaucoup plus lourde que le bus d'événements CDI et EJB3 définit uniquement un écouteur, pas une API de producteur.

Les Beans gérés JSF existent dans Java EE depuis que JSF a été inclus. Eux aussi comportent dependency injectionet scoping. JSF Managed Beans a introduit le concept de portée déclarative. A l'origine, les portées étaient plutôt limitées et dans la même version de Java EE où les beans EJB3 pouvaient déjà être déclarés via des annotations, les Beans gérés JSF devaient encore être déclarés en XML. La version actuelle de JSF Managed Beans est également finalement déclarée via une annotation et les étendues sont étendues avec une étendue de vue et la possibilité de créer des étendues personnalisées. L'étendue de la vue, qui mémorise les données entre les requêtes sur la même page, est une fonctionnalité unique de JSF Managed Beans.

En dehors de la portée de la vue, il reste très peu de choses pour JSF Managed Beans dans Java EE 6. La portée de vue manquante dans CDI est malheureuse, car sinon CDI aurait été un super ensemble parfait de ce que propose JSF Managed Beans. Mise à jour : Dans Java EE 7 / JSF 2.2, un @ViewScoped compatible CDI a été ajouté, faisant de CDI ce super ensemble parfait. Mise à jour 2 : Dans JSF2.3, les beans gérés JSF ont été déconseillés au profit des beans gérés par CDI.

Avec EJB3 et CDI, la situation n'est pas si claire. Le modèle de composant et l'API EJB3 offrent de nombreux services que CDI n'offre pas, de sorte que l'EJB3 ne peut généralement pas être remplacé par CDI. D'autre part, CDI peut être utilisé en combinaison avec EJB3 - par exemple en ajoutant la prise en charge de la portée aux EJB.

Reza Rahman, membre du groupe d'experts et réalisateur d'une implémentation CDI appelée CanDI, a souvent laissé entendre que les services associés au modèle de composant EJB3 peuvent être modernisés sous la forme d'un ensemble d'annotations CDI. Si cela se produisait, tous les beans gérés dans Java EE pourraient devenir des beans CDI. Cela ne signifie pas que EJB3 disparaît ou devient obsolète, mais simplement que sa fonctionnalité sera exposée via CDI au lieu de via les propres annotations d'EJB comme @Stateless et @EJB.

Mettre à jour

David Blevins de TomEE et la renommée d'OpenEJB explique très bien les différences et les similitudes entre CDI et EJB sur son blog: CDI, quand sortir les EJB

* Bien que ce ne soit qu'un incrément de numéro de version, les beans EJB3 étaient pour la plupart un type de bean complètement différent: un simple pojo qui devient un "bean géré" en appliquant une simple annotation unique, vs le modèle dans EJB2 où un poids lourd et Un descripteur de déploiement XML trop détaillé était requis pour chaque bean, en plus du bean étant nécessaire d'implémenter diverses interfaces de composants extrêmement lourdes et pour la plupart dénuées de sens.

** Les beans session sans état sont généralement regroupés, les beans session avec état ne le sont généralement pas (mais ils peuvent l'être). Pour les deux types, la mise en commun est donc facultative et la spécification EJB ne l'exige pas dans les deux cas.

Arjan Tijms
la source
3
Je suis un peu confus par vos déclarations selon lesquelles "les beans EJB3 n'ont pas de concept de portée" et que "EJB3 n'a pas de bus d'événements qui lui est propre". Comment cela cadre-t-il avec l' affirmation de David Blevin selon laquelle "les EJB sont des beans CDI et ont donc tous les avantages du CDI"? Quelque chose a-t-il changé à cet égard entre le moment où vous avez rédigé votre réponse et celui où David a écrit son article sur le blog?
Chris
5
C'est à cause du concept peut-être quelque peu déroutant qu'il n'y a pas vraiment de "beans CDI", mais il y a des services appliqués aux beans gérés. Pour les besoins de la discussion, les gens (et moi-même donc) les appellent de toute façon "beans CDI". Avant CDI, les beans EJB n'avaient pas de portée explicite. Comme l'explique David, Stateful est implicitement une portée (et donc aucune portée en particulier). Maintenant avec CDI disponible, les beans EJB peuvent tirer parti des étendues fournies par CDI. Sans la spécification CDI, donc si vous regardez uniquement la spécification EJB, il n'y a pas de portées explicites.
Arjan Tijms
1
Pouvez-vous expliquer ce que vous entendez par «il existe des services appliqués aux beans gérés»? Cela signifie-t-il que le bean CDI n'existe pas? Il s'agit simplement de fournir des fonctionnalités supplémentaires sur un POJO - EJB - ou un Bean géré JSF? Vous aimez pouvoir utiliser l'annotation Inject dans un Bean géré JSF?
Koray Tugay
3
@Chris pour clarifier davantage du point de vue des spécifications EJB, nous avons délibérément décidé dès le début de CDI d'exiger que les implémentations d'EJB prennent en charge 100% de l'ensemble des fonctionnalités CDI sur les EJB. Tous les aspects de CDI fonctionnent sur les EJB, à l'exception des portées que nous avons dû limiter aux beans avec état uniquement.
David Blevins
1
Notez que JSF 2.2 fournit désormais javax.faces.view.ViewScoped, une extension CDI qui est essentiellement un port de la portée de vue JSF vers CDI. Avec cela, CDI est un remplacement complet des beans gérés JSF.
jdessey
-1

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

Les Ejbs et CDI sont assez simples à comprendre.

Ejbs:

  1. Sera toujours annoté par des qualificateurs de portée, par exemple, @Stateless, @Stateful, @Request, etc.
  2. Les instances d'Ejbs sont contrôlées par le framework Java EE et regroupées. Il est du devoir du cadre d'EE de fournir les instances pour le consommateur.

@Stateless

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

Le CarMaker est annoté avec une portée Ejbs spécifique, donc c'est Ejb

CDI:

  1. Non gérées entièrement par le framework EE, les instances doivent être créées par vous-même.
  2. Cela dépend toujours. laissez-moi vous expliquer "Dépendant" avec un exemple:

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

La Specificationclasse est CDI, car elle n'est pas annotée avec les portées Ejb et elle doit également être initialisée par votre code et non par le framework EE. Un point à noter ici est que puisque nous n'avons pas annoté la Specificationclasse, elle est annotée par défaut par @Dependentannotation.

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

Further reading: Vous devez étudier davantage entre l'annotation de portée Ejbs et l'annotation de portée CDI, cela clarifiera davantage le concept.

A
la source
Einstein a également dit: "Tout devrait être fait aussi simple que possible, mais pas plus simple", vous pouvez (devriez) remplacer "fait" par "expliqué" ici.
Kukeltje