perfectxml.com
 Basic Search  Advanced Search   
Topics Resources Free Library Software XML News About Us
  You are here: home Info Bank Articles » Features of Apache SOAP 2.2 Saturday, 14 July 2007
 

Back to Articles Page      

        

TechMetrix Features of Apache SOAP 2.2
 Reproduced with kind permission of TechMetrix Research External link
 Article written by: BERTRAND GOUPIL, - Analyst (bgoupil@techmetrix.net  E-mail )

SOAP 1.1

Definition of SOAP

SOAP (Simple Object Access Protocol) is a simple, lightweight protocol for structured and strong-type information exchange in a decentralized, distributed environment. The protocol is based on XML (eXtensible Markup Language) and consists of three parts:

1. An envelope which describes the contents of the message and how to use it
2. A set of rules for serializing data exchanged between applications
3. A procedure to represent remote procedure calls, that is, the way in which queries and the resulting responses to the procedure are represented.

Similar to object distribution models (IIOP, DCOM...), SOAP can call methods, services, components and objects on remote servers. However, unlike these protocols, which use binary formats for the calls, SOAP uses text format (Unicode), with the help of XML to structure the nature of the exchanges.

SOAP can generally operate with numerous protocols (FTP, SMTP, POP...), but it is particularly well suited to the HTTP protocol. It defines a reduced set of parameters which are specified in the HTTP header, making it easier to pass through proxies and firewalls.

Using XML in SOAP

SOAP messages are structured using XML. Within the framework of the remote procedure call (RPC), it represents the parameters of the methods, the return values and any potential error messages linked to the processes.

Coding SOAP messages in XML enables universal communication between applications, services and platforms via the Internet. In order to do this, SOAP makes use of the descriptive nature of the XML language, thus transforming the content into an application.

In more technical terms, just as with an XML fragment, SOAP messages make references to different namespaces, enabling the content to be validated. They must therefore include a call to SOAP namespaces, making it possible to define and specify the use of standard tags in the message and to ensure compatibility between SOAP versions. As soon as a SOAP message is received, the SOAP tags are validated, as are the tags that express the subject of the message. If it fails, an error is generated.

Soap thus defines two namespaces:

  • http://schemas.xmlsoap.org/soap/envelope/ for the envelope
  • http://schemas.xmlsoap.org/soap/encoding/ for the coding

SOAP and HTTP

Deploying SOAP over HTTP makes it possible to use the SOAP decentralization method in the well-used environment of HTTP. Using SOAP over HTTP also enables resources already present on the Web to be unified by using the natural request/response mode of HTTP. The only constraint is that a SOAP message via HTTP must use the MIME type "text/xml".

Apache Soap

Presentation

Apache Soap is an Apache project which defines the SOAP protocol in Java. This project is based on the source of IBM's SOAP application, SOAP 4J. The latest version of this implementation, dated May 30, 2001, is version 2.2 of the project.

Apache SOAP 2.2 defines almost all of the SOAP1.1 note, in the same way as the whole "SOAP Messages with Attachments" Note from the W3C.

The project essentially consists of four parts:

  • The definition of an API for developing SOAP services
  • A server-side infrastructure for deploying and running SOAP services.
  • Support for three forms of encoding: SOAP 1.1, XML, XMI.
  • Use of HTTP, SMTP protocols.

The characteristics of Apache SOAP are very important for interoperability between systems.

Apache SOAP limitations

Apache SOAP 2.2 does not support certain recommendations in the Note, such as the definition of processing rules by specifying several attributes in the elements of the SOAP envelope. These attributes are the following:

  • The mustUnderstand attribute
  • The actorintermediaries attribute
  • The root attribute

These are semantically enriching attributes which make more specific uses possible (see Soap 1.1 from w3c). Attention must be paid in particular to the choice of parser. The Xerces 1.3.x parser is not supported by Apache SOAP.

Setting up a Java Web server

The development of a SOAP service in Java uses the API defined by Apache SOAP for sending and processing messages. To deploy a Web service from Apache, we use the deployment infrastructure supplied.

In order to demonstrate how to use Apache SOAP, we deployed a calculating service with three methods:

  • add
  • sub
  • mul

These methods will be called by a Java SOAP client, executed on the remote server that will send the response back to the enquirer.

Test architecture

Setting up a SOAP architecture solely using HTTP will require at least:

  • JDK 1.2.x or greater
  • An Apache SOAP implementation
  • A servlet engine (Websphere, Weblogic, Tomcat ...)
  • A parser supporting XMLSchema

In our analysis, we set up an architecture using the following components:

