web-dev-qa-db-fra.com

Java EE 6 @ javax.annotation.ManagedBean vs @ javax.inject.Named vs @ javax.faces.ManagedBean

Je pense qu'il y a un petit désordre dans la Java Spéc. EE 6. Il y a plusieurs ensembles d'annotations.

On a javax.ejb annotations comme @Stateful et @Stateless pour créer des EJB.

Il y a aussi @javax.annotation.ManagedBean pour créer un bean géré.

Il y a des annotations dans javax.enterprise.context comme @SessionScoped et @RequestScoped.

De plus il y a aussi @ManagedBean et @SessionScoped/@RequestScoped annotations dans javax.faces.bean paquet.

Et pour rendre les choses plus compliquées il y a un paquet javax.inject avec @Named annotation.

Quelqu'un peut-il s'il vous plaît décrire comment ils sont liés les uns aux autres?

Où puis-je utiliser @EJB, @Inject ou @ManagedPropery injecter d'autres haricots?

105
Piotr Gwiazda

Tout d’abord laissez-moi faire quelques précisions:

Définition du bean géré : un bean géré est généralement un objet dont le cycle de vie (construction, destruction, etc.) est géré par un conteneur.

Dans Java ee, nous avons de nombreux conteneurs qui gèrent le cycle de vie de leurs objets, tels que le conteneur JSF, le conteneur EJB, le conteneur CDI, le conteneur Servlet, etc.

Tous ces conteneurs fonctionnent de manière indépendante. Ils démarrent lors de l'initialisation du serveur d'applications et analysent les classes de tous les artefacts, y compris les fichiers jar, ejb-jar, war et ear, et rassemblent et stockent des métadonnées les concernant, puis lorsque vous avez besoin d'un objet. d'une classe à l'exécution, ils vous donneront des exemples de ces classes et, une fois le travail terminé, ils les détruiront.

Nous pouvons donc dire que nous avons:

  • Haricots gérés par JSF
  • Haricots gérés par CDI
  • Haricots gérés par EJB
  • Et même les servlets sont des beans gérés car ils sont instanciés et détruits par un conteneur, qui est un conteneur de servlet.

Ainsi, lorsque vous voyez le mot Managed Bean, vous devez vous informer du contexte ou du type de celui-ci (JSF, CDI, EJB, etc.).

Ensuite, vous pourriez vous demander pourquoi nous avons plusieurs de ces conteneurs: AFAIK, Java Les utilisateurs EE souhaitaient disposer d’un framework d’injection de dépendance, mais ils ne pouvaient pas rassembler toutes les exigences dans une spécification car ils ne pouvaient pas prédire la les exigences futures et ils ont créé EJB 1.0, puis 2.0, puis 3.0 et maintenant 3.1, mais la cible d’EJB ne visait que quelques exigences (transaction, modèle de composant distribué, etc.).

Dans le même temps (en parallèle), ils ont compris qu'ils devaient également prendre en charge JSF. Ils ont ensuite fabriqué des haricots gérés par JSF et un autre conteneur pour les haricots JSF. Ils ont considéré qu'il s'agissait d'un conteneur DI mature, mais ce conteneur n'était pas encore complet et mature.

Après cela, Gavin King et quelques autres gentils gars;) ont fabriqué CDI, le conteneur de DI le plus mature que j'ai jamais vu. CDI (inspiré de Seam2, Guice et Spring) a été créé pour combler le fossé entre JSF et EJB et beaucoup d’autres choses utiles comme l’injection de pojo, les méthodes de production, les intercepteurs, les décorateurs, l’intégration SPI, très flexible, etc., et peut même le faire Ce que font les beans gérés par EJB et JSF, nous ne pouvons avoir qu'un seul conteneur DI mature et puissant. Mais pour des raisons de compatibilité ascendante et pour des raisons politiques Java EE, les gars veulent les garder !!!

Ici vous pouvez trouver la différence et les cas d'utilisation pour chacun de ces types:

Beans gérés JSF, beans CDI et EJB

JSF a été initialement développé avec son propre mécanisme d'injection de beans gérés et de dépendances, qui a été amélioré pour JSF 2.0 afin d'inclure des beans basés sur des annotations. Lorsque CDI a été publié avec Java EE 6, il était considéré comme le framework de bean géré pour cette plate-forme et, bien entendu, les EJB les obsolètes datent de plus de dix ans.

