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