最近在OC4J 10g引用了weblogic10的jar包时,发现Local对象无法获取,总是报javax.naming.NameNotFoundException,于是分析了一下context.lookup是如何执行的。
在获取Local bean时,所用语句如下:
final InitialContext context = new InitialContext(); String jndiName = "java:comp/env/ejb/BusinessLocal"; Object object = context.lookup(jndiName );
解析new InitialContext();
new InitialContext()à
myProps = ResourceManager.getInitialEnvironment(environment); à
String[] jndiSysProps = helper.getJndiProperties();à
System.getProperties();
myProps的值为:
{java.naming.factory.initial=com.evermind.server.ApplicationInitialContextFactory,
java.naming.factory.url.pkgs=oracle.oc4j.naming.url:weblogic.jndi.factories:weblogic.corba.j2ee.naming.url}
解析context.lookup(jndiName );
context.lookup(jndiName ) à
context.getURLOrDefaultInitCtx(String name); à
NamingManager.getURLContext(scheme, myProps); à
NamingManager.getURLObject(scheme, null, null, null, environment); à
ResourceManager.getFactory(
Context.URL_PKG_PREFIXES, environment, nameCtx,
"."+scheme+"."+scheme+"URLContextFactory",defaultPkgPrefix);
分析ResourceManager.getFactory()源码
public static Object getFactory(String propName, Hashtable env, Context ctx, String classSuffix, String defaultPkgPrefix) throws NamingException { // Merge property with provider property and supplied default //从env获取java.naming.factory.url.pkgs的值 String facProp = getProperty(propName, env, ctx, true); if (facProp != null) facProp += (":" + defaultPkgPrefix); //注意在此时加上了默认的sun的com.sun.jndi.url else facProp = defaultPkgPrefix; // Cache factory based on context class loader, class name, and // property val ClassLoader loader = helper.getContextClassLoader(); //此时loader为simple.root:0.0.0 String key = classSuffix + " " + facProp; Map perLoaderCache = null; synchronized (urlFactoryCache) { perLoaderCache = (Map) urlFactoryCache.get(loader); if (perLoaderCache == null) {//第一次perLoaderCache为null perLoaderCache = new HashMap(11); urlFactoryCache.put(loader, perLoaderCache); } } synchronized (perLoaderCache) { Object factory = null; WeakReference factoryRef = (WeakReference) perLoaderCache.get(key); if (factoryRef == NO_FACTORY) { return null; } else if (factoryRef != null) {//第一次factoryRef为null factory = factoryRef.get(); if (factory != null) { // check if weak ref has been cleared return factory; } } // Not cached; find first factory and cache StringTokenizer parser = new StringTokenizer(facProp, ":"); String className; while (factory == null && parser.hasMoreTokens()) { className = parser.nextToken() + classSuffix; /* 这里className 的值分别为 oracle.oc4j.naming.url.java.javaURLContextFactory weblogic.jndi.factories.java.javaURLContextFactory weblogic.corba.j2ee.naming.url.java.javaURLContextFactory com.sun.jndi.url.java.javaURLContextFactory */ try { // System.out.println("loading " + className); factory = helper.loadClass(className, loader).newInstance(); } catch (InstantiationException e) { //略 } catch (IllegalAccessException e) { //略 } catch (Exception e) { // ignore ClassNotFoundException, IllegalArgumentException, // etc. } } // Cache it. perLoaderCache.put(key, (factory != null) ? new WeakReference( factory) : NO_FACTORY); return factory; } }
最后factory.getObjectInstance(urlInfo, name, nameCtx, environment);
当不加载weblogic的jar包时,
java.naming.factory.url.pkgs=oracle.oc4j.naming.url;
当className=oracle.oc4j.naming.url.java.javaURLContextFactory,返回的factory=null,所以最终使用的Factory是com.sun.jndi.url.java.javaURLContextFactory,这个时候没有问题;
当加载weblogic的jar包时,
java.naming.factory.url.pkgs=
oracle.oc4j.naming.url:
weblogic.jndi.factories:
weblogic.corba.j2ee.naming.url
使用的Factory是
weblogic.jndi.factories.java.javaURLContextFactory
而在获取Local bean时抛出javax.naming.NameNotFoundException。