Hi all, I've just spent quite a while tracking down a weird problem...
I'm running a servlet under Tomcat 4.0. The servlet includes Axis, which in this case is using the Xerces (1.4.3) parser. Everything works fine - no problem so far... Now I try to run the same servlet on Tomcat 4.0 embedded in JBoss (2.4.1) and I get the following:- java.lang.ClassCastException: org.apache.crimson.jaxp.DocumentBuilderFactoryImpl at javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFactory.java:152) So much for write once run anywhere. Now this takes some tracking down but I now know how to fix it in my case: It turns out that the JBoss startup script sets a system property to specify org.apache.crimson.jaxp.DocumentBuilderFactoryImpl as the default DOM factory (and does similar for SAX). I dont know why it does this because removing the setting doesnt have any adverse effect which I can see and fixes the ClassCastException. Likewise, adding the same properties to the standalone Tomcat startup script causes the same error to occur in that environment. So what's going on? (and who is to blame?) Both JBoss and Tomcat use JAXP and Crimson and have their own copies of the jaxp.jar and crimson.jar. As far as I can tell, these copies all seem to use the same version of each library. Enabling the jaxp.debug property shows Crimson is being used just fine by the app servers internal code before my problem occurs. Disassambling the DocumentBuilderFactory class which comes with Tomcat and JBoss reveals that there is no code at line 152... Looking at the Xerces jar (and source) reveals that it has its own implementation of JAXP which differs from the one used by Crimson... and does indeed cast the newly created factory to DocumentBuilderFactory at line 152. Both Xerces and Crimson use META-INF/services to supply a default value for the DOM factory. Without the system property, the Servlet's copy of Xerces appears to 'win' in the servlet's context, create the Xerces factory and everything works OK. Both versions of JAXP allow the System property to override the META-INF/services default. So, what I think is happening is the following:- - The Xerces DocumentBuilderFactory is the one running in the servlet context - Its logic causes it to pick the Crimson DOM factory if the system property is present. - It creates the Crimson DOM factory using Class.forName.newInstance - Then it gets a ClassCastException. I presume this is because the Xerces JAXP has a different and incompatible idea of what the javax.xml.parsers.DocumentBuilderFactory class looks like - The Xerces one has an extra private static attribute and method over what the Crimson one has. So what's the answer? - at the moment the answer seems to be to avoid mixing Crimson and Xerces in the same context unless you have a very good understanding of how they are going to interact with each other - you might get away with it or you might (like me) spend a long time chasing strange problems. ... but this is bad news because it means that if my servlet uses an XML parser, I have to check whether the app server I'm deploying on is using another one in a way which is going to cause a conflict. - For the future it would seem to be a better approach to agree on a single implementation of JAXP within Apache, put it in its own JAR and explicitly disallow (in the JAXP spec?) XML parser implementations from reimplementing all or part of JAXP in their own JARs. Andy ---------------------------------------------------------------- Andy Carlson _________________________________________________________________ Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp --------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]