Sending a Complex Request

Page 13
By ServerWatch Staff (Send Email)
Posted Mar 8, 2002


As we have seen, Apache SOAP processes all simple types by default. In the case of a response or an object send, this must be defined so as to be understandable by both parties. For this task, the Apache SOAP implementation gives us some classes to define t hese objects easily.

Let''s take the example of a Web service that supplies a directory. The request must, from a name sent t o the server, find its characteristics -- the address, telephone number, town, and so on. The queried service will send back a much more complex response than the calculator service.

According to the description of the service, the server sends back a compl ex object in the form of an XML hierarchy. The main difficulty is knowing how to process the response issued by the server when it d oes not send back a known type.

If we use the same development as before, the SOAP stream will be correctly formulated on ei ther side, but the response will not be understood in Java, since it will have no instructions as to how to process the received str eam.

 <?xml version=''1.0'' encoding=''UTF-8''?> <SOAP-ENV:Envelope xmlns:SOAP- ENV="http://schemas.xmlsoap.org/soa
p/ envelope/"xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body
> <ns1:getAddressFromName xmlns:ns1="urn:AddressFetcher" SOAP- ENV:encodingStyle="http://schemas.xmlsoap.org/ soap/encoding/"&g
t; <nameToLookup xsi:type="xsd:string">Bertrand Goupil</nameToLookup> </ns1:getAddressFromName> </SOAP-ENV:Body>
 </SOAP-ENV:Envelope> 

The Java client does not understand the response and throws an exception. This exception clearl y indicates to us that the program has not found a method to deserialize the response, which is of the type urn:xml-soap_address-dem o:address. In fact, the server sends back the following response:

 <return xmlns:ns2="urn:xml-soap-address-demo" xsi:type
="ns2:address"> <phoneNumber xsi:type="ns2:phone"> <exchange xsi:type="xsd:string">0</exchange> <areaCode xsi:ty
pe="xsd:int">33</areaCode> <number xsi:type="xsd:string">155932600</number> </phoneNumber> <zip xsi:type="x
sd:int">93200</zip> <streetNum xsi:type="xsd:int">268</streetNum> <state xsi:type="xsd:string">France</stat
e> <streetName xsi:type="xsd:string">ave du prisident Wilson</streetName> <city xsi:type="xsd:string">Saint Denis&
lt/city> </return> 

The XML response indicates to us that there are two unknown types belonging to the namespace ns 2: xsi:type="ns2:address" and "xsi:type="ns2:phone"

Each response type sent by SOAP must be serialized and deserialized betwe en the client and the server. If these types do not belong to any known definition, we must then indicate which deserializer we have to use.

To define a complex type, we use the BeanSerializer class to deserialize the server response. Each object received or sent must be programmed as a JavaBean (set and get methods), with XML elements of the return message as parameters.

In the example below, and according to the previous SOAP message, streetNum is an int type, and streetName is a String type.

...
public void setStreetNum(int streetNum){ this.streetNum = streetNum; } public int getStreetNum(){ return streetNum; } public void se
tStreetName(String streetName){ this.streetName = streetName; } public String getStreetName(){ return streetName; } ... 

Th e definition of a new type must be included in Apache SOAP''s serialization/deserialization mechanism. To do this, we must use the S OAPMappingRegistry class. In this way, the object will contain all the information to process new types. This class enables us to de fine SOAP/JAVA mapping through the mapTypes method.

In our example, we have a complex type comprising two objects: Address an d PhoneNumber.

 import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.BeanSerializer
; ... SOAPMappingRegistry smr = new SOAPMappingRegistry(); BeanSerializer beanSer = new BeanSerializer(); smr.mapTypes(Constants.NS_
URI_SOAP_ENC, new QName("urn:xml-soap-address-demo", "address"), Address.class, beanSer, beanSer); smr.mapTypes(Constants.NS_URI_SOA
P_ENC, new QName("urn:xml-soap-address-demo", "phone"), PhoneNumber.class, beanSer, beanSer); Call call = new Call(); call.setSOAPMa
ppingRegistry(smr); ... 

The setSOAPMappingRegistry method will link the definition of new types and the processing of the response. Therefore it is vital that it is added.

It is important to note that the classes Address.class and PhoneNumber.cla ss must be present on the client side for the application to function well. If we develop an application calling a service that has never been contacted, it is essential to know the structure of the message to define the mapping.

Even so, it is very diffic ult to know the structure of a message. If by chance you do know the XML structure, you do not need to create a JavaBean to define t he mapping, as you can process the XML tags as a character string. However, when programming the mapping, all elements of the SOAP r esponse (except the envelope) on all levels will have to be mapped.

In our service:

 SOAPMappingRegistry smr = new
SOAPMappingRegistry (); StringDeserializer sd = new StringDeserializer (); ... smr.mapTypes (Constants.NS_URI_SOAP_ENC, new QName ("
", "street"), null, null, sd); smr.mapTypes (Constants.NS_URI_SOAP_ENC, new QName ("", "city"), null, null, sd); smr.mapTypes (Const
ants.NS_URI_SOAP_ENC, new QName ("", "state"), null, null, sd); ... 



Comment and Contribute

Your name/nickname

Your email

(Maximum characters: 1200). You have characters left.