Le problème est bien sûr de savoir lequel utiliser et quand les utiliser.

Commençons par les plus simples, les haricots gérés JSF.

Beans gérés JSF

En bref, ne les utilisez pas si vous développez pour Java EE 6 et utilisez CDI. Ils fournissent un mécanisme simple pour l'injection de dépendance et la définition de beans de support pour les pages Web, mais ils sont beaucoup moins puissant que les haricots CDI.

Ils peuvent être définis à l'aide de l'annotation @javax.faces.bean.ManagedBean, Qui prend un paramètre de nom facultatif. Ce nom peut être utilisé pour référencer le bean à partir de pages JSF.

L'étendue peut être appliquée au bean en utilisant l'une des différentes étendues définies dans le package javax.faces.bean, Notamment les étendues demande, session, application, vue et personnalisées.

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

Les haricots JSF ne peuvent pas être mélangés avec d'autres types de haricots sans une sorte de codage manuel.

Beans CDI

CDI est la structure d'injection de dépendance et de gestion des beans publiée dans le cadre de Java EE 6 et qui comprend une installation de bean géré complète et complète. Les beans CDI sont bien plus avancés et flexibles que la simple gestion JSF Ils peuvent utiliser des intercepteurs, une conversation, des événements, une injection sécurisée, des décorateurs, des stéréotypes et des méthodes de production.

Pour déployer des beans CDI, vous devez placer un fichier appelé beans.xml dans un dossier META-INF sur le chemin de classe. Une fois que cela est fait, chaque bean du paquet devient un bean CDI. Il existe de nombreuses fonctionnalités dans CDI, trop nombreuses pour être couvertes ici, mais comme référence rapide pour les fonctionnalités de type JSF, vous pouvez définir la portée du bean CDI en utilisant l'une des portées définies dans le package javax.enterprise.context. (à savoir, champs d'application, de conversation, de session et d'application). Si vous souhaitez utiliser le bean CDI à partir d'une page JSF, vous pouvez lui attribuer un nom à l'aide de l'annotation javax.inject.Named. Pour injecter un haricot dans un autre haricot, vous annotez le champ avec l'annotation javax.inject.Inject.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

L'injection automatique comme celle définie ci-dessus peut être contrôlée à l'aide de qualificateurs qui peuvent aider à correspondre à la classe spécifique que vous souhaitez injecter. Si vous avez plusieurs types de paiement, vous pouvez ajouter un qualificatif indiquant s'il est asynchrone ou non. Bien que vous puissiez utiliser l’annotation @Named Comme qualificatif, vous ne devriez pas le faire car il est prévu pour exposer les beans dans EL.

CDI gère l'injection de haricots avec des portées mal assorties grâce à l'utilisation de mandataires. De ce fait, vous pouvez injecter un bean délimité par une requête dans un bean délimité par une session et la référence sera toujours valide pour chaque requête car pour chaque requête, le proxy se reconnectera à une instance active du bean délimité par la demande.

CDI prend également en charge les intercepteurs, les événements, la nouvelle étendue de conversation et de nombreuses autres fonctionnalités, ce qui en fait un bien meilleur choix que les beans gérés par JSF.

