Re: TC4's classloader choking on xerces.jar (maybe)
Gokul Singh wrote: > - Original Message - > From: "Craig R. McClanahan" <[EMAIL PROTECTED]> > > > Tomcat 4 follows the new rules in the servlet 2.3 PFD spec, which allows a > > container to change this so that loading starts with your WEB-INF areas > first. > > > > Consider the following scenario - I put a copy of the Postgres JDBC driver > (just > > to show that it's not specific to xml parsers :-) in my shared library > > directory, because lots of my apps need it. But, one of my webapps needs > a > > different version of the Postgres driver, because it depends on a new > feature > > that was implemented in a later version. So, I put the new driver file in > the > > WEB-INF/lib directory of my webapp, and install it in Tomcat. > > > > Under Tomcat 3.2, the newer driver is ignored (because it's got the same > class > > names). Under Tomcat 4.0, the newer driver is respected for that webap -- > all > > others continue to use the shared one. > > Craig, I have a small doubt here. > > If I place the same jar file containing the class xyz.class in the > tomcat/lib directory and in WEB-INF/lib directory, then will tomcat load the > class from the tomcat/lib directory or WEB-INF/lib directory? If it is > loaded from the WEB-INF/lib directory then this class gets loaded by a > different classloader(webapp class loader) and is incompatible with the > classes loaded from tomcat/lib. > In Tomcat 3.2, the "xyz" class would be loaded from the tomcat/lib directory, by the system class loader. Therefore, it would be shared across all webapps (and, among other things, static variables would be crossing the boundaries). In Tomcat 4.0, the "xyz" class would be loaded from the WEB-INF/lib directory, and would be completely independent of the "xyz" class loaded by some other webapp. > > Should the container not check the META-INF/MANIFEST.MF to find out if the > versions are same and if the versions are same it loads the class from > tomcat/lib directory. > There is a requirement somewhat like this in the 2.3 spec -- your JAR files can declare dependencies on external shared libraries, using the "Extensions" mechanism described in the JDK documentation bundle. For example, you can declare "my webapp requires JDBC driver Foo, version 1.3 or later, be made available to me by the container because it is not in my WEB-INF/lib directory". > > Or do the specs mandate that any class in the WEB-INF/lib directory > overrides class found in the tomcat/lib directory. > Do the classes in WEB-INF/lib override the classes on the classpath in > tomcat 4.0? > The precise spec wording is in Servlet Spec 2.3 (Proposed Final Draft), section 9.6.2, on page 62: The classloader that a container uses to load a servlet in a WAR must not allow the WAR to override JDK or Java Servlet API classes, and is recommended not to allow Servlets in the WAR visibility of the web container's implementation classes. If a web container has a mechanism for exposing container-wide library JARs to application classloaders, it is recommended that the application classloader be implemented in such a way that classes packaged within the WAR are able to override classes residing in container-wide library JARs. Tomcat 4.0 follows these recommendations, although you can turn off the "override" feature by an appropriate setting in server.xml if you want to. In particular, the Tomcat 4.0 mechanism for "exposing container-wide library JARs" is that it creates a classloader that accesses all JAR files under the $CATALINA_HOME/lib directory, and makes this classloader the parent of all webapp classloaders. The details of Tomcat 4.0's class loader architecture are defined in a document in the source tree, at "catalina/docs/dev/classloaders.html". > > Regds, > Gokul > > > > > Craig McClanahan > > > Craig - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: TC4's classloader choking on xerces.jar (maybe)
- Original Message - From: "Craig R. McClanahan" <[EMAIL PROTECTED]> > Tomcat 4 follows the new rules in the servlet 2.3 PFD spec, which allows a > container to change this so that loading starts with your WEB-INF areas first. > > Consider the following scenario - I put a copy of the Postgres JDBC driver (just > to show that it's not specific to xml parsers :-) in my shared library > directory, because lots of my apps need it. But, one of my webapps needs a > different version of the Postgres driver, because it depends on a new feature > that was implemented in a later version. So, I put the new driver file in the > WEB-INF/lib directory of my webapp, and install it in Tomcat. > > Under Tomcat 3.2, the newer driver is ignored (because it's got the same class > names). Under Tomcat 4.0, the newer driver is respected for that webap -- all > others continue to use the shared one. Craig, I have a small doubt here. If I place the same jar file containing the class xyz.class in the tomcat/lib directory and in WEB-INF/lib directory, then will tomcat load the class from the tomcat/lib directory or WEB-INF/lib directory? If it is loaded from the WEB-INF/lib directory then this class gets loaded by a different classloader(webapp class loader) and is incompatible with the classes loaded from tomcat/lib. Should the container not check the META-INF/MANIFEST.MF to find out if the versions are same and if the versions are same it loads the class from tomcat/lib directory. Or do the specs mandate that any class in the WEB-INF/lib directory overrides class found in the tomcat/lib directory. Do the classes in WEB-INF/lib override the classes on the classpath in tomcat 4.0? Regds, Gokul > > Craig McClanahan > - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: TC4's classloader choking on xerces.jar (maybe)
At 04:34 21/1/01 -0800, Craig R. McClanahan wrote: >The precise answer to what works depends on how your particular class loader is >implemented. My experience (although this classloading stuff is "black magic" at >times) is that URLClassLoader, which is what Tomcat 4.0 uses, follows the process >described in the javadocs for java.lang.ClassLoader.loadClass(): Right - I wasn't talking about how the ClassLoader works but how Class.forName() works. From experience I asuume that Class.forName( "Foo" ); is equivelent to Class.forName( "Foo", true, Thread.currentThread().getContextClassLoader() ); which seems to make more sens. If Thread.currentThread().getContextClassLoader() is null then it gets it's parent threads ContextClassLoader. If it reaches first thread then it uses system classloader. Cheers, Pete *-* | "Faced with the choice between changing one's mind, | | and proving that there is no need to do so - almost | | everyone gets busy on the proof." | | - John Kenneth Galbraith | *-* - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: TC4's classloader choking on xerces.jar (maybe)
Peter Donald wrote: > At 04:08 21/1/01 -0800, Craig R. McClanahan wrote: > >Sealing is one "user error" issue that will cause classloading to fail inside > >Tomcat. Another is the fact that a particular class can only see other > classes > >in its own classloaders, and parents of that classloader, but not > children. The > >net effect is that some class libraries will NOT work unless you put them > inside > >WEB-INF/lib, because they need to be able to access other classes specific to > >that webapp. > > > >Consider the following scenario: > >* Class L is in a shared library ($TOMCAT_HOME/lib for Tomcat) > >* Class W is in WEB-INF/classes or WEB-INF/lib/*.jar > >* You pass the fully qualified class name of class W to a > > method in class L whose job is to instantiate a new object > > of this class. > >* Class L does essentially the following: > >Class wClass = Class.forName(wClassName); > > and encounters ClassNotFoundException. > > > >The reason for the exception is that Class L was loaded from the shared > library > >classloader (which is the parent of all webapp classloaders in Tomcat). > >Therefore, it cannot see into the webapp to find class W. > > I was under the impression that Class.forName() loaded classes from the > context classloader. Do you mean the one you set with Thread.setContextClassLoader()? That's not the way the standard ones work, although you could write such a beast (of course, this is specific to Java2 as well). The precise answer to what works depends on how your particular class loader is implemented. My experience (although this classloading stuff is "black magic" at times) is that URLClassLoader, which is what Tomcat 4.0 uses, follows the process described in the javadocs for java.lang.ClassLoader.loadClass(): * Call findLoadedClass(String) to see if this class has already been loaded by this class loader. * Call loadClass() on the parent class loader of this class loader (NOTE: if found, then that class's classloader will be our parent, not us). * Attempt to load the class from our own repositories (i.e. the list of URLs it was initialized with for a URLClassLoader). > So in theory the above would work if context > classloader was set up correctly. The only thing that wouldn't work is > something like > > Class wClass = getClass().getClassLoader().loadClass( wClassName ); > > Cheers, > > Pete > Craig - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: TC4's classloader choking on xerces.jar (maybe)
At 04:08 21/1/01 -0800, Craig R. McClanahan wrote: >Sealing is one "user error" issue that will cause classloading to fail inside >Tomcat. Another is the fact that a particular class can only see other classes >in its own classloaders, and parents of that classloader, but not children. The >net effect is that some class libraries will NOT work unless you put them inside >WEB-INF/lib, because they need to be able to access other classes specific to >that webapp. > >Consider the following scenario: >* Class L is in a shared library ($TOMCAT_HOME/lib for Tomcat) >* Class W is in WEB-INF/classes or WEB-INF/lib/*.jar >* You pass the fully qualified class name of class W to a > method in class L whose job is to instantiate a new object > of this class. >* Class L does essentially the following: >Class wClass = Class.forName(wClassName); > and encounters ClassNotFoundException. > >The reason for the exception is that Class L was loaded from the shared library >classloader (which is the parent of all webapp classloaders in Tomcat). >Therefore, it cannot see into the webapp to find class W. I was under the impression that Class.forName() loaded classes from the context classloader. So in theory the above would work if context classloader was set up correctly. The only thing that wouldn't work is something like Class wClass = getClass().getClassLoader().loadClass( wClassName ); Cheers, Pete *-* | "Faced with the choice between changing one's mind, | | and proving that there is no need to do so - almost | | everyone gets busy on the proof." | | - John Kenneth Galbraith | *-* - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: TC4's classloader choking on xerces.jar (maybe)
Aaron Mulder wrote: > On Wed, 17 Jan 2001, Craig R. McClanahan wrote: > > Consider the following scenario - I put a copy of the Postgres JDBC > > driver (just to show that it's not specific to xml parsers :-) in my > > shared library directory, because lots of my apps need it. But, one > > of my webapps needs a different version of the Postgres driver, > > because it depends on a new feature that was implemented in a later > > version. So, I put the new driver file in the WEB-INF/lib directory > > of my webapp, and install it in Tomcat. > > > > Under Tomcat 3.2, the newer driver is ignored (because it's got the > > same class names). Under Tomcat 4.0, the newer driver is respected > > for that webap -- all others continue to use the shared one. > > There is still the "sealing" issue, right? Not directly ... you can get package sealing problems in stand-alone Java applications as well, if you try to load classes in a particular package from more than one JAR file, and the JAR is marked "sealed". > Certain libraries > cannot be loaded in more than one ClassLoader, and are marked as "sealed" > in the Manifest. If you put one in the Tomcat lib and another in the > webapp lib, you'll get cryptic "Sealing Violation" exceptions. I think > some of the XML JARs do this (JAXP, perhaps?). Sealing is one "user error" issue that will cause classloading to fail inside Tomcat. Another is the fact that a particular class can only see other classes in its own classloaders, and parents of that classloader, but not children. The net effect is that some class libraries will NOT work unless you put them inside WEB-INF/lib, because they need to be able to access other classes specific to that webapp. Consider the following scenario: * Class L is in a shared library ($TOMCAT_HOME/lib for Tomcat) * Class W is in WEB-INF/classes or WEB-INF/lib/*.jar * You pass the fully qualified class name of class W to a method in class L whose job is to instantiate a new object of this class. * Class L does essentially the following: Class wClass = Class.forName(wClassName); and encounters ClassNotFoundException. The reason for the exception is that Class L was loaded from the shared library classloader (which is the parent of all webapp classloaders in Tomcat). Therefore, it cannot see into the webapp to find class W. This kind of pattern is very common when parsing XML files -- it's not the parser itself that has the problem, it's the code you try to run in your SAX event handlers -- but is not unique to them. > > I don't have a full understanding of this, though. Perhaps it > only breaks if loaded more than once in serial ClassLoaders not parallel > ones. But I think tomcat's lib is sill in serial with webapp lib, right? > I'm not quite sure what you mean by "serial" with the webapp lib, but the classloader used for $TOMCAT_HOME/lib is a *parent* classloader of the classloader used for each web application. > > Aaron > Craig McClanahan - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: TC4's classloader choking on xerces.jar (maybe)
On Wed, 17 Jan 2001, Craig R. McClanahan wrote: > Consider the following scenario - I put a copy of the Postgres JDBC > driver (just to show that it's not specific to xml parsers :-) in my > shared library directory, because lots of my apps need it. But, one > of my webapps needs a different version of the Postgres driver, > because it depends on a new feature that was implemented in a later > version. So, I put the new driver file in the WEB-INF/lib directory > of my webapp, and install it in Tomcat. > > Under Tomcat 3.2, the newer driver is ignored (because it's got the > same class names). Under Tomcat 4.0, the newer driver is respected > for that webap -- all others continue to use the shared one. There is still the "sealing" issue, right? Certain libraries cannot be loaded in more than one ClassLoader, and are marked as "sealed" in the Manifest. If you put one in the Tomcat lib and another in the webapp lib, you'll get cryptic "Sealing Violation" exceptions. I think some of the XML JARs do this (JAXP, perhaps?). I don't have a full understanding of this, though. Perhaps it only breaks if loaded more than once in serial ClassLoaders not parallel ones. But I think tomcat's lib is sill in serial with webapp lib, right? Aaron - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: TC4's classloader choking on xerces.jar (maybe)
"Len, Peter" wrote: > Bob, > > I don't really understand it but what I heard was that any xml jar that > you want to add to your context will need to go in the $TOMCAT_HOME/lib > dir rather that your context's WEB-INF/lib dir. XML apparently is > considered differently that your other .jar files. Again, I don't know > exactly why but that seesm to be the case. I have my xerces.jar in the > $TOMCAT_HOME/lib and the rest of my jars in the WEB-INF/lib and > everything is fine. > Actually, there is nothing special about XML jars versus others. But what goes in depends very much on which Tomcat version you are talking about. Tomcat 3.2 follows the normal Java2 delegation model (simulated when running on a JDK 1.1 system), so that if you ask for class a.b.c.foo, the loader looks in the shared class path *first*, and the WEB-INF area *second*. The net effect of this is that you cannot override classes found in the shared area with the same name -- even if you put your own JAR file in WEB-INF/lib. Tomcat 4 follows the new rules in the servlet 2.3 PFD spec, which allows a container to change this so that loading starts with your WEB-INF areas first. Consider the following scenario - I put a copy of the Postgres JDBC driver (just to show that it's not specific to xml parsers :-) in my shared library directory, because lots of my apps need it. But, one of my webapps needs a different version of the Postgres driver, because it depends on a new feature that was implemented in a later version. So, I put the new driver file in the WEB-INF/lib directory of my webapp, and install it in Tomcat. Under Tomcat 3.2, the newer driver is ignored (because it's got the same class names). Under Tomcat 4.0, the newer driver is respected for that webap -- all others continue to use the shared one. > > FYI: Tomcat 3.2 comes with a jaxp.jar file for its own use. If you > just drop your xerces.jar file in that lib directory you may encounter > problems (as I had) because the jaxp.jar will come before the xerces.jar > file in the CLASSPATH. I renamed my xerces.jar to a_xerces.jar so that > I know it gets loaded first and that I won't run into a conflict with > the same classes listed in both jar files. > If you want to use Xerces under Tomcat 3.2, you should put xerces.jar under $TOMCAT_HOME/lib and remove jaxp.jar and parser.jar. > > Peter Len > Craig McClanahan - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
RE: TC4's classloader choking on xerces.jar (maybe)
Bob, I don't really understand it but what I heard was that any xml jar that you want to add to your context will need to go in the $TOMCAT_HOME/lib dir rather that your context's WEB-INF/lib dir. XML apparently is considered differently that your other .jar files. Again, I don't know exactly why but that seesm to be the case. I have my xerces.jar in the $TOMCAT_HOME/lib and the rest of my jars in the WEB-INF/lib and everything is fine. FYI: Tomcat 3.2 comes with a jaxp.jar file for its own use. If you just drop your xerces.jar file in that lib directory you may encounter problems (as I had) because the jaxp.jar will come before the xerces.jar file in the CLASSPATH. I renamed my xerces.jar to a_xerces.jar so that I know it gets loaded first and that I won't run into a conflict with the same classes listed in both jar files. Peter Len - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]