web-dev-qa-db-fra.com

Que fait l'annotation @EJBs?

Je sais en gros à quoi sert cette construction: elle crée un EJB de type SomeType et injecte l'objet dans un autre EJB.

 @EJB(name="name1")
 SomeType someVariable

Maintenant, j'ai une classe qui commence comme ceci: (Je donne toutes les annotations au niveau de la classe, même si je pense que seul le @EJBs est pertinent)

@Remote(SomeClass.class)
@Stateless(name="someName")
@EJBs({@EJB(name="name1",beanInterface=Type1.class),
       @EJB(name="name2",beanInterface=Type2.class)})
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class X extends Y{ 
  //code

Que font les @EJB s ici? Ils obtiennent ou créent probablement les objets "name1" ... depuis JNDI, mais où placent-ils le résultat? Je ne vois pas d'appels .lookup à proximité, mais la base de code est énorme, donc je ne suis pas très sûr à ce sujet.

Question bonus: je suppose que les deux annotations @Transaction répètent simplement les valeurs par défaut?

UPDATE: Plusieurs personnes ont affirmé à ce stade que @EJBs était une extension propriétaire. Ce n'est pas. C'est une partie essentielle de Java EE5. Voir le JavaDoc pour plus de détails. . C'est simplement un conteneur pour les annotations @EJB individuelles.

Je crois que tous ceux qui prétendent que ces annotations EJB font une recherche. Je veux juste savoir ce qui se passe avec le résultat de cette recherche.

35
hyperman

L'annotation @EJB (et @Resource, @WebServiceRef, etc.) remplit deux fonctions:

  1. Il déclare une référence dans l'espace de nom du composant. Par exemple, @EJB(name="myEJB") crée une référence Java:comp/env/myEJB. Si vous annotez un champ sans spécifier de nom, il crée une référence Java:comp/env/com.example.MyClass/myField.
  2. Si l'annotation est déclarée sur une méthode de champ ou une méthode de définition, le conteneur effectue l'injection lors de la création du composant.

Le mode de résolution de la référence varie, que la référence soit résolue pour une lookup("Java:comp/env/myEJB") ou en raison d'une injection:

  1. Si EE 6+ est utilisé, l'attribut lookup nécessite une recherche JNDI pour résoudre la cible.
  2. Certains serveurs d'applications prennent en charge mappedName, qui est spécifique au fournisseur. Ceci est généralement implémenté en effectuant une recherche.
  3. Les serveurs d'applications prennent en charge les liaisons au moment du déploiement. Ceci est généralement implémenté en effectuant une recherche.
  4. Si aucune autre information de liaison n'est fournie et que l'interface de bean (beanInterface ou le type de champ) est uniquement implémentée par un seul EJB dans l'application, la spécification EJB exige qu'elle y retourne.
  5. Si aucune autre information de liaison n'est fournie et que # 4 ne peut pas fonctionner, certains serveurs d'applications tenteront d'effectuer une recherche dans l'espace de noms du serveur en fonction du nom de la référence (par exemple, Java:comp/env/myEJB peut provoquer une recherche de myEJB dans l'espace de noms du serveur).
36
Brett Kail

La réponse de Miljen Mikic m'a donné une idée de la réponse possible. Si quelqu'un qui connaît JNDI lit ceci, dites-moi s'il vous plaît si c'est sain d'esprit, comme je le suppose en fait ici.

En gros, il y a deux façons de regarder dans l'arborescence JNDI: soit via un chemin global (/ some/proprietary/path/my/bean) et via l'environnement de votre programme (Java: comp/env/my/bean). L'idée est de créer des références à partir du chemin global vers votre environnement local, puis de rechercher les composants à partir de là.

Donc, @Ejb (name = "Java: comp/env/mon/bean", mappedName = "/ some/proprietary/chemin/mon/bean") créerait cette référence à partir de code Java (sans fichier xml de descripteur).

Cela signifie que @Ejb (name = "Java: comp/env/my/bean") est en soi un no-op: il copie une référence sur lui-même. Le fait que votre serveur d’applications sache maintenant, au moment de la compilation, que cette référence est nécessaire, peut-être a-t-il un effet pervers, mais c’est à peu près tout.

2
hyperman

Selon ce lien link , cette annotation permet à EJB de rechercher des EJB externes relativement à son contexte. Habituellement, il existe des moyens plus élégants de le faire.

1
Miljen Mikic

En ce qui concerne la question de bonus: Oui, les deux annotations concernant les transactions répétent les valeurs par défaut: TransactionManagementType par défaut est CONTAINER (vs BEAN) et - par défaut - TransactionAttributeType REQUIRED indique simplement que si le bean est appelé dans un contexte transactionnel, la transaction est poursuivie sinon, une nouvelle transaction sera lancée (par opposition à, par exemple, REQUIRES_NEW qui créera toujours une nouvelle émission). En fait, cela n’est pas aussi trivial que cela puisse paraître. Cf. la spécification EJB 3.1: 

"13.3.7 Spécification des attributs de transaction pour les méthodes d’un bean

Le fournisseur de bean d’un bean entreprise avec une démarcation de transaction gérée par conteneur peut spécifier Les attributs de transaction pour les méthodes du bean entreprise. Par défaut, la valeur de l'attribut transaction Pour une méthode d'un bean avec une démarcation de transaction gérée par conteneur est l'attribut REQUIRED Transaction. Cet attribut n'a pas besoin d'être explicitement spécifié. [. ..] "

1
William Adams