Using Strings to Represent XML Documents in a Service Interface

Sean Brydon, Smitha Kangath, Sameer Tyagi

Problem Description

When designing a web service interaction where a client and service exchange an XML document, developers need to choose a type to represent the XML document in the service interface. This decision has many impacts. The type chosen will be reflected in the WSDL file describing the service and also in the code of the service implementation. In Java[TM] 2 Platform, Enterprise Edition (J2EE[TM] platform) 1.4 applications, XML documents, such as purchase orders or invoices, are exchanged using Java API for XML-based RPC (JAX-RPC). There many strategies to consider for choosing a type to represent an XML document when designing a service interface: This solution focuses on the design considerations when choosing to use the string type to represent XML documents in a document-oriented service. For a description of all these strategies, see the Document-Oriented Service entry.

Solution

Let's consider some of the issues when using xsd:string to represent the XML document being exchanged between a client and service.

In describing this strategy, we will use an example of passing a PurchaseOrder XML document from a client to a service which receives the purchase order. The purchase order document being exchanged is a typical purchase order which includes data such as the order ID, the contact information, and the line items for the goods being purchased.

Strategy: Using a String to Represent the Document

An XML document can be passed as a string between the client and the service. In this strategy, an XML document is transformed into one String which contains all the elements and content of an XML document. This provides a simple option for passing complex business documents without the need for creating serializers or performing encoding-decoding on the underlying elements. This is a simple interface to create because some people are comfortable with Strings. In this strategy it means that your Java interface would have String as the parameter for the document, such as public void submitPO(String PO), and the WSDL file would have the input parameter of xsd:string.

The following example demonstrates this strategy. Note that the WSDL file,  corresponding Java service interface, and implementation classes all use a string type to represent the xml document. The important thing to note here is that the purchase order is represented as a string. Code Example 1 shows a snippet of the WSDL file for a service exchanging a purchase order xml document represented with the string type.

<?xml version="1.0" encoding="UTF-8"?>
  <definitions name="StringPurchaseOrderService"
    targetNamespace="urn:StringPurchaseOrderService" 
    xmlns:tns="urn:StringPurchaseOrderService"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <types>
    <schema targetNamespace="urn:StringPurchaseOrderService" xmlns:tns="urn:StringPurchaseOrderService" 
    xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://www.w3.org/2001/XMLSchema">
   <complexType name="submitPO">
     <sequence>
       <element name="String_1" type="string" nillable="true"/>
     </sequence>
   </complexType>
    ...
   <element name="submitPO" type="tns:submitPO"/>
    ...
   </schema>
  </types>
  <message name="StringPurchaseOrderServiceSEI_submitPO">
    <part name="parameters" element="tns:submitPO"/>
  </message>
  ...
</definitions>

Code Example 1: WSDL File Snippet for Service Using String to Represent the XML Document for a Purchase Order

Note that the Java interface in Code Example 2 corresponding to the WSDL file of the service will also specify String as the type for the purchase order XML document. That means the String xmlPO would have all the document data as well as the XML tags set as its value.

public interface PurchaseOrderServiceSEI extends Remote {  
    public String submitPO(String xmlPO)
                                throws InvalidPOException, RemoteException;
}

Code Example 2: Purchase Order Java Interface Corresponding to WSDL File of Service

Just as in the service interface, the Java implementation would also have to handle the purchase order XML document as a String. Code Example 3 shows an implementation of the service interface. This example shows an EJB bean implementation of the service interface, but could have instead chosen to use a web component to implement it.

