Skip to main content

Web services programming tips and tricks: Using the <xsd:any/> element for custom serialization

Keep control over JAX-RPC serialization and deserialization

Andre Tost, Senior Certified IT Specialist, IBM Software Group
Andre Tost works as a Solution Architect in the WebSphere Business Development group, where he helps the IBM Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family and play and watch soccer whenever possible.

Summary:  For the most part, JAX-RPC assumes that XML elements that occur in a SOAP message should be mapped into Java objects. There are rules for how simple and complex types are mapped, and JAX-RPC implementations typically provide tooling that generates the necessary code to handle this. The good news is that if you are dealing with Java objects in your application, you don't have to worry about type mapping and serialization and deserialization of data. That is, you don't have to know how to parse an XML element and turn it into the appropriate Java object, and vice versa. However, in some cases you might want to keep control over how this (de-)serialization is done. Or you don't want to map XML data into Java objects at all. Luckily, there is a way to do just that in JAX-RPC, and this tip will show you how to do it.

Date:  27 Jan 2004
Level:  Intermediate
Activity:  2704 views

SOAP with Attachments API for Java (SAAJ)

The JAX-RPC specification relies on SAAJ for its handling of SOAP messages. SAAJ defines classes and interfaces for all of the pieces of a SOAP message. This begins with the javax.xml.soap.SOAPMessage class, which gives you access to the javax.xml.soap.SOAPEnvelope instance, which in turn lets you retrieve the javax.xml.soap.SOAPHeader and javax.xml.soap.SOAPBody instances, and so forth. All of them extend and inherit the javax.xml.soap.SOAPElement interface, which itself extends the W3C DOM Node interface.

In other words, SAAJ provides you with an XML-centric view of the elements of a SOAP message. JAX-RPC delegates all handling of messages to SAAJ. Note that I am not trying to offer a comprehensive view of SAAJ here, I just cover it as much as is needed for the topic of this tip.


The <xsd:any/> element

The <xsd:any/> element is an element that represents arbitrary XML content within an XML document. It is what its name indicates: any kind of XML. This lets you create complex type definitions in an XML Schema without describing what the exact structure of certain parts of the complex type is. Here is an example (see Listing 1) that shows the definition of a type called Order. It contains two regular elements and one <xsd:any/> element.


Listing 1. XML Schema with <xsd:any/>
<schema elementFormDefault="qualified"
   targetNamespace="http://anytip.webservices.ibm.com"
   xmlns="http://www.w3.org/2001/XMLSchema">

   <complexType name="Order">
      <sequence>
         <element name="createDate" nillable="true" type="xsd:dateTime"/>
         <element name="customer" nillable="true" type="xsd:string"/>
         <xsd:any maxOccurs="unbounded"/>
      </sequence>
   </complexType>
</schema>

An instance of this type can contain any number of additional XML elements without violating the schema definition. This way, you can add additional information to an Order element without defining its format in the schema.


Bringing it together

So how does JAX-RPC handle an XML Schema that contains an <xsd:any/> element? The recently published JAX-RPC 1.1 specification defines that this element is mapped to the SAAJ's javax.xml.soap.SOAPElement interface (see Resources). This means that the Service Endpoint Interface will contain a parameter or return value of type javax.xml.soap.SOAPElement for each place in the schema where <xsd:any/> was used and, respectively, javax.xml.soap.SOAPElement[] if the maxOccurs attribute is bigger than 1.

Therefore, a JAX-RPC tool will generate the following class (see Listing 2) from the sample schema above (as usual, this sample does not make a lot of sense and only shows the concept; and also as usual, you can find the complete source for this article in the Resources section):


Listing 2. The generated Order class
public class Order  implements java.io.Serializable {
    private java.util.Calendar createDate;
    private java.lang.String customer;
    private javax.xml.soap.SOAPElement[] _any;
    ...
}

