blob: 5681e06c3bf3443ad5088f579676c5c515f10c1e [file] [log] [blame]
Title: Lookup of other EJBs Example
<a name="LookupofotherEJBsExample-Overview"></a>
# 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 the *java:comp/env* namespace of
bean *A*, bean *A* must declare a reference to bean *B*.
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, the *java:comp/env* namespace is shared by all servlets. This is
essentially equivalent to the *java: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.
<a name="LookupofotherEJBsExample-TheCode"></a>
# The Code
Here we show the code for *RedBean* and *BlueBean* and their shared
business local interface *Friend*.
{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/RedBean.java|lang=java}
{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/BlueBean.java|lang=java}
{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/Friend.java|lang=java}
The key items in the above are the following:
- *@EJB* has been used at the *class level* to declare *myFriend* in
the *java:comp/env* namespace of each EJB
- because both beans share the *same interface*, *Friend*, we need to
add **beanName** to the *@EJB* usage to specify the exact EJB we want
- for *BlueBean* the *java:comp/env/myFriend* name has been configured
to point to *RedBean*
- for *RedBean* the *java:comp/env/myFriend* name has been configured
to point to *BlueBean*
<a name="LookupofotherEJBsExample-Alternativetoannotations"></a>
## Alternative to annotations
If there is a desire to not use annotations, the above annotation usage is
equivalent to the following ejb-jar.xml
{snippet:url=openejb3/examples/lookup-of-ejbs-with-descriptor/src/main/resources/META-INF/ejb-jar.xml|lang=xml}
<a name="LookupofotherEJBsExample-Writingaunittestfortheexample"></a>
# 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
{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/test/java/org/superbiz/ejblookup/EjbDependencyTest.java|lang=java}
<a name="LookupofotherEJBsExample-Running"></a>
# Running
Running the example is fairly simple. In the "lookup-of-ejbs" directory of
the [examples zip](openejb:download.html)
, just run:
> $ mvn clean install
Which should create output like the following.
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.superbiz.ejblookup.EjbDependencyTest
Apache OpenEJB 3.1.5-SNAPSHOT build: 20101129-09:51
http://tomee.apache.org/
INFO - openejb.home =
/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs
INFO - openejb.base =
/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs
INFO - Configuring Service(id=Default Security Service,
type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager,
type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Found EjbModule in classpath:
/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs/target/classes
INFO - Beginning load:
/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs/target/classes
INFO - Configuring enterprise application: classpath.ear
INFO - Configuring Service(id=Default Stateless Container, type=Container,
provider-id=Default Stateless Container)
INFO - Auto-creating a container for bean BlueBean:
Container(type=STATELESS, id=Default Stateless Container)
INFO - Enterprise application "classpath.ear" loaded.
INFO - Assembling app: classpath.ear
INFO - Jndi(name=BlueBeanLocal) --> Ejb(deployment-id=BlueBean)
INFO - Jndi(name=RedBeanLocal) --> Ejb(deployment-id=RedBean)
INFO - Created Ejb(deployment-id=RedBean, ejb-name=RedBean,
container=Default Stateless Container)
INFO - Created Ejb(deployment-id=BlueBean, ejb-name=BlueBean,
container=Default Stateless Container)
INFO - Deployed Application(path=classpath.ear)
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.244 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0