About Mike Miller

Mike is a software developer who loves to learn how things work. A Java programmer who caught the Groovy & Grails itch and is always looking for opportunities to include them as part of the solution.

JBoss AS7 JNDI & EJB 3.1 Naming changes

As a result of the “feature train” continuing to march on and us not keeping our software stack up-to-date, our team finds ourselves in the un-enviable position of having to migrate:

  • JBoss 4.2.3 to AS 7.1.x (currently looking at 7.1.1)
  • EJB 2.1 to EJB 3.1
  • Hibernate 2 to Hibernate 3 or 4

in quick fashion.  I mean, who wants to ship a new release with 8-10 year old software, not me! The following is the result of some research I did while looking at upgrading from JBoss 4.2.3 with EJB 2.1 to AS 7.1.x with EJB 3.1.  I am sure there will be more
 
posts related to this migration in the near future, but this one is related to changes in the JNDI naming area.

In the past/current

In our current code, the JNDI naming has been very simple:

  1. We concatenated “ejb/” with the name of the remote Session Bean interface in the deployment descriptor to indicate the name that the service should be bound to.
  2. In the code, we use the following code to handle the JNDI lookup.  The really nice part was that the same code could be used by remote clients AND on the server, within the container.

Current Code

Hashtable properties = new Hashtable();
properties.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
properties.put("java.naming.provider.url", "jnp://localhost:1099");
Context ctx = new InitialContext(properties);
Object ref = ctx.lookup(jndiName);

AS7 and EJB 3.1

The EJB 3.1 spec has made some changes to mandate portable JNDI names for EJBs and you inherit this in AS 7.1.1.   The other tricky thing I found was that I could no longer use the exact same lookup code from our remote clients and the server.

AS 7 now has two options for remote EJB invocation.  The information you need can be found in the JBoss docs, it just didn’t hit me over the head!  After struggling with this issue for a couple days, I decided to create a small program to help make the differences (hopefully) very clear.  Below is the program that I created to invoke a stateless session bean from a remote client.   I deployed the “ejb-remote” sample from the 7.1 Quick Start samples.  The code attempts to load the remote service using both remote methods.  The expectation is that for the first set of lookups, the first lookup is successful and the second, using the “ejb:/” naming format fails.  Then I add the Context.URL_PKG_PREFIXES property with a value of “org.jboss.ejb.client.naming” to the jndi properties passed to the InitialContext constructor and repeat the lookups.  Now, both lookups should be successful.  I have included all the JNDI properties in the code rather than relying on a copy of “jboss-ejb-client.properties” or “jndi.properties” being picked up from the classpath.

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import java.util.Hashtable;

public class EJBClient {

     private static String[] JNDINAME = {
          "jboss-as-ejb-remote-app/CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator", 
          "ejb:/jboss-as-ejb-remote-app/CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator" 
     };

     private Hashtable jndiProps;

     public EJBClient() {
       // setup 'base' jndi properties - no jboss-ejb-client.properties being picked up from classpath!
       jndiProps = new Hashtable();
          jndiProps.put("java.naming.factory.initial",
"org.jboss.naming.remote.client.InitialContextFactory");
          jndiProps.put(InitialContext.PROVIDER_URL, "remote://localhost:4447");
          jndiProps.put("jboss.naming.client.ejb.context", true);

          // needed for remote access - remember to run add-user.bat
          jndiProps.put(Context.SECURITY_PRINCIPAL, "client");
          jndiProps.put(Context.SECURITY_CREDENTIALS, "password");
     }

    public void doLookups() {
         // the 'exported' namespace
         for (int i = 0; i < JNDINAME.length; i++) {
               lookup(JNDINAME[i]);
          }

         // This is an important property to set if you want to do EJB invocations via the remote-naming project
        jndiProps.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

        // now with the ejb
        for (int i = 0; i < JNDINAME.length; i++) {
               lookup(JNDINAME[i]);
          }
    }

    private void lookup(String name) {
         System.out.println("Lookup name="+name);

         Context ctx = null;
        try {
               ctx = new InitialContext(jndiProps);
               Object ref = ctx.lookup(name);
               System.out.println("...Successful");
          } catch (NamingException e) {
               System.out.println("...Failed");
               //System.out.println(e.getMessage());
               e.printStackTrace();
          } finally {
               if (ctx != null) {
                    try {
                         ctx.close();
                    } catch (NamingException e) {}
               }
          }
    }

    public static void main(String[] args) throws Exception {
         EJBClient client = new EJBClient();
         client.doLookups();

         System.out.println("Done!");
    }

}

AS7 on the server-side

Now the easy part, doing the JNDI lookups on the server are very similar to the old way, except that you still need to format the JNDI name according to the new specs and the naming factory is no longer the jnp version!

Hashtable jndiProps = new Hashtable();
    jndiProps.put("java.naming.factory.initial", "org.jboss.as.naming.InitialContextFactory");
    ctx = new InitialContext(jndiProps);
    Object ref = ctx.lookup(jndiName);

Conclusion

As I said earlier, the information was/is in the JBoss documentation, but I probably read past it several times.  What I was looking for was an example showing loading the EJBs from both the client and the server.

Hope this helps!
 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


7 − = six



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
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.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close