41
votes

I know roughly what this construction does: it creates a SomeType EJB and injects the object into another EJB.

 @EJB(name="name1")
 SomeType someVariable

Now I have a class which starts like this: (I give all class-level annotations, even though I think only the @EJBs is relevant)

@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

What do the @EJB s do here? They probably get or create the "name1" ... objects from JNDI, but where do they put the result? I don't see a .lookup call anywhere near, but the codebase is huge so I'm not very sure about this.

Bonus question: I presume the two @Transaction annotations simply repeat defaults?

UPDATE: Multiple persons claimed at this point that @EJBs is a proprietary extension. It is not. It is a core part of java EE5. See the JavaDoc for details.. It is simply a container for the individual @EJB annotations.

I believe everyone who claims these EJB annotations do a lookup. I just want to know what happens with the result of this lookup.

4
Well this is weird I have never heard of @EJBs and ussage like this.Amit Deshpande

4 Answers

42
votes

The @EJB annotation (and @Resource, @WebServiceRef, etc.) serves two purposes:

  1. It declares a reference in the component namespace. For example, @EJB(name="myEJB") creates a reference java:comp/env/myEJB. If you annotate a field and do not specify a name, then it creates a reference java:comp/env/com.example.MyClass/myField.
  2. If the annotation is declared on a field or setter method, then the container performs injection when the component is created.

How the reference is resolved varies, independent of whether the reference is being resolved for a lookup("java:comp/env/myEJB") or due to injection:

  1. If EE 6+ is used, the lookup attribute requires a JNDI lookup to resolve the target.
  2. Some application servers support mappedName, which is specified to be vendor specific. This is usually implemented by performing a lookup.
  3. Application servers support bindings at deployment time. This is usually implemented by performing a lookup.
  4. If no other binding information is provided and the bean interface (beanInterface or the field type) is only implemented by a single EJB in the application, then the EJB specification requires that it fall back to that.
  5. If no other binding information is provided and #4 cannot work, some application servers will attempt to perform a lookup in the server namespace based on the ref name (for example, java:comp/env/myEJB might cause a lookup of myEJB in the server namespace).
2
votes

Miljen Mikic's answer gave me an idea about the possible answer. If anyone who knows about JNDI reads this, please tell me if this is sane, as I'm basically guessing here.

Basically, there are 2 ways to look into the JNDI tree: either via a global path (/some/proprietary/path/my/bean) and via your program's environment (java:comp/env/my/bean). The idea is that you create references from the global path to you local environment, and then lookup the components from there.

So @Ejb(name="java:comp/env/my/bean",mappedName="/some/proprietary/path/my/bean") would create this reference from java code (without descriptor xml file).

This means @Ejb(name="java:comp/env/my/bean") is on its own a no-op: It copies a reference onto itself. It might hava as side effect the fact that you application server now knows at compile time that this reference is required,but that's about it.

2
votes

According to this link, basically this annotation enables EJB to lookup external EJBs relatively to its context. Usually, there are more elegant ways to do that.

1
votes

As for the bonus question: Yes, the two annotations regarding transactions are repeating defaults: The default TransactionManagementType is CONTAINER (vs BEAN) and the - default - TransactionAttributeType REQUIRED simply states that if the bean is called within a transactional context the transaction is continued, otherwise a new transaction will be initiated (as opposed to, for example REQUIRES_NEW which will always create a new tx). This is actually in detail not as trivial as it sounds Cf. the EJB 3.1 spec:

"13.3.7 Specification of the Transaction Attributes for a Bean’s Methods

The Bean Provider of an enterprise bean with container-managed transaction demarcation may specify the transaction attributes for the enterprise bean’s methods. By default, the value of the transaction attribute for a method of a bean with container-managed transaction demarcation is the REQUIRED transaction attribute, and the transaction attribute does not need to be explicitly specified in this case.[...]"