Explanation of Tomcat's Class Loader
from the Chief Developer of Tomcat and Struts:
> On Fri, 9 Aug 2002, Matt Raible wrote: > > Struts Dev Team - please verify my hypothesis below. > > I believe the Struts JARs and the DBCP JARs from common should be the > same. After all, Struts does use the DBCP in it's distribution. You > might want to upgrade to the latest build of Struts (which includes > DBCP and Logging, among others). I know they're planning on releasing > 1.1 Beta 2 this weekend. > The story is somewhat convoluted (I *hate* class loaders :-), but it goes like this: If you are going to use a JNDI datasource, then both your webapp AND Tomcat need to see the same copy of the JDBC driver and the dbcp classes (for 4.1.x) -- and the way to make that happen is to put the driver into common/lib. Because commons-dbcp.jar is there, it's dependent jars (such as commons-collections.jar, jdbc2_0-stdext.jar, and (recently added) commons-lang.jar) need to be in common/lib as well. Plus, of course, jndi.jar if you're on a 1.2 system. Having any of these JARs duplicated inside the webapp causes a problem in 4.x based systems, because they try to use the local copy first -- and a copy if foo.bar.MyClass loaded from the webapp is *not* the same class as a copy of foo.bar.MyClass loaded from common/lib. This is a place where Tomcat's modified class loader model causes grief (but only because you're trying to use the same classes that Tomcat internally is trying to use -- if you were using something like GenericDataSource with your own copy of the connection pool, it would not be a problem). One workaround for this would be to try turning off the modified loader delegation model, by putting something like this in your server.xml file (or in a context configuration file on Tomcat 4.1.x.): <Context path="/myapp" ...> <Loader delegate="false"/> </Context> This *should* let you have a copy of all the JAR files inside your webapp, as well as in common/lib, but not cause any conflicts. Please let me know, one way or the other, if this works -- it's clearly a desireable goal that you can ship a WAR file with all the included commons JARs but not have problems like this. I want to review how Tomcat's default configuration can make this easier. And, from a Struts application perspective (not just for Roller), this is a pretty serious usability issue. > HTH, > > Matt > Craig McClanahan PS: In Tomcat 4.1.x, the "deploy" command of the manager app lets you include a context configuration file in the WAR, at location "META-INF/context.xml". So it might still be possible to configure a single WAR that works correctly in Tomcat 4.1.x and still works in other servers (that would obviously ignore such a file).
Thanks for the clear and concise definition of how this all works Craig. So basically, in Tomcat 4.x, don't keep duplicates of your JARs in $CATALINA_HOME/common/lib AND in yourApp/WEB-INF/lib, OR turn off the modified loader delegation as specified above. Tomcat 4.1.x looks very cool, I'm just curious to know why they're on a Beta Release of 4.1.8, but still no official release?