Overview
This example shows how to configure JNDI to lookup other EJBs using either the @EJB annotation or the ejb-jar.xml deployment descriptor.
There are a couple interesting aspects in this example intended to flush out some of the more confusing, and perhaps frustrating, aspects of referring to EJBs.
- beans themselves do not have JNDI names (this was only recently added in Java EE 6)
This is the most frustrating and hard to accept. Java EE 5 does not have a global namespace and therefore there is no singular name for your EJB. It does not matter what you do to your EJB, there is no standard way to "give" the bean a name that can be used by the application globally.
- each EJB owns its own private
java:comp/env
namespace (java:comp/env
is not global and cannot be treated that way) - names do not magically appear in
java:comp/env
, they must be explicitly added. - to get a reference to bean
B
in thejava:comp/env
namespace of beanA
, beanA
must declare a reference to beanB
.
You read this right. If you have 10 EJBs and all of them want to refer to bean B
, then you must declare bean B
as a reference 10 times (once for each of the 10 beans). There is no standard way in Java EE 5 to do this just once for all beans. In Java EE 6 there is a "java:global
" namespace, a "java:app
" namespace, and a "java:module
" namespace where names can be defined with the desired scope. Java EE 5 has only java:comp
.
There are two things which make this even more confusing:
- Servlets have always defined
java:comp/env
differently. In a webapp, thejava:comp/env
namespace is shared by all servlets. This is essentially equivalent to thejava:module
namespace in Java EE 6. Understand there is a conflict in definition here and that for EJBs,java:comp
is scoped at the component (the EJB itself) not the module as with webapps. - All vendors have some proprietary concept of global JNDI. So you may be able to lookup "
java:/MyBean
" or "MyBeanLocal
", but these are vendor-specific and non-portable.
As well this example shows some other interesting aspects of referring to EJBs:
- Two beans may use the same business interfaces, the interface alone does not necessarily identify the exact bean
- circular references are possible
To illustrate all of this, we have two simple @Stateless beans, RedBean
and BlueBean
. Both implement the same business local interface, Friend
. Both RedBean
and BlueBean
define java:comp/env/myFriend
differently which is allowed as java:comp
is a namespace that is private to each bean and not visible to other beans – so the names do not have to match.
The Code
Here we show the code for RedBean
and BlueBean
and their shared business local interface Friend
.
The key items in the above are the following:
@EJB
has been used at the class level to declaremyFriend
in thejava:comp/env
namespace of each EJB- because both beans share the same interface,
Friend
, we need to addbeanName
to the@EJB
usage to specify the exact EJB we want - for
BlueBean
thejava:comp/env/myFriend
name has been configured to point toRedBean
- for
RedBean
thejava:comp/env/myFriend
name has been configured to point toBlueBean
Alternative to annotations
If there is a desire to not use annotations, the above annotation usage is equivalent to the following ejb-jar.xml
Writing a unit test for the example
Writing an unit test for this example is quite simple. We need just to write a setup method to create and initialize the InitialContext, and then write our test methods
Running
Running the example is fairly simple. In the "lookup-of-ejbs" directory of the examples zip, just run:
$ mvn clean install
Which should create output like the following.