Jar Hell
First, pardon the interruption in your normally scheduled program. This isn't a post on interop, it is a rant. I'm not normally a raving lunatic, but this situation just blows me away.
I wanted to try Sun Java 1.5 for my Java app server install, in order to take advantage of some new ImageIO stuff: BMP Support for WordML generation. The version of JBoss I have running (v3.0.4, from 2002!) does not run on Java 1.5, so need to upgrade to 3.2.6 at least. I am afear'd of JBoss v4, with the implicit "major version upgrade", so I decide to go with v3.2.7. That sounds safe.
So I installed JBoss 3.2.7, then moved over all my WAR files - one for AXIS 1.2RC3 (axis1.2.war) and one for AXIS v1.1 (axis.war) and all the JSPs and classes under those dirs. I also moved over a couple other war dirs. I start JBoss using the Sun Java 1.5, and my WordML app and the Java ImageIO library stuff works. Molto Bene.
Then I try Axis1.2, and the initial JSPs, seem to work, but happyaxis.jsp, does not. Google tells me that to run AXIS with Tomcat (I have never done this, always Jboss+Jetty or Jetty alone), you should move saaj.jar and jaxrpc.jar from the AXIS distribution to the tomcat library directory. Why? Who knows. With the old version of JBoss (v3.0.4), I had jetty, and so didn't have this problem. But the new JBoss bundles Tomcat.
Crossing my fingers, I make the recommended change.
Start up again (60 seconds) and happyaxis.jsp is now truly happy. Ecstatic even. Other basic JSPs also work. But, now I get new errors when I try to invoke an AXIS webservice. This time it appears to point to log4j mismatches. I skulk through my directories and surmise that I don't need 7 copies of the log4j library. So I remove log4j from the AXIS war directories, (AXIS 1.1 ships 2 versions!!, AXIS 1.2 ships another version). I will hope that the log4j shipped by Jboss is the one everybody (Jboss AXIS Tomcat, and whoever else) can agree on.
Ok, no more log4j proliferation. That feels better.
Then restart. Wait 50 seconds.
Run the apps. Again the JSPs look ok. But when I try invoking a webservice, still no good. A new error:
22:04:34,158 ERROR [Engine] StandardWrapperValve[AxisServlet]: Servlet.service() for servlet AxisServlet threw exception java.lang.NoSuchMethodError: org.apache.axis.description.TypeDesc: method (Ljava/lang/Class;Z)V not found
WTF?
Not able to decipher this - it was late, a long day - I start guessing. Maybe it's a Java 1.5 thing. Maybe AXIS does not work on Java 1.5? I googled a bit but found nothing. So I tried running instead with BEA's jRockit JVM 1.4.1_02, but that also failed, but with a different exception. Actually, a cascade of about 6 nested exceptions, each with a 200-line stack trace. The important one, as far as I am able to tell, is
at COM.jrockit.reflect.NativeMethodInvoker.invoke0(ILjava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;(Native Method)
at COM.jrockit.reflect.NativeMethodInvoker.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;(Unknown Source)
Caused by: org.dom4j.DocumentException: Can't find bundle for base name org.apache.xerces.impl.msg.SAXMessages, locale en_US Nested exception: Can't find bundle for base name org.apache.xerces.impl.msg.SAXMessages, locale en_US
at org.dom4j.io.SAXReader.read(Lorg.xml.sax.InputSource;)Lorg.dom4j.Document;(SAXReader.java:353) at org.dom4j.io.SAXReader.read(Ljava.net.URL;)Lorg.dom4j.Document;(SAXReader.java:236)
"Can't find bundle"? Looks like a localization mixup. Complaining about a SAX library. Hmmm. SAX. I don't use SAX. Maybe AXIS uses SAX. I remember vaguely that BEA ships a SAX implementation in the jRockit distrib. Maybe it is different than the one in JBoss and they are tripping on each other?
So I try IBM JDK 1.4.1. IBM doesn’t ship SAX libraries, I know that. So no SAX-related "can't find bundle" crap. But now I am back to the same error as with the Sun JVM 1.5. a NoSuchMethodError.
Looking a little more closely, maybe it is because I have both Axis1.1 and Axis1.2 libs installed on the same Tomcat+Jboss. This worked fine with Jboss v3.0.4. It also works fine on my current Jetty install. But the error message I get here says, it is finding the class, but not the method. And it is an AXIS class. So maybe it has loaded an old version of the class it needs. Why would it do this? Why is this different than the other installations I have? Who knows.
On this hunch, I remove the Axis1.1 war dir.
Again startup on IBM JDK 1.4.1. This takes 80 seconds. Again invoke the AXIS 1.2 webservices, this time it actually works. Woo hoo! So it was a library problem. Again.
Back to the WordML sample, this does not work now, because we are running on IBM JDK 1.4.1. In Java 1.4, there is no support for reading BMP. The ImageIO libraries are there, but they don't do BMP. The operation SILENTLY fails. When I try to read a BMP stream, it doesn't throw, I just get null. No image.
So, stop JBoss again, start on Sun JVM 1.5. Now I am no longer getting the "NoMethodFoundError" because I have yanked AXIS 1.1. Good.
Again try the WordML example with the ImageIO and BMP thing. It works (again). Try AXIS 1.2 samples, they work also.
Whew.
For those counting at home, that is 5 distinct class mismatch problems I experienced when upgrading my JBoss app server, and the 2 tiny apps I run on it. Each of those 5 problems exhibited a totally different failure mode, a totally different error message, and a totally different avoidance or solution.
This is Jar Hell. What if I had real apps? Also, where is the frigging doc? Does everyone wander around in the wilderness like this, or is it just me? How does anybody get anything done?
If this isn't a clear illustration of the value of strongly-named (signed and versioned) libraries as with .NET, I don't know what is. Java's classpath and classloader mechanism is looking more and more broken by the day. Have you ever looked at the JBoss doc on classloading? Or WebSphere's? How does it interact with Tomcat's classloader, or Java's built-in classloader? Why is everybody inventing their own solutions? Why is everything different? Can anyone explain all this?
Every new product release that ships Jars (like JBoss, JVMs, Tomcat, or AXIS) just multiplies the problem. If I scanned my HD right now I'll bet I could find 12 versions of log4j. Easy. Not one is signed or versioned. Same thing with SAX, Xerces, Servlet.jar, and every other utility library. Jaxrpc.jar is next.
Compounded with that, there's the exploding matrix of classpaths from JVM JBoss Tomcat and AXIS . Each has their own set of lib directories: JBoss has at least 3 directories, the JVM has 2 or 3 (JRE + JDK + the ext directory), Tomcat has its own lib dir, and AXIS has its own. If you have jars that are duplicated in any of these, try guessing which library gets loaded. Try guessing which version your app will get.
How is this usable?
There, I feel better now.
Update 13:00 (GMT-5:00), April 1: note more on this
Comments
Anonymous
March 31, 2005
The comment has been removedAnonymous
March 31, 2005
If you think that's bad, you should try getting all the .Net 2.0 CTP builds working together...
JimAnonymous
March 31, 2005
Hani, talking about PicoContainer 2 days ago, said, "It also has next to no dependencies, which makes the thought of depending on it (no pun intended) far less of a house of cards that is the usual case with opensores drivel."
http://www.jroller.com/page/fate/20050328#picocontainer_tagnuts_from_a_thousand
Apparently others have also explored this landscape ...Anonymous
March 31, 2005
The comment has been removedAnonymous
March 31, 2005
I just went through a similar process (ie pain). What I finally did was individually download and install the separate pieces. For example, Xerces can be downloaded and installed separately. Usually, I create a directory (eg C:JavaDev) and throw (unzip) all the stuff into this directory -- notice the directory dosn't have any spaces, Java still has a hard time dealing with directories with spaces (isn't it 2005?). Anyway, I setup a batch file with its own CLASSPATH that points to all the necessary JAR files under JavaDev. Then the batch file launches Tomcat, etc...
I feel your pain.Anonymous
March 31, 2005
addendum, I later found this:
UseJBossWebLoader: This flag indicates that Tomcat should use a JBoss unified class loader as the web application class loader. The default is true, which means that the classes inside of the WEB-INF/classes and WEB-INF/lib directories of the WAR file are incorporated into the default shared class loader repository described in Chapter 2, The JBoss JMX Microkernel. This may not be what you want as its contrary to the default servlet class loading model and can result in sharing of classes/resources between web applications. You can disable this by setting this attribute to false.
from the JBoss doc. http://docs.jboss.org/jbossas/jboss4guide/r1/html/ch9.chapt.html
Had I known this, I could have avoided the "NoMethodFoundError" .Anonymous
March 31, 2005
The comment has been removedAnonymous
March 31, 2005
I work in a company which uses almost exclusively open source bits for development (i.e. Java development) and have come up against similar problems from time to time, usually at the start of a project. The thing is that once you've got over the worst of it (and it can, I agree, be eye-crossingly infuriating) and settled on versions of this and that (which we, ironically enough, distribute to developers via a years-old version of Visual Source Safe), you tend not to come across it again for a reasonable amount of time. Usually not until the start of the next project, by which time if the previous experience was bad enough the memory of it will have been nicely repressed..
SjHAnonymous
March 31, 2005
The comment has been removedAnonymous
July 18, 2008
PingBack from http://www.sheida.com/en/2008/07/18/web-services-ws-policy-implementation/Anonymous
November 06, 2008
Boss -- my 2 resources spent 4 hrs of time on this issue. Finally got u'r note and able to resolve it. I wish this solution comes as first result when u search in google or live.