Using JAXP 1.3 with JBoss 4

Some of my ADF classes heavily rely on DOM L3 and they won’t run with the default settings of JBoss 4.0.2 (and its old endorsed parser). They run just fine with the JAXP 1.3 parser that comes with Java 5.0 so I tried to get rid of the endorsed directory. Unfortunately just removing the directory won’t help, as the JAXP 1.3 classes are not added to the classpath by default. I tried to add %JAVA_HOME%\jre\lib\rt.jar to the classpath but this still didn’t fix the problem. I sill got a lot errors and the most interesting one was a java.lang.NoClassDefFoundError: org/apache/xerces/xni/parser/XMLEntityResolver.

When I had a look at rt.jar the path to the XMLEntityResolver class is now com/sun/org/apache/xerces/internal/xni/parser. Trying to hack past the NoClassDefFoundError I also added the contents of the endorsed directory to the classpath (after removing the -Djava.endorsed.dirs=%JBOSS_ENDORSED_DIRS%” and adding rt.jar to the classpath)

Well, this made Jboss start without errors but it has not solved my problem. I was still getting the same error as before when I tried to perform some DOM L3 functions:

Unexpected Error in method: public abstract void net.sf.adf.transport
.JMSTransportRemote.send(net.sf.adf.acl.ACLMessage) throws net
.sf.adf.transport.SendingException,java.rmi.RemoteException

java.lang.AbstractMethodError: org.apache.xml.serialize
.DOMSerializerImpl.getDomConfig()Lorg/w3c/dom/DOMConfiguration;

at net.sf.adf.acl.xml.XMLCodec.encode(XMLCodec.java:63)
at net.sf.adf.transport.JMSTransport.send(JMSTransport.java:133)
at net.sf.adf.transport.JMSTransport.send(JMSTransport.java:119)

The code that caused this exception is this:

Code
public String encode(ACLMessage message) throws EncodingException {
Document doc = encodeDOM(message);
try {
    DOMImplementationLS domImplLS =
           (DOMImplementationLS)doc.getImplementation();

    StringWriter sw = new StringWriter();
    LSOutput output = domImplLS.createLSOutput();
    output.setCharacterStream(sw);

    LSSerializer serializer = domImplLS.createLSSerializer();
    DOMConfiguration config = serializer.getDomConfig();

In the end I managed to make it work by adding one final touch to the solution described above. Instead of the (arguably) more portable way of obtaining a DOMImplementation:

Code:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation domImpl = builder.getDOMImplementation();

I directly used the DOMImplementation from JDK1.5, that is:

Code:
DOMImplementation domImpl = (DOMImplementation)com.sun.org.apache.xerces
.internal.dom.DOMImplementationImpl.getDOMImplementation();

This is not a nice solution, but it was the best I could find on my own. If you have a more elegant I would be interested in finding out about it.

In both cases I had to make sure that the DOMImplementation supports LS 3.0:

Code:
  if (!domImpl.hasFeature("LS", "3.0")) {
    throw new ParserConfigurationException(
            "Load/Save 3.0 not supported");
}

and finally I used it to create new documents:

Code
Document doc = domImpl.createDocument(namespaceURI,
   rootElementQualifiedName, docType);

cast it to a DOMImplementationLS and parse existing ones:

Code:
     DOMImplementationLS domImplLS = (DOMImplementationLS)domImpl;

    LSInput input = domImplLS.createLSInput();
    input.setCharacterStream(reader);
    LSParser parser = domImplLS.createLSParser(
            DOMImplementationLS.MODE_SYNCHRONOUS,
            validating ? "http://www.w3.org/TR/REC-xml" : null);
    // for schema validation this would be set to
    // "http://www.w3.org/2001/XMLSchema"
    parser.getDomConfig().setParameter("validate", validating);
    Document doc = parser.parse(input);

or serialize in-memory DOM trees:

Code:
     DOMImplementationLS domImplLS =
              (DOMImplementationLS)doc.getImplementation();

    LSOutput output = domImplLS.createLSOutput();
    output.setCharacterStream(writer);

    LSSerializer serializer = domImplLS.createLSSerializer();
    serializer.write(doc, output);

There are so many people who don’t have the slightest idea all these are possible using the DOM and it’s very good JDK1.5 implementation. It is a pity that JBoss is still shipping with a hard-wired full-of-bugs old implementation of Xerces when JAXP 1.3 works great.

Essentially it would not be very hard to make JBoss 4 work with JAXP 1.3 instead of 1.2. I just did a quick search in the JBoss 4.0.2 source for the phrase org.apache.xerces and there are only 11 java source files containing it. According to the JAXP 1.3 relese notes the most important incompatibe change in JAXP 1.3 is that the packages for Xerces and Xalan got renamed. This was made on purpose and makes it possible to deliver to the JDK1.4 without using the endorsed standards mechanism. This change lets you reference newer Apache libraries in the classpath, so application developers can use them in the same way that would use any other additions to the Java platform.

I am not saying that moving the implementation of JBoss to JAXP 1.3 will be painless, but this is a necessary evolution. Until that happens I hope that the workarounds I describe above will help you unleash the power of JBoss and DOM L3 processing.

Advertisements

2 Responses to Using JAXP 1.3 with JBoss 4

  1. Ace Frehley says:

    Is it possible to use this LSSerializer object to transform a java pojo into an XML string? I am currently using Apache’s XMLSerializer and OutputFormat classes to transform a Hibernate entity pojo into XML right now, but the XMLSerializer class has been targetted for deprecation.

    Thanks.

  2. hritcu says:

    Sorry but I have no clue.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: