Control the classpath ordering of jars in WEB-INF/lib on Tomcat 5?
I have a legacy web app running in Tomcat 5.0.
This web app has two jars in WEB-INF/lib, let's say Foo-2.0.jar and Bar-2.0.jar. Bar-2.0.jar actually includes a Foo-1.0.jar inside of it. Bar is also a dead project, meaning no upgrading, no source, but still important to the application.
The latest release of this application requires Foo-2.0.jar for some other stuff. Having both Foo-1.0.jar and Foo-2.0.jar in the classpath creates a conflict, specifically a ClassDefNotFound type of error, where a class that was later added in 2.0 cannot be found 开发者_如何学运维in 1.0, etc.
In Eclipse, the simple solution is to right click on your Project, click Properties > Java Built Path > Order and Export and to move Foo-2.0.jar above Bar-2.0.jar so it's resolved first.
How does one accomplish this type of classpath ordering for jars in WEB-INF/lib in Tomcat?
Tomcat 5's classloading precedence for webapps is roughly as follows: first the bootstrap/system (JRE/lib
, then Tomcat's internal classes), then the webapp libraries (first WEB-INF/classes
, then WEB-INF/lib
), then the common libraries (first Tomcat/common
, then Tomcat/lib
) and finally the webapp-shared libraries (Tomcat/shared
).
So to get Foo-2.0.jar
loaded before Bar-2.0.jar
, best what you can do is to move Bar-2.0.jar
from WEB-INF/lib
to Tomcat/common
or Tomcat/shared
.
The JAR's aren't loaded in alphabetic order of their name. At least, there's no spec which says that. Renaming them to change the alphabetical filename order makes no sense.
Strip Foo-1.0.jar out of Bar-2.0.jar. As it is, it's just trouble waiting to happen both for development(need to fudge the dev. environments) and for deployment.
Put Foo-1.0.jar to $CATALINE_HOME/common/endorsed (or any other place where it will be loaded after Foo-2.0.jar).
You don't, as this feature isn't available in Tomcat. If both Foo-1.0.jar and Foo-2.0.jar are needed in the classpath at the same time, you will need some major classpath reorganization.
If Bar-2.0 can work with Foo-2.0, then the best thing to do would be to rebuild Bar-2.0 yourself without a Foo-1.0.jar inside of it.
It is possible to set the Class-Path in the mainfest of the jar. http://java.sun.com/developer/Books/javaprogramming/JAR/basics/manifest.html I can't really promise it will solve the problem, but can be worth a try.
To have Foo-2.0.jar before Bar-2.0.jar, update the Bar-2.0.jar with the content of Foo-2.0.jar (overwrite already contained .class)and delete Foo-2.0.jar from the war.
-cp A.jar:B.jar has the effect, that content of A.jar is like a layer over B.jar. So you get the same effect with overwriting B.jar's content with A.jar's.
This is a bit hacky but might work. Change the name of Foo-2.0.jar to be alphabetically ahead of Bar-2.0.jar, say AFoo-2.0.jar.
精彩评论