XML and Web services: SOAP

In this tip, William Brogden explains how using the AXIS toolkit and the JWS approach will get you started with a simple SOAP Web service.

The Meaning of SOAP

Early experiments with XML-based messaging using XML-RPC encouraged the development of an extension called SOAP. In the initial submission to the W3C, SOAP was said to stand for Simple Object Access Protocol. Many people have pointed out that SOAP is not particularly simple and does not have to be accessing an object, but the acronym has stuck.

The SOAP specification, now at the 1.2 level, is maintained by the W3C XML Protocol Working Group. Version 1.2 of the basic specification seems to have been stable since 2003. At this point in the introduction to SOAP I always like to emphasize that although you are most likely to run into SOAP in the Web service context of HTTP transport, any method that can move an XML text message can use SOAP. In my 2001 book I tested moving SOAP messages with Java Message Service, e-mail and JavaSpaces.

For this article I am going to use SOAP in its simplest form with HTTP transport, but with as little of the other baggage that it has accumulated as possible. I am going to be using the open source Axis toolkit created by the Apache Software Foundation and currently housed at the Apache Web Services Project. This project is currently at version 1.3 and has a very active user community. The next Axis major revision has reached version 0.95, but the highly stable 1.3 is plenty for our purposes here.

There are several reasons I choose Axis over Sun's Java Web Services Developer Pack. Axis has a simpler installation compatible with Tomcat, it includes the TCPMON utility for examining SOAP messages, and finally it has the ultra-simple "drop in" JWS mechanism for turning Java classes into RPC style Web services.

The Example Class

As it happens, I have a Java class of potential Web service interest. This class was written years ago to help a legal service client cope with alternate spellings of client names found in dictation records by using a phonetic code. The encoding algorithm I used is called "Metaphone" and was devised by Lawrence Philips.

The phonetic encoding uses rules of spoken English to reduce a word to a code. An example set of words that all have the same phonetic code is "sight", "site" and "cite." This lookup class takes two Strings as input, a word and a "hint" as to the presumed use of the word. It returns a String array of words it knows that produce the same phonetic code. The Java interface for this method is:

public String[] lookup( String word, String hint );

The AXIS Toolkit and the JWS Mechanism

Installing the Axis 1.3 toolkit is very simple, the 11.3MB download unzips to about 52MB of files - mostly various samples and documentation. To get it running in a Tomcat 1.4 or 1.5 servlet container installation you just copy the single "axis" directory into the webapps path. On restarting, Tomcat should find the "axis" Web application and you should be able to send your browser to the "http://localhost/axis/" welcome page. Before doing anything else, click the "validation" link – it runs the "happyaxis.jsp" which checks for all of the components needed to run the samples.

The JWS Web service mechanism simply requires a Java class that is not in a package and has one or more public methods. You give the source code file a .jws file type and place it under the Axis directory anywhere an HTML or JSP page would normally reside. In other words, not under WEB-INF subdirectory. Any classes the JWS file refers to must be accessible under normal servlet rules.

Here is the example I used, it has one public "lookup" method which simply creates an instance of the original phonetic implementation class and calls it.

public class SimplePhoneticLookup {

 static com.wbrogden.phonetic.PhoneticLookupImpl pL ;
  
  public String[] lookup( String word, String hint ){
    if( pL == null ){
      pL = new com.wbrogden.phonetic.PhoneticLookupImpl();
    }
    return pL.lookup( word, hint );  
  }
}

Its as simple as that! With the classes used by PhoneticLookupImpl in the WEB-INF/classes directory of the Axis service we are ready to try it. Any SOAP request addressing "axis/SimplePhoneticLookup.jws" will cause AXIS to compile the class, load it, discover the public method(s), extract the parameters, call the method, encode the method return values and send the SOAP response.

A SOAP Client Application

Now we can write a client application using the Service class the Axis toolkit provides. Here is the essential part of the code, where the word variable contains "sight" and the hint variable contains "Common," indicating that the lookup should use a collection of 59,956 common words previously turned into a serialized Java object and residing on the server.

