This Tech Tip reprinted with permission by java.sun.com
Java EE provides various technology choices for handling XML documents. Three of these technologies are Java Architecture for XML Binding (JAXB), Streaming API for XML (StAX), and the Document Object Model (DOM) API. This Tech Tip compares these choices, and shows the technologies in use in a sample application.
JAXB technology provides a way to bind XML schemas to Java objects so that developers can easily process data in their Java applications. The JAXB API provide methods to unmarshal an XML document into a Java object and marshal a Java object into an XML document. For more information about JAXB, see the Tech Tip What is New in JAXB 2.0.
A significant advantage of using JAXB is that you can compile the schema (or dtd) to generate a Java content tree, and then work with plain Java objects. JAXB is not particularly good in cases where complex schemas are involved and you want to work with only a small set of content.
StAX is a streaming API for processing XML documents. It's an event-driven, "pull" parser that reads and writes XML documents. For more information about StAX, see the Tech Tip .
StAX's bidirectional features, small memory footprint, and low processor requirements give it an advantage over APIs such as JAXB or DOM. StAX is particularly effective in extracting a small set of information from a large document. The primary drawback in using StAX is that you get a narrow view of the document -- essentially you have to know what processing you will do before reading the XML document. Another drawback is that StAX is difficult to use if you return XML documents that follow complex schema.
DOM is platform-neutral and language-neutral API that enables programs to dynamically update the contents of XML documents. For more information about DOM, see the Tech Tip Using the Document Object Model.
DOM creates an in-memory object representation of an entire XML document. This allows extreme flexibility in parsing, navigating, and updating the contents of a document. DOM's drawbacks are high memory requirements and the need for more powerful processing capabilities.
The sample application: comparing JAXB, StAX, and DOM
A sample application accompanies this tip. It demonstrates JAXB, StAX, and DOM in use to handle an XML document that is passed as input to a web service. The sample application involves credit card authorization. The application client code calls a web service to authorize payment on a credit card provided by a customer. The client sends credit card and card holder information contained in an XML document to the web service. The client can process the XML document using JAXB, StAX or DOM. The sample demonstrates the XML document processing using all three technologies.
This section describes how to install and run the sample application.
Setting up your environment
The sample uses an open source reference implementation of Java EE 5 called GlassFish. If you haven't already done so, download GlassFish from the GlassFish Community Downloads page. To build and run the sample, you also need JDK 5.0, which you can download from the J2SE 5.0 downloads page, and Apache Ant 1.6.5, which is in the GlassFish bundle (in Windows, it's in the lib\ant subdirectory).
Installing the sample application
Download the sample package and unzip its contents. The root directory for the sample is techtip. Change the current directory to the techtip directory. Edit the script env.sh (for UNIX) or env.bat (for Windows) to reflect your build environment. For example, change the value of the JAVA_HOME environment variable in the script to the location of JDK 5.0 on your system. Then execute the script to set up your environment.
Building the web service
The sample builds a web service using a WSDL file. The steps involved in doing this are:
- Create a WSDL file based on XML schemas.
- Write an endpoint implementation class.
- Generate portable artifacts for web services execution.
- Compile the web service, package it as a WAR file, and deploy it.
Let's look at these steps a little closer.
Create a WSDL file based on XML schemas
A WSDL file is packaged with the sample. You can find the WSDL file, CreditCardService.wsdl, in the conf directory. The WSDL file exposes web service operations that authorize credit card payments. There's a separate operation for each of the three XML handling technologies used in the application, JAXB, StAX, and DOM. For more information about WSDL, see Web Services Description Language (WSDL) 1.1.
The two schema files that the WSDL file imports are CreditCardAuthorization.xsd and CreditCardServiceException.xsd. CreditCardAuthorization.xsd defines the structure of the XML document that a client can send to the web service. The elements in the schema that are pertinent to credit card authorization requests are:
The type value tns:AuthorizationRequest is a complex type with elements for information about the credit card and its user. For StAX, the element type is xsd:string, and for DOM the element type is xsd:any. Similar elements are defined and used for returning authorization status.
CreditCardServiceException.xsd defines the structure of an XML document for returning an error message, that is, when the web service cannot process the request.
Generate portable artifact
The sample uses the wsimport tool to generate portable artifacts such as the Service Endpoint Interface (SEI), the service class, JAXB classes, and exception classes. In the sample this is done in an ant task that has the target name generate-server. You can find the ant tasks for the sample in the build.xml file in the techtip directory. The XML for the ant task that generates the portable artifacts is as follows:
The ant variables mentioned above are defined in the build.properties file in the conf directory. Notice the
After the artifacts are generated, they're compiled using the javac compiler. In the sample, this is done using an ant task with the target name compile-server.
Write an endpoint implementation class
The sample provides an endpoint implementation class, CreditCardService.java, which you can find in the src\server directory. CreditCardService.java implements the SEI that was generated in the previous step using CreditCardService.wsdl and the wsimport tool. The class contains the methods for the different document handling technologies.
Here is the method that makes use of JAXB:
The method receives a JAXB-generated object as a parameter. The method retrieves relevant JAXB objects: CreditCard and CardUser. It then uses these objects to get required information, such as the credit card number and card user name. Next, the method calls the business logic in the application to authorize the charge on the card. The dao object is an instance of the CreditCardDAO class in src\server directory. This class provides information such as an authorization token, whether the charge is authorized or not, and an error code, if any. Finally, the method populates and returns the authorization status in a JAXB object.
Here is the method that uses StAX for performing the same authorization task. The parameter passed to the method is a String object, which is actually an XML document.
StAX parsers use an XMLStreamReader to read XML documents, and an XMLStreamWriter to write them back. The XMLInputFactory is used to configure the XMLStreamReader. The next block of code in the method traverses the XML document and reads from the elements of interest:
The business logic in the application authorizes the charge on the card. Then the method creates the response XML document. In the code below, notice that an XMLOutputFactory object is used to create an XMLStreamWriter. The XMLWriter writes the response XML document. The web service response is sent back as a String object.
Here is the method that uses DOM. The parameter to the method gives the root element of the XML document sent by the client. The method uses it to parse the document and gather the required information about the credit card and its user.
As before, the method calls the application's business logic to authorize the credit charge. Next, the method creates the response using a SOAPElement class. Notice that a SOAPFactory object is used to create the root element. Child elements are then added with authorization information.
Compile the web service, package it as a WAR file, and deploy it
You need to compile the service implementation class as well as portable artifacts for the web service that were generated earlier by running wsimport on CreditCardService.wsdl. Next the classes need to be packaged into a WAR file along with the deployment descriptor for web services, sun-jaxws.xml. These steps are performed in the sample by an ant task with the target build.
Building the client
Here are the steps to build the web service client:
- Write the client class.
- Generate portable artifacts for web service execution.
- Compile the client.
Write the client class
A standalone web service client, CreditCardServiceTest.java, is packaged with the sample. You can find it in the src\client directory. The client calls the credit card web service to authorize payment on a credit card provided by the customer. The client sends credit card and card holder information contained in an XML document to the server. The client can process the XML document using JAXB, StAX or DOM, and in fact, uses all three technologies.
Here's the method in the client that calls the service using JAXB. A JAXB unmarshaller converts an XML document into a Java object. The client uses an instance of the Unmarshaller to unmarshal an XML document into a JAXB object for the authorization request. The client then makes a call to the web service.
Notice that the response from the service is a JAXB authorization status object. Also, stubC is a proxy that is used to invoke methods on the service endpoint interface. It's used in all the XML handling methods in the client. The proxy is initialized in the constructor of the CreditCardServiceTest class.
As an alternative to using an XML document, the client could populate relevant JAXB objects and then make the service call. You can see this approach in the method testAuthorizePaymentJAXB() in CardServiceTest.java.
Here's the method in the client that calls the service using StAX. This method passes the XML document to the service in the form of a String object. The response from the service is also a String. The readStringFromFileRaw method is a utility method that reads an XML file and returns a String.
Finally, here is the method in the client that uses DOM to make the web service call. The utility method createElementMessage returns the document's root element after reading the XML file. The client uses the document's root element in the web service call. The response from the service can be displayed through DOM traversal APIs.
Generate portable artifacts
Generate client-side portable artifacts using the WSDL on server. This is done in the sample using an ant task with the target build. Actually, when you call ant target build, it compiles both the server and client classes, including the generated artifacts. It also builds a deployable WAR file. Note that the client uses a JAXB binding configuration file, config-client.xml.
Running the sample
To run the sample:
- Start GlassFish by entering the following command:
- Build the web service, the client, and needed artifacts, and package it into a WAR file by entering the following command:
- Deploy the application by entering the following command:
- Run the application by entering the following command:
- Undeploy the application by entering the following command:
- Delete all classes and the WAR file generated for the application by entering the following command:
%J2EE_HOME%/bin/asadmin start-domain domain1
Ensure that the J2EE_HOME environment variable is set to the GlassFish install directory.
The command runs the application using all three XML handling technologies. You should see output that looks something like this:
run: [java] Calling Credit Card Service using JAXB [java] Authorization token = 84706723 [java] Authorized = true [java] Error code = 0 [java] Calling Credit Card Service using STAX [java]
[java] Calling Credit Card Service using DOM [java] authorizationToken = 66927959 [java] authorized = true [java] errorCode = 0 39114069 true 0
About the Author
Deep Singh is a staff member of Java Performance Engineering group at Sun Microsystems.
Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.