Hi all!

    A lot of people has been having problems with Tomcat 3.2, classloaders,
jndi, jndi.properties, rmi and stubs when trying to call ejbs from Tomcat in
a different JVM. The problem is simple: because jndi and rmi classes are
loaded by the system (or bootstrap, I can't remember it but it really
doesn't matters) classloader -see
<jdk1.3>\docs\tooldocs\findingclasses.html - they can not see the resources
and classes of your context (loaded by the context classloader, which is a
descendant -i mean in the classloader delegation hierarchy- of the system
classloader).
    An obvious and bad solution is to put your classes in the CLASSPATH
(don't do this!) to allow them to be loaded once for all of your contexts by
the system classloader.
    Instead, to fix the problem you should add the request interceptor
showed below to your server.xml (I have read an email saying that it should
be the last request interceptor in the chain so I put it the last, but I
haven't tried with another combinations):

        <RequestInterceptor
             className="org.apache.tomcat.request.Jdk12Interceptor" />

    This is in order to call the Thread.setContextClassLoader() during each
request. The following is taken from a post by C. McClanahan in tomcat-user:
"Note that Tomcat 4.0, because it is guaranteed a Java2 platform as a
prerequisite, calls Thread.setContextClassLoader() on every request by
default".
    But even after doing this, jndi.properties in your WEB-INF/classes (or
in a .jar in WEB-INF/lib) won't be loaded. Keep reading the following
paragraphs quoted from an email by Christopher Audley in tomcat-dev!

""
The following discussion applies to tomcat 3.2.1 running under Sun JDK 1.3

I spent this afternoon tracking down why a call to new InitialContext()
from a web application did not appear to be finding the jndi.properties
located under WEB-INF/classes.  I am using the Jdk12Interceptor and
verified that Thread.currentThread().getClassLoader() was the tomcat
AdaptiveClassLoader before the call to new InitialContext().  After some
investigation I determined that the JNDI implementation uses the
classloader method getResources to find all occurances of the file
jndi.properties in the classpath.  AdaptiveClassLoader does not have
this method implemented, the default implementation calls findResources
which simply returns an empty Enumeration unless overriden.

Attached are patches to AdaptiveClassLoader and ClassRepository to
implement findResources so that JNDI will behave correctly when a
jndi.properties is placed in the web application classpath.  I have
moved some code from AdaptiveClassLoader to ClassRepository to avoid
code duplication and changed the implementation of getResource to
findResource for consistency.

I hope that this can be incorporated into the sources before 3.2.2.
""

    Finally, after aplying the patch (I've attached it as you can see) and
recompiling the sources you get the desired behaviour.

See you,
    Carlos

--------------------------------------------------------------


diff -ubr
jakarta-tomcat-3.2.1-src.orig/src/share/org/apache/tomcat/loader/AdaptiveCla
ssLoader.java
jakarta-tomcat-3.2.1-src/src/share/org/apache/tomcat/loader/AdaptiveClassLoa
der.java
---
jakarta-tomcat-3.2.1-src.orig/src/share/org/apache/tomcat/loader/AdaptiveCla
ssLoader.java Sun Mar 11 19:21:12 2001
+++
jakarta-tomcat-3.2.1-src/src/share/org/apache/tomcat/loader/AdaptiveClassLoa
der.java Sun Mar 11 18:40:46 2001
@@ -762,69 +762,45 @@
      * @param   name    the name of the resource, to be used as is.
      * @return  an URL on the resource, or null if not found.
      */
-    public URL getResource(String name) {
-        if( debug > 0 ) log( "getResource() " + name );
-        // First ask the parent class loader to fetch it, if possible
-        URL u = null;
-        if (parent != null) {
-            u = parent.getResource(name);
-            if (u != null)
-                return (u);
-        }
-        // Second ask the system class loader to fetch it from the
classpath
-        u = getSystemResource(name);
-        if (u != null) {
-            return u;
-        }
-
+    protected URL findResource(String name) {
         if (name == null) {
             return null;
         }

-        // Third, check our own repositories
+        // check our own repositories
         Enumeration repEnum = repository.elements();
         while (repEnum.hasMoreElements()) {
             ClassRepository cp = (ClassRepository) repEnum.nextElement();
-            File file = cp.getFile();
-            // Construct a file://-URL if the repository is a directory
-            if (file.isDirectory()) {
-                String fileName = name.replace('/', File.separatorChar);
-                File resFile = new File(file, fileName);
-                if (resFile.exists()) {
-                    // Build a file:// URL form the file name
-                    try {
-                        return new URL("file", null,
resFile.getAbsolutePath());
-                    } catch(java.net.MalformedURLException badurl) {
-                        badurl.printStackTrace();
-                        return null;
-                    }
+            URL resourceURL = cp.findResource(name);
+            if ( resourceURL != null )
+                return resourceURL;
                 }
-            }
-            else {
-                // a jar:-URL *could* change even between minor releases,
but
-                // didn't between JVM's 1.1.6 and 1.3beta. Tested on JVM's
from
-                // IBM, Blackdown, Microsoft, Sun @ Windows and Sun @
Solaris
-                try {
-                    ZipFile zf = new ZipFile(file.getAbsolutePath());
-                    ZipEntry ze = zf.getEntry(name);

-                    if (ze != null) {
-                        try {
-                            return new URL("jar:file:" +
file.getAbsolutePath() + "!/" + name);
-                        } catch(java.net.MalformedURLException badurl) {
-                            badurl.printStackTrace();
-                            return null;
-                        }
-                    }
-                } catch (IOException ioe) {
-                    ioe.printStackTrace();
+        // Not found
                     return null;
                 }
+
+    /**
+     * Find all occurences of a given resource in the class loaders
+     * repositories.
+     *
+     * @param   name    the name of the resource, to be used as is.
+     * @return  an Enumeration of URLs of to this resource.
+     */
+    protected Enumeration findResources(String name) {
+        if( debug > 0 ) log( "findResources() " + name );
+
+        Vector urls = new Vector( repository.size() );
+        if ( name != null ) {
+            Enumeration repEnum = repository.elements();
+            while( repEnum.hasMoreElements() ) {
+                ClassRepository cp = (ClassRepository)
repEnum.nextElement();
+                URL resourceURL = cp.findResource(name);
+                if( resourceURL != null )
+                    urls.add( resourceURL );
             }
         }
-
-        // Not found
-        return null;
+        return urls.elements();
     }

     public String toString() {
diff -ubr
jakarta-tomcat-3.2.1-src.orig/src/share/org/apache/tomcat/loader/ClassReposi
tory.java
jakarta-tomcat-3.2.1-src/src/share/org/apache/tomcat/loader/ClassRepository.
java
---
jakarta-tomcat-3.2.1-src.orig/src/share/org/apache/tomcat/loader/ClassReposi
tory.java Sun Mar 11 19:22:31 2001
+++
jakarta-tomcat-3.2.1-src/src/share/org/apache/tomcat/loader/ClassRepository.
java Sun Mar 11 19:01:44 2001
@@ -61,6 +61,8 @@
 import java.io.*;
 import java.lang.*;
 import java.util.*;
+import java.util.zip.*;
+import java.net.*;

 public class ClassRepository {
     private File file;
@@ -77,5 +79,43 @@

     public Object getProtectionDomain() {
  return protectionDomain;
+    }
+
+    public URL findResource(String name) {
+        if (file.isDirectory()) {
+            String fileName = name.replace('/', File.separatorChar);
+            File resFile = new File(file, fileName);
+            if (resFile.exists()) {
+                // Build a file:// URL form the file name
+                try {
+                    return new URL("file", null,
resFile.getAbsolutePath());
+                } catch(java.net.MalformedURLException badurl) {
+                    badurl.printStackTrace();
+                    return null;
+                }
+            }
+        }
+        else {
+            // a jar:-URL *could* change even between minor releases, but
+            // didn't between JVM's 1.1.6 and 1.3beta. Tested on JVM's from
+            // IBM, Blackdown, Microsoft, Sun @ Windows and Sun @ Solaris
+            try {
+                ZipFile zf = new ZipFile(file.getAbsolutePath());
+                ZipEntry ze = zf.getEntry(name);
+
+                if (ze != null) {
+                    try {
+                        return new URL("jar:file:" + file.getAbsolutePath()
+ "!/" + name);
+                    } catch(java.net.MalformedURLException badurl) {
+                        badurl.printStackTrace();
+                        return null;
+                    }
+                }
+            } catch (IOException ioe) {
+                ioe.printStackTrace();
+                return null;
+            }
+        }
+        return null;
     }
 }



Reply via email to