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"
id="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,
qn, 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.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|