15.3 SOAP

The Simple Object Access Protocol (SOAP) is a more complex RPC mechanism than XML-RPC, but both share a common basis (an underlying protocol based on XML and HTTP) and conceptual model. SOAP adds many features to RPC, including explicit support for asynchronous message delivery via the Simple Mail Transport Protocol (SMTP), the basis for delivery of Internet email.

The use of SOAP versus XML-RPC depends largely on the eventual target use of your application and who or what you're communicating with. Generally, the simplicity of XML-RPC has led to widespread adoption, whereas the overall sophistication and capabilities of SOAP have led to broader adoption in the enterprise (not to mention the explicit endorsement of SOAP by entities such as Microsoft and IBM).

This chapter looks at Apache Axis 1.0, an open source implementation of the SOAP 1.1 specification providing both server and client capabilities.

15.3.1 Obtaining Axis

You can download Apache Axis 1.0 from http://xml.apache.org/axis/. The download used here is Release 1.0 from http://xml.apache.org/axis/releases.html.

15.3.2 Installation

The rest of this chapter assumes that you are working with JBoss, installed as described in Chapter 14.

The process of installing Axis under Tomcat is similar to installation under JBoss. For complete instructions, refer to http://cvs.apache.org/viewcvs.cgi/~checkout~/xml-axis/java/docs/install.html.

SOAP requires a servlet (or, sometimes, several servlets) to receive requests, and then respond to those requests, via HTTP. Using a servlet lets you avoid dealing with network sockets manually, which is always a hassle.

Axis comes prepackaged with a WAR directory, ready to install in a web container or application server.

If you decide to install Axis manually or on another system later, the core libraries are in the following JAR files:

  • axis-1_0/lib/axis.jar

  • axis-1_0/lib/jaxrpc.jar

  • axis-1_0/lib/saaj.jar

  • axis-1_0/lib/commons-logging.jar

  • axis-1_0/lib/commons-dicovery.jar

  • axis-1_0/lib/wsdl4j.jar

While you can set up Axis to expose any Java class as a web service, one of its best features is its ability to expose Java Web Service files with little (or no) developer intervention. What is JWS?

A Java Web Service (JWS) file is an ordinary Java source file with a different extension (.jws), placed in a specific directory exposed as part of a web application. When a request is made for a JWS file, Axis compiles the file as if it were a Java file, adding additional wrappers to make the objects and methods within available to the remote caller. In this way, it operates much like a JSP file, but instead of providing HTML documents to web browsers, JWS files provide web services.

One of JWS's key advantages is that it is a much easier development model than a traditional edit/compile cycle, like JSPs or servlets. Instead of packaging your files as a WAR file and then deploying them, you can work directly on the files in a deployment directory, with Axis handling compilation (and recompilation) as requests come in from clients, all due to the .jws extension. Copying the files

To facilitate using JWS files, install Axis in JBoss not as a sealed WAR, but as a directory that you can deploy directly, as shown below:

[Luthien:~/Public/xml-axis-10] wiverson% ls
README              lib                 samples             xmls
docs                release-notes.html  webapps

[Luthien:~/Public/xml-axis-10] wiverson% cd webapps/axis/

[Luthien:xml-axis-10/webapps/axis] wiverson% mkdir /usr/local/jboss/server/

[Luthien:xml-axis-10/webapps/axis] wiverson% cp -r * /usr/local/jboss/

To support the dynamic compilation of JWS files with JBoss, add the servlet library to the Axis web application's WEB-INF/lib directory:

[Luthien:xml-axis-10/webapps/axis] wiverson% cd /usr/local/jboss/server/

[Luthien:server/default/lib] wiverson% cp javax.servlet.jar ../deploy/axis.

If JBoss isn't already running, start it now. You can verify that Axis is properly installed by viewing the default Axis management page at http://localhost:8080/axis/. If everything is working properly, you'll see the configuration page shown in Figure 15-7.

Figure 15-7. Axis configuration

15.3.3 SOAP Basics

SOAP is a direct descendent of XML-RPC, proposed by some of the same vendors that originally worked on XML-RPC. It's been positioned as the enterprise version of web services, adding functionality such as support for more complex objects, namespaces, and envelopes. It is also associated with related technologies such as the Web Services Description Language (WSDL). This topic is beyond the scope of this text, however. If you're interested in these advanced features of SOAP, consult O'Reilly's Java Web Services, by David Chappell and Tyler Jewell.