It should be noted that the installation documents for the SOAP service recommend using the JavaMail API and JAF (Java Activation Framework).

You can consult the installation documents at: http://xml.apache. org/soap/docs/index.html

Deployment of a Server application

Developing a server application remains a traditional Java development. For our calculator, we have developed a Calculator class whose methods will be called by a SOAP envelope.

package webservice;
class Calculator
{
public long add (long nbr1, long nbr2)
{
long result;
result = nbr1 + nbr2;
return result;
}
public long sub (long nbr1, long nbr2)
{...}
public long mul (long nbr1, long nbr2)
{...}
}

The architecture of Apache SOAP provides us with the means to identify our service. We have two solutions to this. The first involves describing the Java class by the SOAP Web Interface at the following URL:

http://localhost:8080/soap/admin/deploy.js

Deployment Interface

The second is to invoke an XML file describing the service with a command line:

java org.apache.soap.server.ServiceManagerClient
http://localhost:8080/soap/servlet/rpcrouter deploy mon_fic.xml

This XML file is called the "deployment descriptor". The deployment descriptor supplies data to servers regarding the Web service: Which types are defined? What are the functions or the methods that one can call on it? How to process the responses sent by the server? All this information is described by an XML file.

In our example, we can define the calcul.xml file describing the service of our Calculator class:

<?xml version="1.0" encoding="ISO-8859-1"?>
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:Calculator">
<isd:provider type="java" scope="Application" methods="add sub mul">
<isd:java class="webservice.Calculator" static="false"/>
</isd:provider>
</isd:service>

Identifying features:

  • name of the service: urn:Calculator
  • language: Java
  • name of the methods: add, sub, mul
  • name of the service application: webservice.Calculator

The Calculator class sends back a Long type - a simple type in the XMLSchema definition. Simple types are processed by default by Apache SOAP (see Appendix), and do not require a particular definition. On the other hand, if a service sends back an object as a response, the object must be described in order to define its XML/JAVA mapping. An object is defined in a SOAP envelope as an XML hierarchy. Each element or object type must be defined for the serialization and deserialization of the response (see Sending a complex request).

Let us take the example of a directory service. We can consult this directory by requesting an address from a name. An address is represented in Java as an object. Without returning to the object model, an address is then made up of a street number, street name, town, etc.

In order to describe these objects, mappings must be defined in the deployment descriptor, as follows, for each object:

<isd:mappings>
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="urn:xml-soap-address-demo" qname="x:address"
javaType="samples.addressbook.Address"
java2XMLClassName="org.apache.soap.encoding.soapenc.
BeanSerializerer"
xml2JavaClassName="org.apache.soap.encoding.soapenc.
BeanSerializer"/>
...
</isd:mapping>

With this mapping, the server indicates to Java clients where to find the methods to understand the server response, with the attributes Java2XMLClassName and xml2JavaClassName. We will enter into this in more detail in the section entitled Sending a complex request.

Client

The Apache SOAP API supplies the methods for creating a SOAP client in Java. In order to call a Soap service, the client application must know the definition of the service. For this, we need the following information :

  • service URL
  • service identifier
  • coding to use
  • names of the service methods
  • types of parameters to send and to process

All this information will be included in the SOAP envelope when the request is made.

Development of a simple service

The client consulting the calculator service must import the Apache Soap implementation classes. When developing a service for processing simple types, the following classes must be imported, at least:

import org.apache.soap.rpc.Call;
import org.apache.soap.rpc.Parameter;
import org.apache.soap.rpc.Response;
import org.apache.soap.Fault;
import org.apache.soap.Constants;
import org.apache.soap.SOAPException;

Construction and sending of SOAP messages

The construction of the SOAP message uses the methods in the Call class. This class defines the set of characteristics which make up an RPC. Amongst these methods, we can note two phases involved in the call.

The service identification phase represented by:

  • setTargetURI(String identifiant_du_service)
  • setMethodName(String nom_des_methodes_du_service)
  • setEncodingStyleURI(String uri_encodage)

