java left logo
java middle logo
java right logo
 

Home arrow Java EE Tips
 
 
Main Menu
Home
Java Tutorials
Book Reviews
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Java Network
Java Forums
Java Blog




Most Visited Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews
Top Rated Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews


Statistics
Registered Users: 4088
Java SE Tips: 614
Java ME Tips: 202
Java EE Tips: 183
Other API Tips: 779
Java Applications: 298
Java Libraries: 209
Java Games: 16
Book Reviews:
 
 
 
Document Handling in Web Services Applications E-mail
User Rating: / 15
PoorBest 

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

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

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

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:

  1. Create a WSDL file based on XML schemas.
  2. Write an endpoint implementation class.
  3. Generate portable artifacts for web services execution.
  4. 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.

Schema files

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:

  <element name="AuthorizationRequest" 
  type="tns:AuthorizationRequest"/>
   
  <element name="authorizePaymentSTAX" type="xsd:string"/>
   
   <element name="authorizePaymentDOM">
       <complexType>
               <sequence>
                       <any maxOccurs="1"/>
               </sequence>
       </complexType> 
   </element>  

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:

   <target name="generate-server" depends="prepare">
      <wsimport
          ...
              
          wsdl="${server.wsdl}">
        <binding dir="${confdir}" 
          includes="${server.config}"/>
      </wsimport>
   </target> 

