Configuring and Using JAXP 1.1 In JBoss

Scott Stark <[email protected]>

Introduction

JBoss uses the JAXP 1.1 optional package to JAXP to parse and transform XML documents using a pure Java API that is independent of a particular XML processor implementation. This allows the flexibility to swap between XML processors without making application code changes. Version 1.1 includes an XSLT framework based on TrAX (Transformation API for XML) plus some updates to the parsing API to support DOM Level 2 and SAX version 2.0 and an improved scheme to locate pluggable implementations.

Configuring XML Parsers and Transformers

This section covers how one configures which xml parser and transformers the JBoss uses. It is based largely on the current Java API for XML Processing (JAXP) 1.1 specification. The types of configurable objects include DOM parsers, SAX parsers and XSLT transformers. First we'll describe the configuration options for the various objects per the JAXP spec and then show how JBoss uses the configuration properties and how you can change them.

SAX Parser Configuration

The SAX Plugability classes allow an application programmer to provide an implementation of the org.xml.sax.DefaultHandler API to a SAXParser implementation and parse XML documents. In order to obtain a SAXParser instance, an application programmer first obtains an instance of a SAXParserFactory. The SAXParserFactory instance is obtained via the static newInstance method of the SAXParserFactory class. This method uses the following ordered lookup procedure to determine the SAXParserFactory implementation class to load:

  1. Use the javax.xml.parsers.SAXParserFactory system property

  2. Use the properties file "lib/jaxp.properties" in the JRE directory. This configuration file is in standard java.util.Properties format and contains the fully qualified name of the implementation class with the key being the system property defined above.

  3. Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for the classname in the file META-INF/services/javax.xml.parsers.SAXParserFactory in jars available to the runtime.

  4. Platform default SAXParserFactory instance.

DOM Parser Configuration

The DOM plugability classes allow a programmer to parse an XML document and obtain an org.w3c.dom.Document object from a DocumentBuilder implementation which wraps an underlying DOM implementation. In order to obtain a DocumentBuilder instance, an application programmer first obtains an instance of a Document-BuilderFactory. The DocumentBuilderFactory instance is obtained via the static newInstance method of the DocumentBuilderFactory class. This method uses the following ordered lookup procedure to determine the DocumentBuilderFactory implementation class to load:

  1. Use the javax.xml.parsers.DocumentBuilderFactory system property

  2. Use the properties file "lib/jaxp.properties" in the JRE directory. This configuration file is in standard java.util.Properties format and contains the fully qualified name of the implementation class with the key being the system property defined above.

  3. Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for the classname in the file META-INF/services/javax.xml.parsers.DocumentBuilderFactory in jars available to the runtime.

  4. Platform default SAXParserFactory instance.

XSLT Transformer Configuration

The XSLT Plugability classes allow an application programmer to obtain a Transformer object that is based on a specific XSLT stylesheet from a TransformerFactory implementation. In order to obtain a Transformer object, a programmer first obtains an instance of the TransformerFactory. The TransformerFactory instance is obtained via the static newInstance method of the TransformerFactory class. This method uses the following ordered lookup procedure to determine the TransformerFactory implementation class to load:

  1. Use the javax.xml.transform.TransformerFactory system property

  2. Use the properties file "lib/jaxp.properties" in the JRE directory. This configuration file is in standard java.util.Properties format and contains the fully qualified name of the implementation class with the key being the system property defined above.

  3. Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for the classname in the file META-INF/services/javax.xml.transform.TransformerFactory in jars available to the runtime.

  4. Platform default TransformFactory instance.

Changing the JBoss Defaults

JBoss uses a DOM DocumentBuilder to parse the jboss.jcml configuration file. The run.bat and run.sh startup scripts sets the javax.xml.parsers.DocumentBuilderFactory and javax.xml.parsers.SAXParserFactory system properties to the bundled Crimson 1.1 DOM and SAX parsers contained in lib/crimson.jar. Figure 11.30 shows the setup.

Figure 11.30. The run.sh setup for the Crimson xml parsers

# Add the XML parser jars and set the JAXP factory names
# Crimson parser JAXP setup(default)
CLASSPATH=$CLASSPATH:../lib/crimson.jar
JAXP=-Djavax.xml.parsers.DocumentBuilderFactory=org.apache.crimson.jaxp.DocumentBuilderFactoryImpl
JAXP="$JAXP -Djavax.xml.parsers.SAXParserFactory=org.apache.crimson.jaxp.SAXParserFactoryImpl"

To change JBoss to use the Xerces parser, you would need change the setup to that shown in Figure 11.31 assuming you copied the xerces.jar into the JBoss lib directory.

Figure 11.31. The run.sh setup for the Xerces xml parsers

# Add the XML parser jars and set the JAXP factory names
# Xerces parser JAXP setup
CLASSPATH=$CLASSPATH:../lib/xerces.jar
JAXP=-Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
JAXP="$JAXP -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl"

JBoss does not currently use any XSLT transformers and so does not set a default value for the javax.xml.transform.TransformerFactory system property. To setup the desired transformer you are free to use any of the approaches described in the section called “XSLT Transformer Configuration”.

Using JAXP

To aide in porting your xml parser creation to use the JAXP package, this section gives some small code fragments showing the use of each type of factory. See the JAXP spec or JavaDoc for the full usage details.

Figure 11.32. Example SAX Parser Creation

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

SAXParser parser = null;
DefaultHandler handler = new DefaultHandler()
{
 ...
}

try
{
 SAXParserFactory factory = SAXParserFactory.newInstance();
 parser = factory.newSAXParser();
 String docURI = ...;
 parser.parse(docURI);
}
catch(SAXException e)
{
 ...
}
catch(java.io.IOException e)
{
 ...
}
catch(ParserConfigurationException e)
{
 ...
}
catch(FactoryConfigurationError e)
{
 ...
}

Figure 11.33. Example DOM Parser Creation

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

DocumentBuilder parser = null;
try
{
 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 String docURI = ...;
 parser.parse(docURI);
}
catch(SAXException e)
{
 ...
}
catch(java.io.IOException e)
{
 ...
}
catch(ParserConfigurationException e)
{
 ...
}
catch(FactoryConfigurationError e)
{
 ...
}

Figure 11.34. Example XSLT Transformer Creation

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

Transformer transformer = null;
try
{
 TransformerFactory factory = TransformerFactory.newInstance();
 String stylesheet = "file:///ssheet.xsl";
 String xmldoc = "file:///application.xml";
 StreamSource style = new StreamSource(stylesheet);
 StreamSource src = new StreamSource(xmldoc);
 StreamResult result = new StreamResult(System.out);
 transformer = factory.newTransformer(style);
 transformer.transform(src, dest);
}
catch(TransformerFactoryConfigurationError e)
{
 ...
}
catch(TransformerConfigurationException e)
{
 ...
}
catch(TransformerException e)
{
 ...
}

Common Questions

1. Do I have to use JAXP for xml parsing?
2. Can I mix different xml parsers?
3. What if I have to use an older parser that does not support JAXP?

1. Do I have to use JAXP for xml parsing?

Not necessarily. If you have a specific parser you want to use and you want to uses a parser specific factory you can as long as the parser supports JAXP as this is how JBoss is locating its xml parsers.

2. Can I mix different xml parsers?

If they are all support the same level of the xml standards and JAXP then you should be able to. However, if there are differences then you are likely to see a SecurityException("sealing violation") error thrown.

3. What if I have to use an older parser that does not support JAXP?

The you will need to use your own ClassLoader instance to isolate any common xml parser packages to avoid the sealing violation exception.