I try to understand how the DI is working together with the @Resource annotation. In short, I have a code snippet which looks like :
The Counter is a remote interface - an interface annotated with the @Remote adnotation. In this case the container injects the counter bean in the variable counterBean, but how it locates this Bean. Somebody must make a mapping between the "mihai/bussines" name and the needed bean reference and this mapping must be know on the container.
My big question is where is this mapping done ?
[ September 24, 2008: Message edited by: Mihai Radulescu ] [ September 24, 2008: Message edited by: Mihai Radulescu ]
When you declare a dependency injection using annotations is the Container's responsibility to inject the corresponding entry from the environment. To do so it issues a JNDI lookup. In general, lookups of objects in the JNDI java: namespace are required to return a new instance of the requested object every time. In your example, the resource to be injected is inferred from the field class' type (Counter.class).
Refer to the following sections of the ejb core specification to get a clearer idea.
The container injects entries from the environment into the enterprise bean's fields or methods as specified by the bean's metadata annotations or the deployment descriptor.
The container makes the environment naming context available to the enterprise bean instances at runtime. The enterprise bean's instances can use the EJBContext lookup method or the JNDI interfaces to obtain the values of the environment entries.
Section 16.2.1 (Sharing of Environment Entries)
In general, lookups of objects in the JNDI java: namespace are required to return a new instance of the requested object every time. Exceptions are allowed for the following: � The container knows the object is immutable (for example, objects of type java.lang.String), or knows that the application can't change the state of the object. � The object is defined to be a singleton, such that only one instance of the object may exist in the JVM. � The name used for the lookup is defined to return an instance of the object that might be shared. The name java:comp/ORB is such a name.
In these cases, a shared instance of the object may be returned. In all other cases, a new instance of the requested object must be returned on each lookup. Note that, in the case of resource adapter connection objects, it is the resource adapter's ManagedConnectionFactory implementation that is responsible for satisfying this requirement.
Each injection of an object corresponds to a JNDI lookup. Whether a new instance of the requested object is injected, or whether a shared instance is injected, is determined by the rules described above.
The name you provided in your example is the name under which that resource is available in your bean's environment.
Thanks for your answer. But I still have one question : How the container knows which bean instance must be injected. The container knows the bean name (the JNDI name of the resource) and it search it in its context, but before this somebody must map the JNDI name to a resource.
Somebody must do a mapping between the JNDI name and the resource before the DI occurs, otherwise the container can not locate the resource. My question (still) is : where is mapping ?
I don't think the name specified in the annotation is used by the Container to get a reference to an EJB.
I'll quote a fragment form O'Reilly's book, which is the book I used:
@EJB ProcessPaymentLocal processPayment;
The specification isn't very detailed in terms of exactly how the EJB container should resolve this reference. To give you a feel for how this process works, let's see how the JBoss application server resolves this reference: 1. The only possible identifier for this EJB reference is the business interface type. The application server first looks for a unique EJB in the referencing EJB's EJB-JAR deployment that uses ProcessPaymentLocal as its local or remote interface. If more than one EJB uses the same business interface, it throws a deployment exception. 2. If the EJB-JAR is deployed as part of an Enterprise ARchive (.ear), it looks in other EJB-JARs for a unique EJB that uses the ProcessPaymentLocal interface. Again, if more than one EJB uses the same business interface, it throws a deployment exception. 3. If the EJB reference is not found in the .ear file, it looks for it in other global EJB-JAR deployments. If the beanName( ) attribute is specified, then JBoss uses the same search process, but it uses the beanName( )'s value as an additional identifier. If the mappedName( ) attribute is specified, then no search process is performed. The application server expects that a specific EJB is bound into the global JNDI under the mappedName( )'s value.
This is in section 184.108.40.206. Resolving EJB references. [ September 24, 2008: Message edited by: Sergio Tridente ]
Thanks fro your detailed answer, but I still have 2 questions.
The first question is about the @Resource and the EJB. In the "EJB in action" in on Chapterv 5, sub-chapter 5.2.1. I found the following information about the @Resource
.... However the (Resource) annotation can be also used for e-mail server resources, environment entries, Orb references or even EJB instances. ....
My second question is about the JNDI lock up done by hand. Here I mean something like :
can I use this kind of look up from a POJO client ? In this case the String argument for the lookup method will be the JNDI name descibed by you in the previous posts. I keep trying this but I get always a NammingException.
Originally posted by Mihai Radulescu: even EJB instances.
I did not know about that. I fail to see any reference to that in the ejb core specification. Section 220.127.116.11 (Injection of EJB References) states:
The Bean Provider uses the EJB annotation to annotate a field or setter property method of the bean class as a target for the injection of an EJB reference. The reference may be to a session bean�s business interface or to the local home interface or remote home interface of a session bean or entity bean.
Originally posted by Mihai Radulescu: can I use this kind of look up from a POJO client ? In this case the String argument for the lookup method will be the JNDI name descibed by you in the previous posts. I keep trying this but I get always a NammingException.
You certainly can use lookup for getting a reference to a session bean's remote interface. However, when we talk about clients that not reside in the same application server you need to use another mechanism to specify the JNDI name of your bean.
For example, in JBoss the default JNDI name of your bean's interface would be "MyBeanClass/remote" (for the bean's remote interface). In Glassfish it would be "com.mypackage.MyInterface", if MyInterface is a remote interface of the MyBeanClass' bean. Mapping a session bean to a JNDI name is done by the Deployer (role). How it would be done, depends on the Application Server implementation. For example, in Glassfish you can use the "META-INF/sun-ejb-jar.xml" descriptor:
Where: - The name specified in ejb-name corresponds to the name specified in @Stateless(name="MyBeanClass"), @Stateful(name="MyBeanClass") or the default name of the bean (the unqualified class name). - The name specified in jndi-name is the name you would use to perform a JNDI lookup of your bean's interface, in this case it would be "ejb/MyBeanNameForJNDI".
Please, understand that the name you specify in the @Stateless/@Stateful annotations is NOT necessarily the JNDI name (but it is in JBoss). Section 19.2 of the ejb core specification states:
Enterprise bean�s name. A logical name is assigned to each enterprise bean in the ejb-jar file. There is no architected relationship between this name and the JNDI name that the Deployer will assign to the enterprise bean. The Bean Provider can specify the enterprise bean�s name in the ejb-name element. If the enterprise bean�s name is not explicitly specified in metadata annotations or in the deployment descriptor, it defaults to the unqualified name of the bean class.
I hope this explanation would give you a better idea of what's going on. Nevertheless, I recommend you to read the ejb core specification, in this case chapters 16 and 19. [ September 25, 2008: Message edited by: Sergio Tridente ]
and thanks for your explanations, now I think I got an overview picture - or at least I hope. I am on beginning whit by EJB and I don't have to much knowledge/experince about - that why my questions are a little bit to easy but this I think will change.
For the moment I read the "EJB in action" by Debu Panda and paralel with this I try to "brush" a little the specifications. Do you think that the issue with bean DI with Resource is a failure in the book ?
I don't know if it is possible to use @Resource to get a reference to an EJB, maybe by specifying mappedName and defining the reference name in your Container's specific configurations files. But that's not the point: it is not defined in the specifications, so from the exam point of view you should not care about that possibility. However, if you are curious and have the time, I encourage you to try it by yourself: knowledge cannot hurt (only what people do with knowledge).
About your questions being a "little bit easy", I do not agree. I was not able to find the answer to those questions until I went through the specification several times, specifically chapter 19 which I have read three days before the exam!