Thanks to all who helped on this.
Andrew was right, and Craig too .... and I was wrong !

Here is what happened. My code was written like this :

        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) {

As Andrew pointed out, this would never have caught the NoClassDefFoundError
error because it is not a subclass of Exception. Modifying it to Throwable
did not help. However the error was that ServletTestCase was defined outside
the try catch block and thus the error was thrown there and would be caught
in the first class because I was catching Throwable there ...

So it is a stupid error. However I learnt how the Tomcat class loader worked
which I didn't know. I also learned that the error raised when a class is
not found by the class loader was NoClassDefFoundError and not (as I thought
initially) ClassNotFoundException !

So I'll to rewrite my code as follows :

        Object dummy; <-- cannot use ServletTestCase here as it might raise
a NoClassDefFoundError!
        try {
            testClass = Class.forName(theClassName);
            Constructor constructor = testClass.getConstructor(new Class[]
{ String.class });
            dummy = (ServletTestCase)constructor.newInstance(new Object[]
{ theMethod }); <--- need the cast to catch NoClassDefFoundError
        } catch (Exception e) {
            ...
        }
        ServletTestCase testInstance = (ServletTestCase)dummy;

... which I don't find that easy to write at first ... (I'll need to put
some comments to explain the trick) !

You might say, why catch this error and not let it be thrown by the
container itself ... However the problem with this is that the error that
gets displayed does not give any clue that the initial problem was a
NoClassDefFoundError, it just prints the following in the console :

     [java] StandardWrapperValve[ServletRedirector]: Servlet.service() for
servlet ServletRedirector threw exception
     [java] javax.servlet.ServletException: Servlet execution threw an
exception
     [java] javax.servlet.ServletException: Servlet execution threw an
exception
     [java]     at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Application
FilterChain.java:269)

which is absolutely not explicit ! Wouldn't it be possible to improve Tomcat
so that it chains the exception and also prints the original excpetion in
the console ?

Thanks again.
-Vincent

----- Original Message -----
From: "Andrew Inggs" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Friday, July 27, 2001 10:01 AM
Subject: RE: WebappClassLoader question


> Hi Vincent
>
> You seem to be missing at least two things here:
>
> 1. In your original post you said:
>
> > 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.
>
> This does not look right.  You say MyProxyClass does not make
> use of JUnit, but it *does*.  This is the line that causes it to:
>
> > testInstance = (ServletTestCase)constructor.newInstance(new Object[] {
> theMethod });
>
> You see here you are explicitly referencing ServletTestCase which
> extends junit.framework.TestCase, this introduces the dependency.
>
> 2. You seem to be assuming that NoClassDefFoundError extends
> Exception, but it doesn't.  If you want to catch a
> NoClassDefFoundError you'll have to catch it directly, or one of
> its superclasses (java.lang.LinkageError, java.lang.Error, or
> java.lang.Throwable).  This is why "I would have thought here"
> never gets printed out:
>
> >       } catch (Exception e) {
> >         log("I would have thought here");
> >       }
>
> As an aside, I'm not sure what you are trying to achieve here?
> You don't have junit.jar in your classpath, and then you're say
> you get this strange error.  The details aside, isn't that what
> you'd expect :-)?  Even if you hadn't referenced ServletTestCase
> directly, you still wouldn't have been able to instantiate it
> using reflection without junit.jar in the classpath.  What are
> you really trying to achieve?
>
> -- Andrew
>

Reply via email to