views:

472

answers:

6

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?

+1  A: 

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.

jsight
There is no way to know if Bar-2.0 works with Foo-2.0 or not, and it's a massive, binary-only library with no test cases.
rcampbell
I believe the solution you are using has Bar-2.0 running with Foo-2.0, just in a kind of roundabout way.
jsight
+2  A: 

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.

David Soroko
I really think this is the best suggestion. Repackage your bar-2.0.jar, otherwise you are just asking for headaches down the road.
gregcase
+1  A: 

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.

Kennet
A: 

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.

Vinodh Ramasubramanian
+5  A: 

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.

BalusC
Georgy answered first, so I accepted his submission, but what you describe is exactly what I did to resolve the problem. Your link was especially helpful. **I encourage everyone to vote up this answer**.
rcampbell
You're welcome. Although I would point out that answers here are **not** by default ordered by answer date. At the moment of writing you can see at the topright of the user avatar that I answered this question 23 minutes ago and Georgy 15 minutes ago. You can change the ordering by one of the three tabs `oldest`, `newest` and `votes` righttop of the answers. The default is `votes`.
BalusC
And, in the tooltip you can see the exact time. So I was actually first :o
BalusC
+2  A: 

Put Foo-1.0.jar to $CATALINE_HOME/common/endorsed (or any other place where it will be loaded after Foo-2.0.jar).

Georgy Bolyuba