= Lookup of other EJBs Example
:index-group: EJB
:jbake-date: 2018-12-05
:jbake-type: page
:jbake-status: published

= 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 look up "_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_.
* link:https://github.com/apache/tomee/blob/main/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/RedBean.java[RedBean.java]
* link:https://github.com/apache/tomee/blob/main/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/BlueBean.java[BlueBean.java]
* link:https://github.com/apache/tomee/blob/main/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/Friend.java[Friend.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_

== Alternative to annotations

If there is a desire to not use annotations, the above annotation usage
is equivalent to the following `ejb-jar.xml`
link:https://github.com/apache/tomee/blob/main/examples/lookup-of-ejbs-with-descriptor/src/main/resources/META-INF/ejb-jar.xml[ejb-jar.xml]

= Writing a unit test for the example

Writing a 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

link:https://github.com/apache/tomee/blob/main/examples/lookup-of-ejbs/src/test/java/org/superbiz/ejblookup/EjbDependencyTest.java[EjbDependencyTest.java]

= Running

Running the example is fairly simple. In the "lookup-of-ejbs" directory
of the link:https://github.com/apache/tomee/tree/main/examples/lookup-of-ejbs[lookup-of-ejbs example], just run:

___________________
$ mvn clean install
___________________

Which should create output like the following.

[source,java]
----
-------------------------------------------------------
 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

[source,properties]
----
Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
----