The construction and request sending phase:

  • setParams(Vector mes_parametres)
  • invoke(URL http://mon.web.service..., String soapActionField)

The method setParams is used to define the variables which will be sent to the server. This definition uses the Parameter class which instantiates an object taking as its arguments:

  • name
  • type
  • value
  • coding (empty by default)

The invoke method triggers the mechanism to send the SOAP request to the relevant service. This service is identified by a URL. The URL of our service will be the local server on which the Web service is deployed:

http://localhost:8080/soap/servlet/rpcrouter/.

Thus, for our calculator example, we will have the following code:

Long nbr1 = Long.valueOf(args[0]);
Long nbr2 = Long.valueOf(args[2]);
URL url = new URL("http://localhost:8080/soap/servlet/rpcrouter");
Call call = new Call();
//Name of service
call.setTargetObjectURI("urn:Calculator");
if (args[1].equals("+")){
// Name of service method
call.setMethodName("add");
}
...
// Coding
call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
Vector params = new Vector();
// Declaration of parameters
params.addElement(new Parameter("nbr1", Long.class, nbr1, null));
params.addElement(new Parameter("nbr2", Long.class, nbr2, null));
call.setParams(params);
Response resp = null;
try{
// SOAP request send
resp = call.invoke(url, soapActionField);
}
...
//processes

Processing the SOAP response

The envelope returned by the server is processed by the Response object. The object contains the SOAP XML stream, and therefore all the characteristics of the response. The stream is processed by the Parameter class methods. By default, the Parameter object processes all the simple data types (Integer, Long, String,...). The calculator service sends back a Long type, and therefore has no special coding.

//construction of SOAP message
...
Response resp = null;
try{
resp = call.invoke(url, soapActionField);
}
catch( SOAPException e ){
System.err.println("Caught SOAPException (" + e.getFaultCode() + "): " + e.getMessage());
System.exit(-1);
}
// Response retrieval.
if( !resp.generatedFault() ){
Parameter ret = resp.getReturnValue();
Object value = ret.getValue();
System.out.println(value);
}
else{
Fault fault = resp.getFault();
System.err.println("Generated fault: ");
System.out.println (" Fault Code = " + fault.getFaultCode());
System.out.println (" Fault String = " + fault.getFaultString());
}

Executing the program

Executing the client program sends the HTTP-SOAP stream to the server indicated by the program. We have asked the server to calculate an addition for us:

java webservice.CalculatorClient 6 + 5

The stream is made up of an HTTP Header, followed by a SOAP envelope.

HTTP Header:

POST /soap/servlet/rpcrouter HTTP/1.0
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: 463
SOAPAction: ""

SOAP envelope:


<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd= "http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:add xmlns:ns1="urn:Calculator" SOAP-ENV:encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/">
<nbr1 xsi:type="xsd:long">6</nbr1>
<nbr2 xsi:type="xsd:long">5</nbr2>
</ns1:add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The server receives the SOAP request and sends back the results of this addition:

HTTP Header

HTTP/1.0 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 451
Set-Cookie2: JSESSIONID=8qilh88em1;Version=1;Discard;Path="/soap"
Set-Cookie: JSESSIONID=8qilh88em1;Path=/soap
Servlet-Engine: Tomcat Web Server/3.2.2 (JSP 1.1; Servlet 2.2; Java 1.3.0; Windows 2000 5.0 x86; java.vendor=Sun Microsystems Inc.)

SOAP envelope

<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd= "http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:addResponse xmlns:ns1="urn:Calculator" SOAP- ENV:encodingStyle="http://schemas.xmlsoap.org/soap/ encoding/">
<return xsi:type="xsd:long">11</return>
</ns1:addResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Execution of the calculator service

Sending a complex request

As we have seen, Apache SOAP processes all simple types (see Appendix) 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 in order to define these objects easily.

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

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

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

Send:

<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:SOAP- ENV="http://schemas.xmlsoap.org/soap/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/">
<nameToLookup xsi:type="xsd:string">Bertrand Goupil</nameToLookup>
</ns1:getAddressFromName>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Click here for a larger image

Execution of the directory service (Click here for a larger image)

The Java client does not understand the response and throws an exception. This exception clearly indicates to us that the program has not found a method to deserialize the response, which is of the type urn:xml-soap_address-demo:address. In fact, the server sent 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:type="xsd:int">33</areaCode>
<number xsi:type="xsd:string">155932600</number>
</phoneNumber>
<zip xsi:type="xsd:int">93200</zip>
<streetNum xsi:type="xsd:int">268</streetNum>
<state xsi:type="xsd:string">France</state>
<streetName xsi:type="xsd:string">ave du président Wilson</streetName>
<city xsi:type="xsd:string">Saint Denis</city>
</return>

The XML response indicates to us that there are two unknown types belonging to the namespace ns2.

  • xsi:type="ns2:address"
  • xsi:type="ns2:phone"

Each response type sent by SOAP must be serialized and deserialized between 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.

In order 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 setStreetName(String streetName){
this.streetName = streetName;
}
public String getStreetName(){
return streetName;
}
...

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

In our example, we have a complex type comprising two objects: Address and 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_SOAP_ENC,
new QName("urn:xml-soap-address-demo", "phone"),
PhoneNumber.class, beanSer, beanSer);
Call call = new Call();
call.setSOAPMappingRegistry(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.class need to be present on the client side for the application to function well. If we develop an application calling a service which has never been contacted, it is essential to know the structure of the message in order to define the mapping.

Even so, it is very difficult 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 the mapping, as you can process the XML tags as a character string. However, when programming the mapping, all elements of the SOAP response (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 (Constants.NS_URI_SOAP_ENC, new QName ("", "state"), null,
null, sd);
...

Serialization of the response

GUI Interface

In order to debug SOAP applications, Apache provides an interface which displays SOAP message sends. In the case of our directory, this tool is very useful for finding out the structure of the response message. This interface, called the GUI Interface, is a TCP tunnel which redirects the HTTP data flow from a listening port, by way of tunneling, to the port of the machine being queried. The interface is launched with this command:

java org.apache.soap.util.net.TcpTunnelGui port_ecoute nom_serveur port

Click here for a larger image

GUI Interface (Click here for a larger image)

For our calculator service, deployed on a local server (localhost:8080), the definition of the URL in the SOAP program will link to the listening port of the GUI interface.

URL url = new URL("http://localhost:8000/soap/servlet/rpcrouter");

The launch command for the GUI tunnel will lead to the service address:

java org.apache.soap.util.net.TcpTunnelGui 8000 localhost 8080

The only limitation of the GUI is that it does not function with addresses containing sub-domains.

Performances

CORBA, DCOM and RMI use binary coding for message exchanges. This process requires both parties to know the exchange language. This mode of transmission is very effective, but makes it difficult to tweak the application that processes the messages, and while each system uses its own binary mode, these systems do not interoperate easily.

Given that SOAP uses XML coding, it is easier to process the messages at each stage of invocation, which requires a significant degree of flexibility in the development of the SOAP application.

Clearly, reading and interpreting XML messages is intrinsically slower than processing binary messages, because of the coding-decoding time for SOAP messages.

Nonetheless it is possible, in a closed environment such as an intranet, to optimize the processing of SOAP messages using the same client-server implementation. For example, a SOAP client could easily add an additional tag to the HTTP header to indicate that it supports a particular optimization. If the server also accepts it, this optimization could be set up for subsequent transmissions.

The Apache SOAP architecture is fairly slow in comparison to other implementations. Indeed, communication between two Java applications on the same one machine works at around thirty round-trips per second, while other implementations can work at up to 700 round-trips per second (see http://www.extreme.indiana.edu/soap
/sc00/paper/node13 .html#observations
).

Future Implementation Development

The Apache SOAP project will remain at version 2.2, as Apache's future Web services implementation project is called "Axis". This project will support the whole of the SOAP 1.1 note, but will be much more comprehensive than the Apache SOAP project.

As well as being a more reliable and effective implementation, Axis implements a greater number of protocols (HTTP, HTTPs, SMTP, POP3, JMS, etc). Security aspects are strengthened, and the implementation provides support for the description and discovery of Web services by using WSDL. It is worth noting that there are no releases yet for these products; those who cannot wait can only download the "nightly" version on CVS .

Conclusion

Apache SOAP is a comprehensive implementation of SOAP. Nonetheless it moves away from the rules for referencing services by using its own description language (deployment descriptor). As regards interoperability, problems are recurrent, regardless of the implementation. This is caused by the lack of compliance with standards, both in terms of transport protocols and XML parsing. Another important issue is the status of the SOAP standard itself. It is in note status, therefore will move up to a recommendation. Evidently, as long as a standard is not definitive, some small interoperability problems will persist.

Appendix

XMLSchema types supported by Apache Soap 2.2:
                 XMLSchema 1999
XMLSchema 2000
XMLSchema 2001
string
Yes
Yes
Yes
int
Yes
Yes
Yes
decimal
Yes
Yes
Yes
float
Yes
Yes
Yes
double
Yes
Yes
Yes
date
Yes
Yes
Yes
boolean
Yes
Yes
Yes
long
Yes
Yes
Yes
short
Yes
Yes
Yes
QName
Yes
Yes
Yes
timeInstant
Yes
Yes
Yes
any Type
No
Yes
Yes
ur-type
Yes
No
No


TechMetrix
 Reproduced with kind permission of TechMetrix Research External link
 Article written by: BERTRAND GOUPIL, - Analyst (bgoupil@techmetrix.net  E-mail )

  

Back to Articles Page      

  Contact Us | E-mail Us | Site Guide | About PerfectXML | Advertise ©2004 perfectxml.com. All rights reserved. | Privacy