Hi Vincent!

I've run into the same situation a couple of times, when one class uses
a second class, and this second class uses a third one that is not
present.

1st -> 2nd -> 3rd (missing)

One would think that instantiating the 2nd should give an error, but
that loading the 2nd and/or instantiating the 1st should be ok. In fact,
all of the behaviors raise exceptions.

The following paragraph in ClassLoader javadoc might be of help:

"The methods and constructors of objects created by a class loader may
reference other classes. To determine the class(es) referred to, the
Java virtual machine calls the loadClass method of the class loader that
originally created the class."

Or, to find out what the JVM is doing, the spec is here:
http://java.sun.com/docs/books/vmspec/

Hope it helps.

Un saludo,

Alex.

> Vincent Massol wrote:
> 
> Hi,
> 
> Here is the situation :
> 
> * I have a class that makes use of JUnit (by extending the JUnit
> TestCase class). Let's call it ServletTestCase
> * I have a second class that is used to call a method in
> ServletTestCase, let's call it MyProxyClass
> * I have a third class (a servlet) that does _not_ make use of JUnit.
> Let's call it ServletTestRedirector. This class actually instanciate
> MyProxyClass and calls one of its method.
> * I package these classes in a war file and I _don't_ include
> junit.jar in this war file
> 
> When I access the servlet, I get a ClassNotFoundException on a JUnit
> class. So far it is normal ...
> When I debugged it, I have actually found that the error was happening
> when ServletTestRedirector was instancianting MyProxyClass (which does
> _not_ make use of JUnit) and before it was calling its method.
> 
> Here is the stack trace I got :
> 
> java.lang.NoClassDefFoundError: junit/framework/TestCase
>  at java.lang.ClassLoader.defineClass0(Native Method)
>  at java.lang.ClassLoader.defineClass(ClassLoader.java:486)
>  at
> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:111)
>  at
> 
>org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1475)
>  at
> org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:836)
>  at
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1215)
>  at
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1098)
>  at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313)
>  at
> 
>org.apache.commons.cactus.server.ServletTestRedirector.doPost(ServletTestRedirector.java:143)
> Here is what I imagined is happening (tell me if this correct or wrong
> !) :
> 
> As MyProxyClass is within the war file, the WebappClassLoader gets
> called to load it. The WebappClassLoader, in trying to find out the
> correct class, actually loads some other class in memory, and thus the
> ServletTestCase, which fails to load because the junit jar is not in
> the classpath.
> 
> Is that correct ?
> Don't you find it strange that the error about the missing class is
> reported when calling a class that has nothing to do with the problem
> ? It gets very hard to catch errors ...
> 
> For example, in MyProxyClass, the code that calls the ServletTestCase
> method is as follows :
> 
>         ServletTestCase testInstance = null;
>         try {
>             testClass = Class.forName(theClassName);
>             Constructor constructor = testClass.getConstructor(new
> Class[] { String.class });
>             testInstance =
> (ServletTestCase)constructor.newInstance(new Object[] { theMethod });
>         } catch (Exception e) {
>             logger.debug("Error instanciating class [" + theClassName
> + "]", e);
>             e.printStackTrace();
>             throw new ServletException("Error instanciating class [" +
> theClassName + "]", e);
>         }
> And there is never any exception caught here .... because the error
> happens earlier in the call stack, when the ServletTestRedirector
> instanciates MyProxyClass ...
> 
> ... or am I missing something ? :)
> 
> Thanks
> -Vincent Massol
>

Reply via email to