Using xsd:any 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 are 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:any to represent XML documents in 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 that arise when using an XML fragment with xsd:any to represent the XML document being exchanged between a client and service. This solution to use xsd:any to represent the XML document being exchanged in a service interface is very useful in cases where the service endpoint may receive many types of documents and each document has its own schema. And you want to design the interface to receive any of these types of documents. This helps when designing brokers or more generic service interfaces. Because the xsd:any type is essentially a wildcard, it can be used as a type when you want to receive documents with different schemas on the same operation. Because the WSDL interface will specify xsd:any as the type for the XML documents to be received, the WSDL does not contain the schemas of the documents the service might expect. As a result, the clients of the service  must find another mechanism, such as auxiliary documentation, to determine the set of expected document types. The service implementation will need to write code to validate and process the set of documents that are expected and also handle the case for documents of an unexpected schema. This is in contrast the the strategy where the WSDL file specifies the use of a schema-defined type for the documents used by the service. In a nutshell, this solution of using xsd:any is useful when you want a generic operation where the service operation uses a varied set of XML documents, but this puts the burden on the service implementor to handle those types in terms of validation, processing, binding to Java objects, and so forth.

Strategy: Using an XML Fragment With xsd:any to Represent the XML Document

In XML schema, the wildcard <xsd:any> element allows the complex types to be extended with elements not specified by the schema. This <xsd:any> element can also be useful when the contents of the complex type don’t actually need to be defined in the schema. For example, consider a situation where the service operation may receive more than one type of purchase order XML document, and each purchase order has a different schema defined. In this case, it's useful to describe the element purchase order document type as <any> in the service interface. This makes the endpoint more generic. It also means that the service implementation code must determine which type of xml document it receives and handle it appropriately. Using <any> will make the service operation more generic, so your code must be able to handle it. In the WSDL file in Code Example 1, note that there is a type submitPO defined which includes an <any> element, so it sort of wraps the <any> inside another element declaration. This submitPO type is then used in the service interface for the operation to submit a purchase order. (Note that the element name submitPO and the operation name submitPO are the same, and this is just because the WSDL uses the wrapped style which specifies a convention of these names matching.) For this service, the document being received can have any elements in the XML.

<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:AnyPurchaseOrderService">

    <complexType name="submitPO">
      <sequence>
          <any/>                       
      </sequence>
    </complexType>   
    <element name="submitPO" type="tns:submitPO"/>
  </schema>
</types>

<message name="AnyPurchaseOrderServiceSEI_submitPO">
  <part name="parameters" element="tns:submitPO"/>
</message>
 
...

<portType name="AnyPurchaseOrderServiceSEI">
  <operation name="submitPO">
      <input message="tns:AnyPurchaseOrderServiceSEI_submitPO"/>
      ...
  </operation>
</portType>

Code Example 1: WSDL Snippet Showing the Usage of <any> for a Service Operation Input Parameter

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. 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). Also, in JAX-RPC, if there is no standard Java mapping for an XML schema type, a message part with literal representation is considered and 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. As a result, if you generate a Java interface from a WSDL file such as in Code Example 1 which uses <any> for the document being received, then your Java interface may have a wrapper class of type SubmitPO, as shown in Code Example 2. In this case, the Java implementation of this interface will need to call a getter method  get_any() on the SubmitPO parameter to get the SOAPElement which is wrapped inside. This extra step to call is a bit inconvenient but not much trouble.

public interface AnyPurchaseOrderServiceSEI extends Remote {
    public SubmitPOResponse submitPO(SubmitPO parameters) throws
        InvalidPOException,  java.rmi.RemoteException;
}

Code Example 2:Service Interface Used to Access the Web Service

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.