What does all of this have to do with custom serialization? Assume that your Web service uses some data that you don't want to be mapped into a Java class, but rather want to let the JAX-RPC engine hand it to the implementation in its XML form. The implementation could then parse it or simply pass it on as XML for further processing in the backend application. Similarly, you can create a client proxy that lets you pass in a SOAPElement rather than a mapped Java object.


An example

This example also works in cases where you know the structure of the XML data beforehand. Imagine you use an OrderManager Web service which returns Order data based on some search criteria. Each Order instance contains a number of line items. Here is an extract of the WSDL in Listing3. Assuming that this is a pretty straightforward Web service, we will only look at the <types> section here.


Listing 3. WSDL for the Web service
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ...>
 <wsdl:types>
  <schema elementFormDefault="qualified" 
          targetNamespace="http://any.webservices.ibm.com" 
          xmlns="http://www.w3.org/2001/XMLSchema">
   <element name="getOrder">
    <complexType>
     <sequence>
      <element name="searchCriteria" 
               nillable="true" type="xsd:string"/>
     </sequence>
    </complexType>
   </element>
   <complexType name="Order">
    <sequence>
     <element name="createDate" nillable="true" type="xsd:dateTime"/>
     <element name="customer" nillable="true" type="xsd:string"/>
     <element name="lineItems" nillable="true" type="impl:LineItem"
              maxOccurs="unbounded"/>
    </sequence>
   </complexType>
   <complexType name="LineItem">
    <sequence>
     <element name="itemDesc" nillable="true" type="xsd:string"/>
     <element name="itemNumber" nillable="true" type="xsd:string"/>
    </sequence>
   </complexType>
   <element name="getOrderResponse">
    <complexType>
     <sequence>
      <element name="getOrderReturn" 
               nillable="true" type="impl:Order"/>
     </sequence>
    </complexType>
   </element>
  </schema>
 </wsdl:types>
 ...
</definitions>

Now imagine that you don't want the JAX-RPC engine to generate a LineItem Java class that maps the structure as defined in the XML Schema, but rather want to deal with the XML yourself (maybe because you directly store it as XML in a database, so that parsing it is not necessary at all). Therefore, before generating the client code for this Web service, you change the WSDL file and replace the element representing the lineItems with the <xsd:any/> element. The Order complex type will now look exactly like what you had seen earlier. The JAX-RPC tools will now generate a client side Order class that contains the SOAPElement property, instead of a lineItem class. The example above has already shown what this class looks like.

Now you can create client code that will retrieve an Order from the Web service, and use the line item information in its XML form. Here is an example test client in Listing 4, generated using WebSphere Application Server V5.0.2, which shows you what this could look like:


Listing 4. Sample client code
public class TestMain {

	public static void main(String[] args) throws Exception {
		OrderManager om = 
                  new OrderManagerServiceLocator().getOrderManager();
		Order order = om.getOrder("whatever");
		SOAPElement lineItem = order.get_any()[0];
		System.out.println("Line item is : "+lineItem.toString());
	}
}

This client application will retrieve the Order as a Java object, but the line item information is returned in XML form, as an array of SOAPElements.


Summary

JAX-RPC provides a Java-centric view on Web services. If you want to do your own processing of some of the XML artifacts in a SOAP message, you can use the SAAJ API together with the <xsd:any/> element to do so. You can expect future versions of JAX-RPC engines to make this even easier. In fact, the JAX-RPC 1.1 specification mandates that compliant tools offer you for each type the option to map it either to a Java class or to a javax.xml.soap.SOAPElement.



Download

NameSizeDownload method
ws-xsdany.ear43.0 KB HTTP

Information about download methods


Resources

About the author

Andre Tost works as a Solution Architect in the WebSphere Business Development group, where he helps the IBM Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family and play and watch soccer whenever possible.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services, XML
ArticleID=11873
ArticleTitle=Web services programming tips and tricks: Using the <xsd:any/> element for custom serialization
publish-date=01272004
author1-email=
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers