Using xsd:anyType 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 on the type chosen to represent the XML document in a service interface has many impacts. The type chosen is 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 xsd:anyType to represent  XML documents on a document-oriented service. For a description of all these strategies, see the Document-Oriented Services entry.

Solution

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

Strategy: Using an XML Fragment With xsd:anyType to Represent the XMLDdocument

This strategy represents the XML business document as an XML fragment. For the service Java interface and implementation, this means that the type will be specified as a SOAPEelement. In JAX-RPC, if there is no standard Java mapping for an XML schema type, it is mapped as an XML document fragment. The XML to Java mapping uses the interface javax.xml.soap.SOAPElement to represent a literal message part in the Java mapping of a wsdl:operation element. For your WSDL file, you can choose to use xsd:anyType as the type to represent the XML document, such as the purchase order.

Let's consider using xsd:anyType in the WSDL file. In XML Schemas, the xsd:anyType represents an abstraction for the base type from which all simple and complex types are derived. An anyType type has no restriction or constraints on the data content, and it is quite possible to use the anyType like other schema types. This anyType can be used to pass an XML document between a service client and service endpoint. The JAX-RPC implementation maps xsd:anyType to a javax.xml.soap.SOAPElement. One big disadvantage of relying on the anyType data type is that the JAX-RPC specification does not define standard Java mapping for the xsd:anyType, so not all JAX-RPC implementations in J2EE 1.4 will behave the same way in mapping this to a SOAPElement. In fact, support for the xsd:anyType is optional for an implementation of JAX-RPC. Usage of anyType can lead to problems with portability and interoperability. One benefit of using XSD:anyType is that it allows the action and the payload to be passed together. This can be useful when creating a polymorphic processor that accepts multiple document types with the same operation. For example, consider a single service that accepts a set of different types of purchase orders, each of which conform to different schema.

One thing to note about using anyType is that it forces the client to wrap the xml document, such as purchase order document, inside a parent element that matches the name WSDL specified for that  parameter element type. This is explained in more detail in the design document for using anyType in a service interface, but let's looks at it briefly here. Consider an example scenario where a web service interface has an operation to submit a purchase order XML document and has a WSDL file like Code Example 1. Notice that this WSDL file declares an element called BusinessDocumentRequest <element name="BusinessDocumentRequest"  type="anyType"/>  which is then mapped to the message received as input to the submitPO operation. As a result, if you have a schema defined for the purchase order, then in essence it will get nested inside a parent element so that the xml transmitted to the service is different than the purchase order schema. For example, a purchase order document would need to get wrapped inside a parent element as shown in Code Example 2. This is inconvenient for developers, and also the XML document does not maintain its integrity with the schema definition.

<types>
    <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="urn:AnyTypePurchaseOrderService">
    <complexType name="submitPO">
    <sequence>
      <element name="BusinessDocumentRequest" type="anyType" />                                          
    </sequence>
    </complexType> 
        ...
    <element name="submitPO" type="tns:submitPO"/>
        ...
    </schema>
</types>
        ...
<message name="AnyTypePurchaseOrderServiceSEI_submitPO">
        <part name="parameters" element="ns1:submitPO"/>
</message>
<portType name="AnyTypePurchaseOrderServiceSEI">
        <operation name="submitPO">
            <input message="tns:AnyTypePurchaseOrderServiceSEI_submitPO"/>
             ...
        </operation>
</portType>

Code Example 1:  Snippet From the WSDL for a Service Using anyType


The result of a service with a WSDL file using anyType for the document type is that the client will need to write code to it. So if the client has a purchase order schema, it will need to create a purchase order document matching that schema and then wrap it inside a parent element. Because the anyType actually defines the data type for a named element in the WSDL, the business document being passed in the SOAP body is located inside this element identified in the WSDL. (For example, in Code Example 2, the PurchaseOrder is inside the BusinessDocumentRequest element.) This means that the document being passed now must either have its root element identified in the WSDL or be constructed appropriately or wrapped in the element on the fly.

<BusinessDocumentRequest>
    <PurchaseOrder>
       .... the rest of purchase order elements here ...
    </PurchaseOrder>
</BusinessDocumentRequest>

Code Example 2: Sample of Purchase Order XML Getting Nested Inside an Element Named BusinessDocumentRequest Specified in the WSDL

In addition to xsdanyType, some services are designed using xsd:any to represent  XML documents in a service interface. Let's look at this alternative strategy of using xsd:any to make a comparison to using xsd:anyType. In XML schema, the <any> element allows the complex types to be extended with elements not specified by the schema. In JAX-RPC, when the xsd:any schema type element is used to represent element wildcards, the mapping of the complex type will get mapped to a JavaBeans[TM] component as usual, however, the presence of the <any> element with a maxOccurs=1 results in an additional property called _any which maps to a javax.xml.soap.SOAPElement (if the maxOccurs is greater than 1, it maps to an array of javax.xml.soap.SOAPElement). The mapping of the <any> element can be leveraged to transport XML documents over the wire in a document-literal formatting. The mapping of the xsd:any has been standardized to map to SOAPElement with JAX-RPC 1.1, which means that you can depend on it being available on different application servers. Another benefit is that xsd:any extends an existing element, with arbitrary content not defined in the schema. This means that even though an element is named in the WSDL and the business document passed appears inside these elements on the wire, the web service with its client can still work with complete XML documents and maintain schema integrity without having to include document content as under these elements (this is not the case with the anyType strategy). The XML document still maintains its integrity with the schema definition.

Besides the comparison of using xsd:any or xsd:anyType in the WSDL for this strategy, let's consider some other issues. With the strategy of using an XML document fragment to represent the XML business document such as a PurchaseOrder, the developer on the client or endpoint would need to work with the SOAPElement APIs to handle processing of the document. These APIs are not well-known APIs, and can be a bit tricky to use. If the developer needed to work with Java objects to process the document, then writing code to bind to those Java objects corresponding to the document, such as the PurchaseOrder, would have to be done. This can have some performance impact.

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.