For your purposes here, SOAP is just another RPC mechanism, similar to XML-RPC. There are significant differences in the protocols used to communicate between systems and the implementation libraries, but the conceptual model is the same as the one shown in Figure 15-2.

Server application development is most easily handled via JWS files, described above. Client development is similar to that of XML-RPC, with a slightly different set of classes. An org.apache.axis.client.Service object binds to a specific remote server, and an org.apache.axis.client.Call object executes a remote method. This section creates a .jws file for your server and uses these client APIs to retrieve the methods' results.

15.3.4 Building a SOAP Web Service

The web service you'll build for Axis is much like the one you built for XML-RPC. Add a file called SimpleWebService.jws to the /usr/local/jboss/server/default/deploy/axis.war directory with the contents shown in Example 15-6.

Example 15-6. A simple web service
public class SimpleWebService

    public SimpleWebService(  )
    public int add(int a, int b)
        return a + b;
    public String now(  )
        return new java.util.Date().toString(  );
    public String slownow(  )
            } catch (java.lang.InterruptedException e)
        return new java.util.Date().toString(  );

You'll notice that the JWS appears to be an ordinary Java class. Axis offers other mechanisms for handling SOAP requests that provide more control, but for many services, the JWS mechanism is more than adequate.

15.3.5 Accessing a SOAP Web Service from Java

The easiest way to talk to the web service is directly from your browser's address bar. As shown in Figure 15-8, you can simply request a web service via an HTML request, like http://localhost:8080/axis/SimpleWebService.jws?method=now.

Figure 15-8. The "now" function via an HTTP GET request

You can also send parameters via the request parameters of a URL, such as http://localhost:8080/axis/SimpleWebService.jws?method=add&a=1&b=2. In this example, the parameter names provided on the URL (a and b) aren't significant. However, for more complex web services they are important, as they associate values with specific parameters in code. Figure 15-9 shows the results of this request.

Figure 15-9. The "add" functionality via an HTTP GET request

Example 15-7 shows how to access SOAP via Java. SOAP is more complex than XML-RPC, and therefore requires a bit more setup and configuration. It also affords a great deal more sophistication, however, and if your application requires very specific details about the methods invoked and how they are interacted with, it can be well worth the extra work.

Example 15-7. Accessing SOAP services
package com.wiverson.macosbook.webservices;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
import com.wiverson.macosbook.SimpleEdit;

public class SOAPClientPlugin implements 
    public SOAPClientPlugin(  )
    public void doAction(SimpleEdit frame, java.awt.event.ActionEvent evt)
        frame.appendDocumentText(this.remoteCall(  ));
    public String getAction(  )
        return "SOAP Client";
    public void init(SimpleEdit frame)
    public static void main(String[] args)
        System.out.println(new SOAPClientPlugin().remoteCall(  ));
    public String remoteCall(  )
            String webserviceLocation =
            Service service = new Service(  );
            Call call    = (Call) service.createCall(  );
            call.setTargetEndpointAddress(new java.net.URL(webserviceLocation));
            return (String) call.invoke("now", null);
        } catch (Exception e)
            System.err.println(e.toString(  ));
        return "Unable to connect.";

15.3.6 Accessing a SOAP Web Service from AppleScript

SOAP might be more complex than XML-RPC, but a SOAP client is built into AppleScript as well, as shown in Figure 15-10.

Figure 15-10. Scripting a SOAP client

Example 15-8 shows a client similar to the one you built earlier to access the XML-RPC service. However, more detail is required (in particular, extra parameter information) for SOAP interaction. It may seem a bit odd that the AppleScript client enforces this extra detail (when the browser's HTTP GET was able to invoke the service without it), but that's the nature of SOAP?it's an evolving set of standards.

Example 15-8. Scripting a SOAP client
script SoapServer
    on now(  )
        tell application "http://localhost:8080/axis/SimpleWebService.jws"
            return call soap {method name:"now"}
        end tell
    end now
    on add(s1, s2)
        tell application "http://localhost:8080/axis/SimpleWebService.jws"
            return call soap {method name:"add", parameters:{a:s1 as integer, b:s2 as integer}}
        end tell
    end add
end script

display dialog SoapServer's now(  )
display dialog SoapServer's add(1, 2)