h1. 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. h1. 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}} h2. 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} h1. 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} h1. Running Running the example is fairly simple. In the "lookup-of-ejbs" directory of the [examples zip|OPENEJB:Download], just run: {quote} $ mvn clean install {quote} Which should create output like the following. {noformat} ------------------------------------------------------- T E S T S ------------------------------------------------------- Running org.superbiz.ejblookup.EjbDependencyTest Apache OpenEJB 3.1.5-SNAPSHOT build: 20101129-09:51 http://openejb.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 {noformat}