[~ # ~] ejb [~ # ~]

Les EJB sont antérieurs aux haricots CDI et sont en quelque sorte similaires aux haricots CDI et, à d'autres égards, très différents. Principalement, les différences entre les beans CDI et les EJB sont que les EJB sont:

  • Transactionnel
  • Distant ou local
  • Capable de passiver des beans stateful libérant des ressources
  • Capable d'utiliser des minuteries
  • Peut être asynchrone

Les deux types d'EJB sont appelés stateless et stateful. Les EJB sans état peuvent être considérés comme des beans à usage unique sécurisés pour les threads qui ne conservent aucun état entre deux demandes Web. Les EJB avec état conservent leur statut et peuvent être créés et restés assis aussi longtemps qu'ils sont nécessaires jusqu'à leur élimination.

Définir un EJB est simple, vous ajoutez simplement une annotation javax.ejb.Stateless Ou javax.ejb.Stateful À la classe.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

Les beans sans état doivent avoir une portée dépendante, alors qu'un bean session avec état peut avoir n'importe quelle portée. Par défaut, ils sont transactionnels, mais vous pouvez utiliser l'annotation d'attribut de transaction.

Bien que les EJB et les beans CDI soient très différents en termes de fonctionnalités, l'écriture du code pour les intégrer est très similaire puisque les beans CDI peuvent être injectés dans des EJB et que les EJB peuvent être injectés dans des beans CDI. Il n’est pas nécessaire de faire la distinction lorsqu’on s’injecte l’un dans l’autre. Encore une fois, CDI gère les différentes portées à l’aide du proxy. Une exception à cette règle est que CDI ne prend pas en charge l’injection d’EJB distants, mais que cela peut être implémenté en écrivant une méthode de production simple pour ce dernier.

L'annotation javax.inject.Named Ainsi que tous les qualificateurs peuvent être utilisés sur un EJB pour le faire correspondre à un point d'injection.

Quand utiliser quel haricot

Comment savez-vous quand utiliser quel haricot? Simple.

N'utilisez jamais de beans gérés par JSF, sauf si vous travaillez dans un conteneur de servlets et que vous ne voulez pas que CDI fonctionne dans Tomcat (bien qu'il existe certains archétypes Maven pour cela, il n'y a donc aucune excuse).

En règle générale, vous devez utiliser les beans CDI sauf si vous avez besoin des fonctionnalités avancées disponibles dans les EJB, telles que les fonctions transactionnelles. Vous pouvez écrire votre propre intercepteur pour rendre les beans CDI transactionnels, mais pour le moment, il est plus simple d'utiliser un EJB jusqu'à ce que CDI obtienne les beans CDI transactionnels qui se trouvent à proximité. Si vous êtes bloqué dans un conteneur de servlet et utilisez CDI, alors les transactions écrites à la main ou votre propre intercepteur de transaction est la seule option sans EJB.

Si vous devez utiliser @ViewScoped Dans CDI, vous devriez

  • utiliser le module coutures-faces ou MyFaces CODI . il suffit d’ajouter l’un d’eux à votre chemin de classe et @ViewScoped fonctionnera dans CDI. MyFaces CODI a un support encore plus solide de @ViewScoped
  • utilisez @ViewAccessScoped de MyFaces CODI, c'est une extension écrite au-dessus de CDI par Apache, il suffit de télécharger et d'utiliser l'annotation @ViewAccessScoped au lieu de @ViewScoped.
  • Utilisez CDI @ConversationScoped Et faites-le fonctionner longtemps. Voir ici pour plus d'informations .
  • Utiliser Omnifaces @ViewScoped Annotation

Certaines parties volées de ici .

189
Heidarzadeh

Oui, cela peut être déroutant.

Pour certaines raisons eh historiques, JSF et CDI utilisent les mêmes annotations pour les portées, mais pour des packages différents.

Comme vous devinez probablement ceux de javax.faces.bean proviennent des spécifications JSF et ne sont pas liées à CDI. Ne les utilisez pas sauf si vous avez une très bonne raison de le faire. Et ne les mélangez jamais avec les annotations CDI de javax.ejb. Cela produira une liste infinie de bugs et d'anomalies subtiles.

Je recommande généralement que vous parcouriez les quelques premières (voire plus) pages de l'excellent documentation sur les soudures . Cela devrait vous mettre sur la bonne voie pour Java EE 6.

Et n'hésitez pas à poser d'autres questions ici.

6
jan groth

Puisqu'il n'y a pas de réponse spécifique à propos de @javax.annotation.ManagedBean, voici un lien vers la réponse à une question similaire: beans de sauvegarde (@ManagedBean) ou beans CDI (@Named)? . La spécification peut être trouvée à l’adresse http://download.Oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ . Donc, il me semble que @javax.annotation.ManagedBean était censé être une généralisation de @javax.faces.bean.ManagedBean.

D'après ce que j'ai compris, les beans gérés JSF sont progressivement supprimés au profit des beans CDI (peut-être devenir obsolètes à partir de JSF 2.3?), Donc je suppose que @javax.annotation.ManagedBean est de plus en plus obsolète.

1
Hein Blöd