The ant variables mentioned above are defined in the build.properties file in the conf directory. Notice the element. It uses an external binding file, config-server.xml, that you can find in the conf directory. In JAXB, you bind the schema for an XML document into a set of Java interfaces and classes that represents the schema. You then compile the interfaces and classes. The config-server.xml file defines the JAXB bindings for the schema used in the sample. As far as compiling the interfaces and classes that represent the schema, GlassFish includes JAX-WS which internally calls JAXB's binding compiler, xjc.

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:

   public AuthorizationStatus authorizePaymentJAXB(
    AuthorizationRequest parametersthrows 
    com.sun.techtip.cardservice.service.CardServiceException {
      try 
          CreditCard card = parameters.getCreditCard();
          CardUser user = parameters.getCardUser()
   
          // For sake of simplicity, read only limited 
          // information about credit card and credit card user
          String cardNumber = card.getCardNumber();
          String lastName = user.getLname();
   
          // Emulate charge authorization
          dao.authorizeCharge(cardNumber, lastName);

          // Create and populate authorization status object
          ObjectFactory of = new ObjectFactory();
          AuthorizationStatus status = 
            of.createAuthorizationStatus();
          status.setAuthorizationToken(dao.authorizationToken);
          ...
          
          return status; 

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.

   public String authorizePaymentSTAX(String parametersthrows 
    CardServiceException {
      try {
          // Create the StAX reader to read the XML document
          StringReader strReader = new StringReader(parameters);
          XMLInputFactory staxFactory = 
            XMLInputFactory.newInstance();
          staxFactory.setProperty(
            XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
          XMLStreamReader xmlReader = 
            staxFactory.createXMLStreamReader(strReader);

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:

   // For sake of simplicity, we read only limited information 
   // about credit card and credit card user 
   String cardNumber= null;
   String lastName = null;
   while (xmlReader.hasNext()) {
       if (xmlReader.isStartElement()) {
           String sName = xmlReader.getLocalName();
           if (sName.equals("cardNumber")) {
               cardNumber = xmlReader.getElementText();
           }
           if (sName.equals("lname")) {
               lastName = xmlReader.getElementText();
           }
        }
        xmlReader.next();
   }
   xmlReader.close()

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.

   // Emulate charge authorization
   dao.authorizeCharge(cardNumber, lastName);
   
   // Create response XML document
   StringWriter strWr = new StringWriter();
   XMLStreamWriter resvStatusWr = 
     XMLOutputFactory.newInstance().createXMLStreamWriter(strWr);
   resvStatusWr.writeStartDocument()
   resvStatusWr.writeStartElement(
     "ns0""AuthorizationStatus""urn:CardService")
   resvStatusWr.writeStartElement(
     "ns0""authorizationToken""urn:CardService");
   resvStatusWr.writeCharacters(dao.authorizationToken);
   resvStatusWr.writeEndElement()
   ...
   
   resvStatusWr.writeEndDocument();
   
   return strWr.toString();

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.

   public AuthorizeStatusDOM authorizePaymentDOM(
    AuthorizePaymentDOM parametersthrows 
    CardServiceException {
     try {
         Element element = (Element)parameters.getAny();

         // For sake of simplicity, we read only limited 
         // information about credit card and credit card user 
         Node cardNode = (
           element.getElementsByTagName("cardNumber")).item(0);
         String cardNumber = 
           cardNode.getFirstChild().getNodeValue();
         Node lnameNode = 
           (element.getElementsByTagName("fname")).item(0);
         String lastName = 
           lnameNode.getFirstChild().getNodeValue();

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.

   // Emulate charge authorization
   dao.authorizeCharge(cardNumber, lastName);
   
   SOAPFactory sf = SOAPFactory.newInstance();
   SOAPElement root = sf.createElement(
     "AuthorizationStatus","ns0","urn:CardService");
   SOAPElement token = sf.createElement("authorizationToken");
   token.addTextNode(dao.authorizationToken);
   root.addChildElement(token);
   ...
   
   ObjectFactory of = new ObjectFactory();
   AuthorizeStatusDOM status = of.createAuthorizeStatusDOM();
   status.setAny(root);
      
   return status;

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:

  1. Write the client class.
  2. Generate portable artifacts for web service execution.
  3. 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.

   public void testAuthorizePaymentJAXB(
    String authrequestXMLfilethrows Exception 
       try {
           // Get the unmarshaller to convert XML into Object
           JAXBContext jc = 
             JAXBContext.newInstance("creditcard");
           Unmarshaller u = jc.createUnmarshaller();

           // Unmarshal the XML document into authorization 
           // request object
           JAXBElement cardAuthorizationElement = 
             (JAXBElement)u.unmarshal(
             new FileInputStream(authrequestXMLfile));
           AuthorizationRequest cardAuthorizationRequest = 
             (AuthorizationRequest)
             cardAuthorizationElement.getValue();

          // Make web service call
          AuthorizationStatus reply = 
            stubC.authorizePaymentJAXB(cardAuthorizationRequest);

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.

   public void testAuthorizePaymentSTAX(
    String authrequestXMLfilethrows Exception {
       // Read XML document into a string
       String authRequest = 
         readStringFromFileRaw(authrequestXMLfile);
       try {
           // Make web service call 
           String reply = 
             stubC.authorizePaymentSTAX(authRequest);

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.

 public void testAuthorizePaymentDOM(String authrequestXMLfile
  throws Exception    {
   // Get document root element
   Element authRequest = 
     createElementMessage(authrequestXMLfile);
   try {
           // Populate authorization request object
           ObjectFactory of = new ObjectFactory()
           AuthorizePaymentDOM msg = 
             of.createAuthorizePaymentDOM();
           msg.setAny(authRequest);

           // Make web service call 
           AuthorizeStatusDOM reply = 
             stubC.authorizePaymentDOM(msg);

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:

  1. Start GlassFish by entering the following command:
  2.             %J2EE_HOME%/bin/asadmin start-domain domain1
    

    Ensure that the J2EE_HOME environment variable is set to the GlassFish install directory.

  3. Build the web service, the client, and needed artifacts, and package it into a WAR file by entering the following command:
  4.             ant build
    
  5. Deploy the application by entering the following command:
  6.             ant deploy
    
  7. Run the application by entering the following command:
  8.             ant run
    

    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] 
                  39114069
                  true0
                  
                  [java] Calling Credit Card Service using DOM
                  [java] authorizationToken = 66927959
                  [java] authorized = true
                  [java] errorCode = 0
    
  9. Undeploy the application by entering the following command:
  10.             ant undeploy
    
  11. Delete all classes and the WAR file generated for the application by entering the following command:
  12.             ant clean
    

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.

 Related Tips

 
< Prev   Next >

Page 1 of 0 ( 0 comments )

You can share your information about this topic using the form below!

Please do not post your questions with this form! Thanks.


Name (required)


E-Mail (required)

Your email will not be displayed on the site - only to our administrator
Homepage(optional)



Comment Enable HTML code : Yes No



 
       
         
     
 
 
 
   
 
 
java bottom left
java bottom middle
java bottom right
RSS 0.91 FeedRSS 1.0 FeedRSS 2.0 FeedATOM FeedOPML Feed

Home - About Us - Privacy Policy
Copyright 2005 - 2008 www.java-tips.org
Java is a trademark of Sun Microsystems, Inc.