On May 2, 2008, at 10:19 PM, ManojS wrote:


Hi,

I have an issue while looking up an EJB using service locator pattern. I have a "ServiceLocator" class which is being used everywhere in my code to lookup any EJB. But now when I use openEJB (version 3.0) it is throwing a "javax.naming.NamingException" with message, "Name GenConfigFacadeEJB not
found".

My service locator class is as follows:
//imports I removed for here ...
public class ServiceLocator {
        private static Context context = null;
        static {
                System.setProperty( 
javax.naming.Context.INITIAL_CONTEXT_FACTORY,
"org.openejb.client.LocalInitialContextFactory");
                System.setProperty( javax.naming.Context.URL_PKG_PREFIXES,
"org.openejb.client" );
                context =  new InitialContext();
        }

It's likely that the vm has already pulled and cached the value of INITIAL_CONTEXT_FACTORY, it looks for the default only once and is probably pointing to Tomcat. If the NameNotFoundException stack trace doesn't show any openejb classes, this is definitely what happened.

Best bet is to construct your InitialContext like so:

  static {
      Properties p = new Properties();
      p.setProperty( javax.naming.Context.INITIAL_CONTEXT_FACTORY,
                     "org.openejb.client.LocalInitialContextFactory");
      context =  new InitialContext(p);
  }

I left the URL_PKG_PREFIXES property out as I know that one is pulled and cached very early in startup and Tomcat owns the "java:" prefix, which is good.

That should fix the issue.

I like your service locator approach. Some recommendations for you on that.

updated openejb-jar.xml:

  <?xml version="1.0" encoding="UTF-8"?>
  <openejb-jar>
    <properties>
      openejb.deploymentId.format = {ejbName}
      openejb.jndiname.format = {deploymentId}/{interfaceClass}
    </properties>
  </openejb-jar>

updated service locator using generics:

public static <T extends EJBHome> T getEJB(String ejbName, Class<T> homeClass) throws NamingException {
        Object objref = null;
        try {
objref = context.lookup(ejbName + "/" + homeClass.getName());
        } catch (NamingException e) {
            objref = context.lookup("java:comp/env/" + ejbName);
        }
        T home = (T) PortableRemoteObject.narrow(objref, homeClass);
        return home;
    }

then it can be used with no cast as:

GenConfigFacadeHome home = ServiceLocator.getEJB("GenConfigFacadeEJB",GenConfigFacadeHome.class);


Reason for the updated openejb.jndiname.format is that you have two interface one local and one remote and with the format set to {deploymentId} only one interface will be bound. Since your locator uses ejbName and home interface class, using the same pattern in your jndiname.format has advantages.

The updated getEJB method signature with <T extends EJBHome> is identical to having the method return EJBHome, which is why I left it that way when making it generic. But, if you yank the "extends EJBHome" you can use the same method to lookup your EJBLocalHome interaces as well. So that'd be:

public static <T> T getEJB(String ejbName, Class<T> homeClass) throws NamingException {...}


-David






Reply via email to