Search code examples
grailsgroovyjboss

org.apache.xml.serializer.ToXMLSAXHandler cannot be cast to org.apache.xml.serializer.SerializationHandler in JBOSS when using XmlUtil.serialize()


I am trying to remove and add tags from an xml file using XmlParser . Following is my code block which runs fine when executed inside my grails application deployed with "grails run-app" command :

def parser = new XmlParser()
def xmlTemplate = parser.parse(file1)
def origFile  = parser.parse(file2)

for (def n : origFile.cars)
{
    origFile.remove(n)
}


def children = origFile.children()
int i = 0 ; 
for (def n : xmlTemplate.cars)
{
  children.add(i,n)
   i++
}

new File(finalFileName).write( XmlUtil.serialize(origFile) )

However when I deploy this code on JBOSS server as a war it throws the following error when called :

13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28) org.apache.xml.serializer.utils.WrappedRuntimeException: org.apache.xml.serializer.ToXMLSAXHandler cannot be cast to org.apache.xml.serializer.SerializationHandler
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at org.apache.xml.serializer.SerializerFactory.getSerializer(SerializerFactory.java:179)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at org.apache.xalan.transformer.TransformerIdentityImpl.createResultContentHandler(TransformerIdentityImpl.java:260)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:330)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at groovy.xml.XmlUtil.serialize(XmlUtil.java:448)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at groovy.xml.XmlUtil.serialize(XmlUtil.java:437)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at groovy.xml.XmlUtil.serialize(XmlUtil.java:179)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at groovy.xml.XmlUtil.serialize(XmlUtil.java:88)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at groovy.xml.XmlUtil$serialize.call(Unknown Source)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
13:50:36,312 INFO  [stdout] (http-/10.64.96.82:8080-28)     at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)

I found a similar issue on https://issues.jboss.org/browse/JBEAP-19 which suggested to remove xalan serializer-2.7.1.jar from the package and it indeed works fine after removing this jar from the application war. The jar serializer-2.7.1.jar was part of my war file as I created the war using "grails war" command and I am not sure where it was being used.My app is running fine after the removal of jar so it seems the grails framework is also not using this jar internally anywhere.

Can anyone explain what can be the root cause of this issue and also what is the use of serializer-2.7.1.jar in grails app ?


Solution

  • The OP asks:

    "Can anyone explain what can be the root cause of this issue and also what is the use of serializer-2.7.1.jar in grails app ? "

    I will take a stab at answering the 'root cause' part of the question:

    I believe what you have encountered is "Xerces hell". Serializer-2.7.1-jar uses Xerces.

    Xerces hell is when you have conflicting dependencies of Xerces.

    Citing from another StackOverflow question about the history of Xerces:

    Xerces is the most widely used XML parser in the Java ecosystem. Almost every library or framework written in Java uses Xerces in some capacity (transitively, if not directly).

    The Xerces jars included in the official binaries are, to this day, not versioned. For example, the Xerces 2.11.0 implementation jar is named xercesImpl.jar and not xercesImpl-2.11.0.jar.

    The Xerces team does not use Maven, which means they do not upload an official release to Maven Central.

    Xerces used to be released as a single jar (xerces.jar), but was split into two jars, one containing the API (xml-apis.jar) and one containing the implementations of those APIs (xercesImpl.jar). Many older Maven POMs still declare a dependency on xerces.jar. At some point in the past, Xerces was also released as xmlParserAPIs.jar, which some older POMs also depend on.

    The versions assigned to the xml-apis and xercesImpl jars by those who deploy their jars to Maven repositories are often different. For example, xml-apis might be given version 1.3.03 and xercesImpl might be given version 2.8.0, even though both are from Xerces 2.8.0. This is because people often tag the xml-apis jar with the version of the specifications that it implements. There is a very nice, but incomplete breakdown of this here.

    To complicate matters, Xerces is the XML parser used in the reference implementation of the Java API for XML Processing (JAXP), included in the JRE. The implementation classes are repackaged under the com.sun.* namespace, which makes it dangerous to access them directly, as they may not be available in some JREs. However, not all of the Xerces functionality is exposed via the java.* and javax.* APIs; for example, there is no API that exposes Xerces serialization.

    Adding to the confusing mess, almost all servlet containers (JBoss, Jetty, Glassfish, Tomcat, etc.), ship with Xerces in one or more of their /lib folders.

    See the full StackOverflow question here: Dealing with "Xerces hell" in Java/Maven?

    It is an interesting read.

    The most common solution seems to be excluding all other version of Xerces - though it can be tough task with the many versions and names used by Xerces jar files.

    To give another example of "Xerces hell", I have encountered this issue with WebLogic and the Xalan dependency (the same one you excluded).