String endpoint = "http://localhost/axis/SimplePhoneticLookup.jws";
try {
  Service  service = new Service();
  Call     call    = (Call) service.createCall();
  call.setTargetEndpointAddress( new java.net.URL(endpoint) );
  call.setOperationName( "lookup" ); 
  call.addParameter( "op1", XMLType.XSD_STRING, ParameterMode.IN );
  call.addParameter( "op2", XMLType.XSD_STRING, ParameterMode.IN );
  call.setReturnType( XMLType.XSD_ANYTYPE );

  Object ret =  call.invoke( new Object [] { word, hint });       
  System.out.println("Got result : " + ret);
  if( ret instanceof String[] ){
    String[] sret = (String[])ret ;
    for( int i = 0 ; i < sret.length ;i++ ){
      System.out.println( sret[i] );
    }
  }
} catch(Exception e ){ // report exception here

When executed, the client displays a list of words that all have the same phonetic code representation, including, among many others, "cite," "site" and "sight."

Using TCPMON to See What Really Happened

Web service applications are harder to debug than desktop applications because there are so many places something can go wrong. For example, if you get a SOAP fault message how can you be sure that the client SOAP request was formatted correctly in the first place?

The Axis toolkit provides the TCPMON tool that can capture the entire exchange of SOAP request and response for your further analysis. TCPMON acts as a proxy between your client and any Web service by listening to your client on a designated port and relaying data to the Web service. Captured messages, including the all-important HTTP headers, are displayed on a graphic interface.

The SOAP request

Here is what TCPMON captured from the client code – I have formatted the text for readability because the entire SOAP request is sent without any line breaks.

POST /axis/SimplePhoneticLookup.jws HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.3
Host: localhost:9000
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 421
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <lookup soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <op1 xsi:type="xsd:string">sight <op2 xsi:type="xsd:string">Common </soapenv:Body> </soapenv:Envelope>

A cool debugging feature of TCPMON lets you edit the request and send it again from the TCPMON interface so you can experiment with SOAP requests very easily.

The SOAP response

Here is what the JWS server sent back as captured by TCPMON. I have reformatted it for clarity and deleted all but a few of the individual match strings – a surprising number of common words have the same phonetic code as "sight."

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=D0A0D9173E5456033706B02216A37E84; Path=/axis
Content-Type: text/xml;charset=utf-8
Date: Mon, 27 Mar 2006 15:14:03 GMT
Connection: close
<?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <lookupResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <lookupReturn soapenc:arrayType="xsd:string[63]" xsi:type="soapenc:Array" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <lookupReturn xsi:type="xsd:string">cite <lookupReturn xsi:type="xsd:string">city ... many elements deleted <lookupReturn xsi:type="xsd:string">side <lookupReturn xsi:type="xsd:string">sight <lookupReturn xsi:type="xsd:string">sit <lookupReturn xsi:type="xsd:string">site ... many more elements deleted </lookupResponse> </soapenv:Body> </soapenv:Envelope>

I am sure you will all be struck by how very, very wordy a SOAP request and response are, particularly compared with XML-RPC. Concern over the bulk and resulting slow processing of SOAP messages has led to the development of "Fast Infoset" – a story for another time.

Conclusion

If you want to experiment with the possibilities of a simple SOAP Web service you don't have to wade through the complexities of WSDL, schema, JAXB or other acronyms. Using the AXIS toolkit and the JWS approach will get you started and you can figure out a more formal approach later.

Resources

Dave Winer's History of SOAP (1999)

Don Box's History of SOAP (2001)

Initial W3C SOAP Submission

Apache Web Service Project - AXIS toolkit

Source for the Metaphone phonetic code algorithm


This was first published in March 2006

Dig deeper on Simple Object Access Protocol (SOAP)

Pro+

Features

Enjoy the benefits of Pro+ membership, learn more and join.

0 comments

Oldest 

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

-ADS BY GOOGLE

SearchSoftwareQuality

SearchCloudApplications

SearchAWS

TheServerSide

SearchWinDevelopment

Close