Mark,
Thanks for your patch ! Unfortunately I don't think there is an easy solution for doing what you're suggesting. We're trying to break the J2EE model and I don't believe you'll succeed in a consistent way (i.e. it may work on one server but will fail on another). The classloaders are hierarchical (webappclassloader -> ejbclassloader -> system classloader). Thus the problem is if you put a class in a parent class loader that needs to call a child class loader, it will fail. You'll have to move the called classloader to the parent. Thus I believe there are only 2 valid configurations : 1/ All classes/jars outside WEB-INF/lib and in your system classpath (yuck !) 2/ All needed classes/jars in WEB-INF/lib and WEB-INF/classes (The Way to go) This is done voluntarily by the J2EE spec. (although it could be viewed as a limitation and future spec may remove it). This is to compartiment webapps so that they live in their own space. Thus, for example, you can dynamically reload a webapp without impacting the others. Same for EARs. If you need more convincing (;-)) here is an email posted by Craig (he is an authority when it comes to Tomcat . among other things) : "Roytman, Alex" wrote: > I would like to use Thread.currentThread().getContextClassLoader() with > Tomcat 3.2 to resolve one common problem when class from system classpath > needs to call something loaded by tomcat context's loader. As far as I > understand Tomcat 3.2 suppose to run under jdk1.1 so it does not do > Thread.currentThread().setContextClassLoader() before it hands control to a > Servlet. > If Tomcat 3.2 runs in a Java2 environment, it does in fact call setContextClassLoader(), assigning the webapp class loader for the currently selected web application to the current request thread. Tomcat 4.0 does this under all circumstances, because it requires a Java2 environment. However, the fact that this occurs has nothing to do with your issue. Under any version of Tomcat, what you are asking for does not work. More importantly, it *should not* work. Class loaders are only allowed to look *up* the class loader hierarchy (and, of course, such a hierarchy exists only in a Java2 environment). Classes that are loaded from the system class path *do not* have any access to classes loaded only by a webapp's class loader. If they did, it would violate the whole concept of a web application being self contained. If you have a class that needs access to classes that are loaded from WEB-INF/classes and WEB-INF/lib, that class itself must be loaded from one of those two places (and therefore loaded by the webapp class loader). Craig McClanahan For these reasons, I'm not too keen to include your patch for the above-mentionned reasons. Note: Be careful about what container classloader report as error. They will report thing such as cannot load class A but in fact the error is because they browsed the dependency tree and couldn't load a class that is called by one of the descendant of the initial class . Thanks -Vincent -----Original Message----- From: Volkmann, Mark [mailto:[EMAIL PROTECTED]] Sent: 21 February 2002 14:12 To: 'Fred Loney'; '[EMAIL PROTECTED]' Subject: RE: java.lang.NoClassDefFoundError: org/apache/cactus/ServletTestCase We did resolve the problem, but the solution isn't pretty. We had to patch Cactus to get it to work. I've attached a class we added. We replaced all calls to Class.forName in the Cactus source with calls to ClassLoaderHelper.forName. This allows classes in your web app., such as your unit test code, to find classes in your server classpath, such as Cactus and Log4J classes. We think the problem has something to do with using Log4J in our application. We put log4j.jar in our server classpath and this seems to be a problem for Cactus without the patch. I've also attached our custom cactus.jar file that contains these changes. All you need to do to try it is put all the JARs cactus needs (aspectjrt.jar, cactus.jar, httpunit.jar, junit.jar and log4j.jar) in your server classpath instead of your web app. Another advantage to this approach is that you don't have to include all those JARs in every web application. That's a big plus for us because we are testing around 20 web apps. Perhaps this change should become part of the normal Cactus codebase! If this is a bad idea, I'd like to hear why. <<ClassLoaderHelper.java>> <<cactus.jar>> -----Original Message----- From: Fred Loney [SMTP:[EMAIL PROTECTED]] Sent: Wednesday, February 20, 2002 9:23 PM To: Volkmann, Mark Subject: java.lang.NoClassDefFoundError: org/apache/cactus/ServletTestCase Were you able to resolve the problem? I have the same situation and would appreciate any advice on resolution. Classloaders are truly the bane of webapp development. Thanks. ---- Mark Volkmann wrote: Here's part of the stack trace I'm getting. cactus.jar, junit.jar and aspectjrt.jar are in the WEB-INF/lib of the WAR file of my web application. They are not available through my CLASSPATH. How could it find AbstractTestCaller, but not find ServletTestCase? java.lang.NoClassDefFoundError: org/apache/cactus/ServletTestCase at java.lang.ClassLoader.defineClass0(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:486) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:111) at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericCla ssLo ader.java:339) at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoa der. java:156) at java.lang.ClassLoader.loadClass(ClassLoader.java:297) at java.lang.ClassLoader.loadClass(ClassLoader.java:290) at java.lang.ClassLoader.loadClass(ClassLoader.java:253) at weblogic.utils.classloaders.ChangeAwareClassLoader.loadClass(ChangeAware Clas sLoader.java:43) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:120) at org.apache.cactus.server.AbstractTestCaller.getTestClassClass(AbstractTe stCa ller.java:326) ************************************************************************ *************** WARNING: All e-mail sent to and from this address will be received or otherwise recorded by the A.G. Edwards corporate e-mail system and is subject to archival, monitoring or review by, and/or disclosure to, someone other than the recipient. ************************************************************************ ***************
