Using SOAP with Java | Writing a Deserializer

Writing Deserializer

Deserialization is the reverse process of constructing Java objects out of the XML instance. In the SOAP context, to write a Deserializer we will traverse through a DOM Node of the XML instance of the object, find the required tags containing the required values for the attributes of our complex Java object, assign the values to the object and return it. The unmarshall() method of the Deserializer interface has a return type of org.apache.soap.util.Bean which holds a reference to the destination java data-type.

public Bean unmarshall(String inScopeEncStyle,QName elementType,Node src,
  XMLJavaMappingRegistry xjmr,SOAPContext ctx) 
                       throws IllegalArgumentException

The parameters to the marshall method represent the following properties:

  • inScopeEncStyle : This represents the encodingStyleURI as specified in the enclosing Call or Response object.
  • elementType : This is the Qname of the type to be deserialized.
  • xjmr : This is the XMLJavaMappingRegistry object.
  • ctx : This is used to pass in things like javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpSession from the servlet context.

The first step is to construct an instance of the destination java object to which we will assign the values.

//creating an instance of the destination java object
Person person = new Person();

We now prepare to traverse through the Node object to obtain different elements in it and inspect their tag names and the values. As the DOM is based around parent and child node relationship, we loop through every child element, compare the tag names with the Qnames of the attributes of the java object and if matched unmarshall it to a Bean object. The Bean object in all cases holds the type of the returned object.
The Bean object holds the value as a reference to a java.lang.Object type. We need to cast it down to a Parameter object. We then obtain the required value from the Parameter object, cast it to the appropriate data-type and assign it to the destination java object.

         Element personElement = (Element)src;
        Element childElement = DOMUtils.getFirstChildElement(personElement);
         while(childElement !=null)
        {
            String tagName = childElement.getTagName();
            if(tagName.equals("name"))
            {
                Bean bean = xjmr.unmarshall(inScopeEncStyle, 
                  RPCConstants.Q_ELEM_PARAMETER, childElement, ctx);
                Parameter param = (Parameter)bean.value;
                person.setName((String)param.getValue());
            }
            if(tagName.equals("age"))
            {
                Bean bean = xjmr.unmarshall(inScopeEncStyle, 
                  RPCConstants.Q_ELEM_PARAMETER, childElement, ctx);
                Parameter param = (Parameter)bean.value;
                person.setAge( ( (Integer)param.getValue()).intValue());
            }
            childElement = DOMUtils.getNextSiblingElement(childElement);
                
        }
        return new Bean(Person.class, person);

Finally we return a Bean object with a reference to the destination java object Person.

Deployment descriptor

The deployment descriptor remains more or less the same as the one we created for our previous Java bean based example. The only change is in the java2XMLClassName and XML2JavaClassName attributes where we specify our own Serializer and DeSerializer class names. The changed deployment descriptor looks like the following:

<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" 
returnid="urn:greetingService">
  <isd:provider type="java" scope="Application" methods="sayGreeting">
    <isd:java class="sam.soap.service.SoapService" static="false"/>
  </isd:provider> 
<isd:mappings>
    <isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
             xmlns:x="urn:greetingService" qname="x:sam.soap.client.Person"
             javaType="sam.soap.client.Person"
             java2XMLClassName="sam.soap.client.PersonSerializer"
             xml2JavaClassName="sam.soap.client.PersonSerializer"/>
  </isd:mappings>    
</isd:service>

In this example, we have implemented the Serializer and the Deserializer in the same class. But in theory, we can separate them out to two different classes.

The client

In the client program as in the previous example we have to create an instance of our custom serializer/deserializer class PersonSerializer and pass the instance to the SOAPMappingRegistry.

//creating an instance of the Serializer class
PersonSerializer psr = new PersonSerializer();
//passing it to the SOAPMappingRegistry
            smr.mapTypes(Constants.NS_URI_SOAP_ENC, 
	returnqn, sam.soap.client.Name.class, psr, psr);

The rest of the code remains the same and if you deploy the service with the changed deployment descriptor and run the client, you will get the desired result.

Concluding remarks

In this three series tutorial, I have covered the basics of SOAP, a very simple SOAP application, a Java bean based example with the built in Serializer and Deserializer and also shown how to write a Custom Serializer and Deserializer. Also I have tried to explain the concepts working behind the API. I dare not claim that it is a complete manual for writing SOAP based applications but it is a quick start tutorial targeted to give you an insight to writing SOAP based applications. The topics I have not considered in this series are sending attachments with SOAP, Messaging with SOAP and a few others. I wish to present them sometime in the near future. Till then, good-bye and happy soaping.

About | Sitemap | Contact