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:
- Using String to represent the XML document
- Using a schema-defined type to represent the XML document
- Using an XML fragment to represent the XML document (using
xsd:anyType)
- Using an XML fragment to represent the XML document (using
xsd:any)
- Using attachments to package the XML document
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.