public class PurchaseOrderServiceBean implements SessionBean {
  ...
  public String submitPO(String xmlPO) throws InvalidPOException, RemoteException {
        String id =null;
        //validate the doc against its schema      
        if (!(validate(xmlPO))) {
            throw new InvalidPOException("Error parsing the purchase order XML document!!!");
        }
        try {
            //extract the PO ID from the document and return to the client
            id = getID(xmlPO);
        } catch (Exception e) {
            throw new EJBException("StringPurchaseOrderService implementation had trouble parsing PO.xml, some system or
            configuration problem " + e.getMessage(), e);
        }
        //this is done just to illustrate throwing an application specific exception
        if(id.equals("100"))
            throw new InvalidPOException("Invalid ID for the purchase order!!! " +
                    "For demo purposes, we throw " +
                    "an application defined exception for the ID value of 100.");
        return id;
    }

}
Code Example 3: Purchase Order Service Endpoint Implementation Class

In addition to creating the interface artifacts that have string to represent the document, the endpoint developer must also consider how to handle this document. One common requirement of an endpoint is to validate the purchase order document that was received. Because the purchase order is a string, it can not be validated against its schema by the JAX-RPC runtime (as can be done by other strategies), so the application must write code to validate the purchase order against its schema. Therefore, one weakness in this strategy is that the schema validation offered by the runtime cannot be used, and errors with the document will not be picked up until the service has read the document in memory and attempted to process it.

Another requirement common in endpoints is that they need to process the document. Often that means binding to some Java types, such as a PurchaseOrder.java and corresponding LineItem.java objects. This binding is often done in the service interaction layer before delegating to the business processing layer which may have an existing Java data model. For other strategies, such as using a schema-defined type to represent the XML document where the purchase order schema details are embedded in the WSDL, this binding is done automatically by the JAX-RPC runtime. So the developer must write code to handle transforming the string document into Java objects representing the document. This is a bit more work for the developer and can cause some performance impact.

Let's consider some impacts on the client code when a service uses the string type to represent the document being exchanged. The client needs to take its PurchaseOrder.xml document and create a String version to use the service as defined in the WSDL file. The client can pass the business document to the service after converting it to a String. Creating a String version of an XML doc is an extra step of work that the client must do when an endpoint uses String to represent the XML document. Also, because the WSDL defines the parameter for the purchase order as a string, the WSDL does not really describe the service interface very well. If the WSDL file specifies string as the type of a document, how does the client developer know the schema of that document? In contrast, the strategy of using a schema-defined type to represent the XML document  will include the schema of the purchase order XML document in the WSDL, which makes the service description more complete and therefore easier for clients to determine the requirements of the service. If string is used in the WSDL to represent the purchase order XML document, then the service would need to publish a description somewhere else to aid clients interested in accessing the service. This is a weakness in this strategy of using string to represent an XML document being exchanged with a service.

When a String document is passed from a client to a service, like any payload, it is serialized onto the wire. The JAX-RPC runtime will create the appropriate escape characters for the tags and quotes in the XML as shown in the SOAP request below. Note that by adding all the info to encode the string, this can add to the size of a message. Code Example 4 shows the string encoding of the purchase order. You can see the extra added content. The String received by the server in its implementation class will contain the original XML that was created on the client side. Note that the original document would be a bit smaller.

POST /xmlstring/jaxrpc HTTP/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: 1397
SOAPAction: ""
User-Agent: Java/1.4.2_03
Host: localhost:9090
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schema.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:enc="http://schema.xmlsoap.org/soap/encoding/"
xmlns:ns0="http://www.examples.com/types">
<env:Body>
<ns0:submitPO>
<String_1>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&#13;
&lt;PurchaseOrderDocument&gt;&#13;
&lt;createDate&gt;11-15-04&lt;/createDate&gt;&#13;
&lt;shipTo&gt;&#13;
&lt;street&gt;abc st&lt;/street&gt;&#13;
&lt;city&gt;abc city&lt;/city&gt;&#13;
&lt;state&gt;CA&lt;/state&gt;&#13;
&lt;zipCode&gt;99999&lt;/zipCode&gt;&#13;
&lt;/shipTo&gt;&#13;
&lt;billTo&gt;&#13;
&lt;street&gt;abc st&lt;/street&gt;&#13;
&lt;city&gt;abc city&lt;/city&gt;&#13;
&lt;state&gt;CA&lt;/state&gt;&#13;
&lt;zipCode&gt;99999&lt;/zipCode&gt;&#13;
&lt;/billTo&gt;&#13;
&lt;items&gt;&#13;
&lt;itemname&gt;Glass Ceiling Fan&lt;/itemname&gt;&#13;
&lt;price&gt;2&lt;/price&gt;&#13;
&lt;quantity&gt;200.0&lt;/quantity&gt;&#13;
&lt;/items&gt;&#13;
&lt;items&gt;&#13;
&lt;itemname&gt;Stainless Steel Blender &lt;/itemname&gt;&#13;
&lt;price&gt;1&lt;/price&gt;&#13;
&lt;quantity&gt;75.0&lt;/quantity&gt;&#13;
&lt;/items&gt;&#13;
&lt;/PurchaseOrderDocument&gt;&#13;
</String_1>

</ns0:submitPO>
</env:Body>
</env:Envelope>

Code Example 4: The SOAP Request of an XML Document Represented Using the String Type

References

For more information about this topic, refer to the following:

© Sun Microsystems 2005. All of the material in The Java BluePrints Solutions Catalog is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.