Hola Vincent:
> -----Mensaje original-----
> De: Vincent Massol [mailto:[EMAIL PROTECTED]]
> Enviado el: jueves 26 de julio de 2001 22:20
> Para: Craig R. McClanahan; [EMAIL PROTECTED]
> Asunto: Re: WebappClassLoader question
>
<snip/>
> Now all of this is packaged in a war, classes A and B and in
> a jar put in
> WEB-INF/lib and class C is put in WEB-INF/classes. The junit
> jar is *not*
> put in WEB-INF/lib.
>
I'm lost here, where you put the Junit.jar? , because it will be on some
place? no? to allow you load classes from , no?, i think you need the
entire inheritance chain for resolving dependencies, so you need
Junit.jar in some place in classpath AFAIK.. this is the simple dumb
explanation i know, but is what i'm seeing on your example..
Can you make a simple main example trying to do what you want to do,
without involving a servlet container.. i dont know how you can load (
using reflection for it doesnt matter ) a class without his entire
inheritance chain present ...
Only a wild thought, i'm not an expert on anything so... take it me too
seriously .. :)
Saludos ,
Ignacio J. Ortega
> Calling the servlet A result in an error occurring between
> the logs "before
> error" and "after error" and the log "I would have thought
> here" is never
> printed because the error happens _before_ ... This is what I don't
> understand.
>
> Any idea ?
> Thanks a lot
> -Vincent
>
> ----- Original Message -----
> From: "Craig R. McClanahan" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>; "Vincent Massol"
> <[EMAIL PROTECTED]>
> Sent: Thursday, July 26, 2001 6:18 PM
> Subject: Re: WebappClassLoader question
>
>
> On Thu, 26 Jul 2001, Vincent Massol wrote:
>
> > Thanks Alex,
> >
> > I don't think the standard classloader mechanism is involved here. I
> believe
> > it is a 'feature' of Tomcat and more specifically of it's
> WebappClassLoader.
> > When you do standard java code and you have the following
> situation :
> >
> > 1st -> 2nd --- (using reflection) --> 3rd (not in classpath)
> >
> > then the error always happen in the 2nd class and you can
> put the code
> > between a try catch block and you'll be able to catch the
> > ClassNotFoundException. However what happens here is that the error
> happens
> > when calling a method on the 1st class that instanciates
> the 2nd class !
> > This is what I don't understand.
> >
> > Am I dreaming or is this a behaviour of Tomcat 4 ?
> >
>
> The web app class loader in Tomcat 4 is based on
> java.net.URLClassLoader,
> and has the same basic class loading behavior. In particular, when a
> class A is loaded, all the classes that A directly references
> (i.e. listed
> in import statements, used as a variable declaration, and so
> on) are also
> loaded. This is done recursively on the referenced classes, until the
> entire tree of references is resolved. If the load for class
> A fails, you
> will get ClassNotFoundException. However, if the load for one of the
> referenced classes fails, you will typically get
> NoClassDefError instead
> (and the class named in the error message may or may not be
> the one that
> is actually missing, which complicates debugging this problem
> tremendously
> :-).
>
> A good rule of thumb to avoid this kind of problem -- if you
> need to add
> classes to your CLASSPATH at compile time (when rebuilding the entire
> app), be sure all of those classes are visible to the web app
> at runtime.
>
> Using reflection, on the other hand, lets you defer loading
> of "dependent"
> classes until runtime, and you can deal with
> ClassNotFoundException errors
> that you might run into. Note however that, even if you load a class
> dynamically, *that* class still contains direct references to other
> classes that must all be resolved in the manner described above.
>
>
> > Thanks
> > -Vincent
> >
>
> Craig McClanahan
>
> PS: One place where the Tomcat 4 class loader *does* vary
> from the usual
> class loader behavior is in the order of places it looks to load a
> class. The usual pattern in Java2 is to delegate to the parent class
> loader first, then look locally. Tomcat 4 does the opposite
> -- it checks
> in /WEB-INF/classes and /WEB-INF/lib of your web application *before*
> looking up the parent class loader chain. This means that,
> if you have a
> class in the $CATALINA_HOME/lib directory (shared across web
> apps), and a
> version of that same class in your web app, the version in your webapp
> wins.
>
>
> > ----- Original Message -----
> > From: "Alex Fern�ndez" <[EMAIL PROTECTED]>
> > To: <[EMAIL PROTECTED]>
> > Sent: Wednesday, July 25, 2001 3:44 PM
> > Subject: Re: WebappClassLoader question
> >
> >
> > > 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
> (WebappClassLo
> > ader.java:1475)
> > > > at
> > > >
> >
> org.apache.catalina.loader.WebappClassLoader.findClass(WebappC
> lassLoader.jav
> > a:836)
> > > > at
> > > >
> >
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappC
> lassLoader.jav
> > a:1215)
> > > > at
> > > >
> >
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappC
> lassLoader.jav
> > a:1098)
> > > > at
> java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313)
> > > > at
> > > >
> >
> org.apache.commons.cactus.server.ServletTestRedirector.doPost(
> ServletTestRed
> > irector.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
> > > >
> > >
> >
> >
>
>