> craigmcc 01/06/22 14:57:08
>
> Log:
> Add some unit tests for bean references from a servlet (Session01 or
> Session03) to beans in the following locations:
> * SessionBean is in the same /WEB-INF/lib/tester.jar JAR file as the
> servlet classes are
> * UnsharedSessionBean is unpacked under /WEB-INF/classes in the
> tester web app, but should be loaded by the same webapp class loader
> that loads the servlet.
> * SharedSessionBean is in a JAR file under $CATALINA_HOME/lib, so it
> should be loaded by the parent classloader
>
> There definitely appears to be a problem with class loading, and trying
> this stuff fails under either WebappClassLoader and StandardClassLoader.
> Right now, I've commented things in the build.xml file out so that all
the
> classes get built into tester.jar, and running the "HttpSession" target
> all succeeds.
>
> If you uncomment the following sets of lines in build.xml, though:
> * 75-76 to copy UnsharedSessionBean to /WEB-INF/classes
> * 95-96 to exclude SharedSessionBean and UnsharedSessionBean
> from tester.jar
> * 151-156 to create and deploy SharedSessionBean into the
> $CATALINA_HOME/lib directory
>
> then you will get NoClassDefFound exceptions when trying to execute
either
> Session01 or Session03.
>
> Conclusion: class loading fails when a class within a JAR file under
> /WEB-INF/lib references a class in /WEB-INF/classes, or in a shared JAR
> file in the parent class loader.
I don't think that test case is valid.
Both of the following explanations are theories. I could be wrong. Comments
by CL gurus are welcome.
Case A (Craig's test) :
Basically, what happens here is :
- The Webapp CL which manages the tester webapp loads Session01
- It then notices it needs to be linked with other classes (SessionBean,
SSB, and USB)
- It loads USB, no problem
- It asks the parent CL to load SSB, because it can't find it
- Parent loads SSB, checks linking
- It notices it needs to load SB
- It can't find SB (since it's in his child CL repository)
I don't see how we can have that work. It's a case where classes from the
shared loader depend on classes from the webapp loader.
Case B (Jon's reloading) :
- Class A which depends on class B (which is also loaded by CL 1 -
everything would be ok if it was loaded by the parent CL) gets loaded
(perhaps along with class B) by CL 1
- Touch class A
- Reload
- CL 1 gets destroyed, and CL 2 is created, and contains the same
repositories as CL 1
- all the classes loaded by CL 1 are still there
- Later, reload new class A
- New class A needs class B, which CL 2 doesn't know
- CL 2 loads another class B
- The other objects instance of the old class B are unaffected, which leads
to an error at some point
To solve this, I would try doing a ctx.stop + ctx.start (instead of
ctx.reload) whenever class reloading is needed. I think the current
reloading will only be able to reload reliably things like the HelloWorld
servlet (ie, classes which are fully independent from other classes from the
webapp).
Remy