EJB Programmatic Lookup

In our previous post we learnt about EJB references and EJB injection. Even though EJB injection is a powerful container facility that eases modular application development, sometimes performing a programmatic EJB lookup is instead desirable.

Let’s suppose, for example, that a set of distinct EJBs implement a common strategy, defined by a common business interface. Depending on the result of some choice algorithm (such as a business rule), a different strategy is chosen and hence a different EJB will be executed in the scope of a business process. In such a scenario the target EJB cannot be chosen at injection time since annotation elements (such as @EJB’s) are defined at compilation time and deployment descriptors are defined at deployment time. The only solution to this problem is a programmatic JNDI lookup.

The same mechanisms described in the previous posts will apply. EJB references will be declared and linked against a name in your application private namespace using the @EJB annotation or the corresponding elements of your Java EE module deployment descriptor.

Lookup in the Application Private Namespace

The portable way to establish an indirection level between the namespace used in your lookup code and the target EJBs is using your application private namespace. This kind of indirection level is quite common in the Java EE platform: not only it is used for EJB references but for all sorts of resource references such as JDBC data sources, JMS queues, JavaMail sessions, etc.

In the case of EJBs, as seen in our previous post, you simply define a private name used by lookup and injection code of your application. This is a private application-scoped name and is a subelement of the java:comp/env JNDI entry. With the aid of the @EJB annotation and of the deployment descriptors, you can establish a link between this name and a target EJB. The only difference is that instead of relying on the container to inject a reference into a component of yours, your application algorithms will choose the appropriate EJB and will look it up dynamically.

As we’ve seen in part 2 of this series, the @EJB annotation can be used at type, method and field level to declare a reference to an EJB and, optionally, to link it to the target bean without the need of writing any deployment descriptor code.

If the case of dynamic programmatic JNDI lookup, instead of annotating a field (or a property) as an injection target, you can annotate a class (such as a Servlet) to establish a reference to an EJB. In the following example we’ll see how to do it with both the @EJB annotation and the deployment descriptor. 

Declaring a Reference to an EJB

In the test servlet we’ve used throughout our previous posts, we can use the @EJB annotation at class level to declare a reference to an EJB in the private name ejb/ejbLocalRef:

@EJB(name = "ejb/ejbLocalRef",
     beanInterface = es.reacts.SessionTest0Local.class,
     beanName = "EJBServer1.jar#SessionTest1")
public class ServletTest1 extends HttpServlet {
  [...]
}

The annotation in the previous example is functionally equivalent to the following deployment descriptor (in this case, the web.xml file) fragment:

<ejb-local-ref>
  <ejb-ref-name>ejb/ejbLocalRef</ejb-ref-name>
  <ejb-ref-type>Session</ejb-ref-type>
  <local>es.reacts.SessionTest0Local</local>
  <ejb-link>EJBServer1.jar#SessionTest1</ejb-link>
</ejb-local-ref>

The most important difference between the @EJB semantics in this example and in the examples in the previous post is that in this case we’re providing all of the information required to establish the reference and the link to the target EJB without injecting nor even relying on information coming from the injection target (such as the beanInterface).

Although the annotation is applied at a class level, it is effectively equivalent to adding the corresponding deployment descriptor elements and, therefore, the declared reference will be available throughout your Java EE module. In this case, any other servlet in your Java EE web module will be able to inject or lookup the very same EJB referenced by the ejb/ejbLocalRef name:

@EJB(name = "ejb/ejbLocalRef")
SessionTest0Local lc4;

Additional “plumbing” here is not necessary since the reference declaration contains all of the information that is required to resolve the target EJB.

EJB Programmatic Lookup

Since a reference has been declared and linked, our code is now able to make a JNDI lookup and retrieve a reference to the desired business interface of our target EJB. The JNDI lookup code is the good ole lookup code we’re used to (with a little difference we’ll point out later):

InitialContext ctx = new InitialContext();
Object obj = ctx.lookup("java:comp/env/ejb/ejbLocalRef");
if (obj instanceof SessionTest0Local) {
  SessionTest0Local lc = (SessionTest0Local) obj;
  [...]
}

(* Please note that the previous fragment has been stripped of the required exception handling code.)

The good news with EJB 3.0 is that you don’t need to narrow the reference using the PortableRemoteObject.narrow() method as was required by the EJB v. 2.1 Specification. In the example code we can directly test the reference with the instanceof operator and use a Java native cast to set a SessionTest0Local reference.

There’s absolutely no difference between looking up local and remote business interfaces. Only in the case you rely on the deployment descriptor, the declaration and the linking of the EJB references will be performed using an <ejb-ref> or an <ejb-local-ref> according to the EJB business interface type. As far as it concerns your application, the lookup code will be identical.

Patterns

In scenarios in which you don’t use EJB injection and rely on lookup instead, there are both advantages and disadvantages in using annotations or the deployment descriptors to declare and link EJB references.

The advantages of annotations is that they’re easier to write and use than the corresponding deployment descriptors elements. Moreover, as far as it concerns my experience, IDE support for code autocompletion might be a better tool than some deployment descriptor editors which are “obscure”, at best (with notable exceptions such as Oracle JDeveloper’s and NetBeans’.)

The advantage of the deployment descriptor is that it can centralize resource references declarations. If the same EJB reference is used throughout the code of your Java EE module and is not confined to a single class, a best option is using the deployment descriptor to declare and link the EJB (and other resource) reference and avoid using annotations at all. This is a design choice that has to be taken carefully. In the uses cases in which a lookup is desirable, chances are that EJB linking might be performed in the application assembly and deployment stages. Having references well documented and declared in a central repository might still be preferable instead of having @EJB annotation scattered throughout your code and the task of the deployer might get considerably eased.

Reference: EJB Programmatic Lookup from our JCG partner Grey at the The Grey Blog.

Related Articles :
Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


+ five = 9



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books