Kalaimaan

Doing simple things to make great life

Archive for the ‘Soap Service’ Category

Creating Web Services in Java with Apache SOAP

Posted by kalaimaan on January 29, 2009

Creating Web Services in Java with Apache SOAP

Creating web services in Java is more work than in Perl with SOAP::Lite, but the process is essentially the same. To illustrate how it’s done, let’s create the same Hello World web service and deploy it using the Apache SOAP tools.

Apache SOAP is the Apache Software Foundation’s implementation of the SOAP protocol. It is designed to run as a servlet within any Java HTTP Server. As such, it implements only the proxy part of the message handling process. Like SOAP::Lite, Apache SOAP’s list of features is impressive, sharing many of the same benefits as its Perl-based counterpart.

Installing Apache SOAP

Apache SOAP can be used as both a client and provider of SOAP web services. A server-side installation of Apache SOAP involves placing some .jar files in your classpath. You will need a separate web server that supports Servlets and Java Server Pages, such as Apache’s Tomcat (http://jakarta.apache.org/tomcat/).

The Apache SOAP homepage, http://xml.apache.org/soap/index.html, has links to both source-only and precompiled distributions of the toolkit. Installing the precompiled binary distribution is as simple as downloading a Zip archive and extracting it into a directory.

On the client, three .jar files from the distribution (soap.jar, mail.jar, and activation.jar) must be present in your classpath. Also present must be any Java API for XML Parsing (JAXP) aware XML parser, such as Xerces Version 1.4 (http://xml.apache.org/xerces-j/).

Assuming that you installed Apache SOAP .jar files in the C:\book\soap directory, set your SOAP_LIB environment variable to C:\book\soap\lib. Adding the .jar files to your classpath then entails:

set CLASSPATH = %CLASSPATH%;%SOAP_LIB%\soap.jar
set CLASSPATH = %CLASSPATH%;%SOAP_LIB%\mail.jar
set CLASSPATH = %CLASSPATH%;%SOAP_LIB%\activation.jar

Or, in the Unix Bourne shell (/bin/sh):

CLASSPATH = $CLASSPATH;$SOAP_LIB/soap.jar
CLASSPATH = $CLASSPATH;$SOAP_LIB/mail.jar
CLASSPATH = $CLASSPATH;$SOAP_LIB/activation.jar

The exact steps for a server installation will depend on which web application server you are using, but the process is essentially the same. The first step is to ensure the same three .jar files are located in your application server’s classpath.

If your application server supports the use of web application archives (WAR files), simply use the soap.war file that ships with Apache SOAP. Apache Tomcat supports this. The Apache SOAP documentation includes detailed installation instructions for Tomcat and a number of other environments.

If you intend to use the Bean Scripting Framework (BSF) to make script-based web services, you need to ensure that bsf.jar and js.jar (a BSF JavaScript implementation) are also in the web application server’s classpath.

The vast majority of problems encountered by new Apache SOAP users are related to incorrect classpaths. If you encounter problems writing web services with Apache SOAP, be sure to start your debugging by checking your classpath!

The Hello Server

We’re going to do the same things we did in Perl: create the code, deploy the service, and use the service. Example 3-12 shows the Java code for the Hello class.

Example 3-12: Hello.java

package samples;
public class Hello {
   public String sayHello(String name) {
       return "Hello " + name;
   }
}

Compile the Java class and put it somewhere in your web server’s classpath.

Deployment Descriptor

Next we must create a deployment descriptor to tell the Apache SOAP implementation everything it needs to know to dispatch sayHello messages to the samples.Hello class. This is shown in Example 3-13.

Example 3-13: Deployment descriptor for samples.Hello

<dd:service xmlns:dd="http://xml.apache.org/xml-soap/deployment" 
    id="urn:Example1">
 <dd:provider type="java"
              scope="Application"
              methods="sayHello">
    <dd:java class="samples.Hello"
             static="false" />
 </dd:provider>  
 <dd:faultListener>
  org.apache.soap.server.DOMFaultListener
 </dd:faultListener>
 <dd:mappings />
</dd:service>

The information contained within a deployment descriptor is fairly basic. There is the class name of the Java code being invoked (<dd:java class="samples.Hello" static="false" />), and an indication of the session scope of the service class (application or session scope, as defined by the Java Servlet specification), an indication of which faultListener to use (used to declare how faults are handled by the SOAP engine), and a listing of Java-to-XML type mappings. We will demonstrate later how the type mappings are defined.

Apache SOAP supports the use of pluggable providers that allow web services to be implemented not only as Java classes, but as Enterprise Java Beans, COM Classes, and Bean Scripting Framework scripts. Full information about how to use pluggable providers is available in the documentation and not covered here.

While simple in structure, deployment descriptor files must be created for every web service that you want to deploy. Thankfully, there are tools available that automate that process, but they still require the developer to walk through some type of wizard to select the Java class, the methods, and the type mappings. (A type mapping is an explicit link between a type of XML data and a Java class, and the Java classes that are used to serialize or deserialize between those types.)

Once the file is created, you have to deploy it with the Apache SOAP service manager. There are two ways to do this: you can use the Service Manager Client or, if you’re using the XML-based Service Manager that ships with Apache SOAP, modify the deployment registry directly.

The first method requires executing the following command:

% java org.apache.soap.server.ServiceManagerClient http://hostname:port/soap/servlet/rpcrouter deploy foo.xml

Where hostname:port is the hostname and port that your web service is listening on.

One interesting fact you should notice here is that the Apache Service Manager is itself a web service, and that deployment of a new service takes place by sending a SOAP message to the server that includes the deployment descriptor. While this is handy, it’s not necessarily all that secure (considering the fact that it would allow anybody to deploy and undeploy services on your web server). To disable this, set the SOAPInterfaceEnabled option in the soap.xml configuration file to false. This will prevent the ServiceManagerClient from working.

The second approach will only work if you’re using the XML Configuration Manager. This component allows you to store deployment information in an XML file. This file is located in the web-apps folder where your Apache SOAP servlet is located.

The XML is nothing more than a root element that contains all of the deployment descriptors for all of the services deployed. To deploy the Hello World service, simply take the deployment descriptor we wrote earlier and append it to this list. The next time that the SOAP servlet is started, the service manager will be reinitialized and the new service will be ready for use. A sample configuration file is given in Example 3-14.

Example 3-14: Apache SOAP configuration file

<root>
  <dd:service xmlns:dd="http://xml.apache.org/xml-soap/deployment"
              id="urn:Example1">
    <dd:provider type="java"
                 scope="Application"
                 methods="sayHello">
       <dd:java class="samples.Hello" 
                static="false" />
    </dd:provider>
    <dd:faultListener>
     org.apache.soap.server.DOMFaultListener
    </dd:faultListener>
    <dd:mappings />
   </dd:service>
</root>

The Hello Client

To invoke the Hello World service, use the Java class in Example 3-15.

Example 3-15: Hello client in Java

import java.io.*;
import java.net.*;
import java.util.*;
import org.apache.soap.*;
import org.apache.soap.rpc.*;

public class Example1_client {

  public static void main (String[] args) 
       throws Exception {

    System.out.println("\n\nCalling the SOAP Server to say hello\n\n");       
    URL url = new URL (args[0]);
    String name = args[1];

    Call call = new Call (  );
    call.setTargetObjectURI("urn:Example1");
    call.setMethodName("sayHello");
    call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC;);
    Vector params = new Vector (  );
    params.addElement (new Parameter("name", String.class, name, null));
    call.setParams (params);

    System.out.print("The SOAP Server says: ");

    Response resp = call.invoke(url, "");

    if (resp.generatedFault (  )) {
      Fault fault = resp.getFault (  );
      System.out.println ("\nOuch, the call failed: ");
      System.out.println ("  Fault Code   = " + fault.getFaultCode (  ));
      System.out.println ("  Fault String = " + fault.getFaultString (  ));
    } else {
      Parameter result = resp.getReturnValue (  );
      System.out.print(result.getValue (  ));
      System.out.println(  );
    }
  }
}

The amount of code to accomplish this relatively simple operation may seem surprising (nine lines to actually initialize and invoke the web services call). Java will never be as terse as Perl and other scripting languages, but it has other strengths. Also, various Java-based SOAP toolkits such as The Mind Electric’s GLUE and IBM’s Web Services ToolKit support dynamic proxy interfaces that cut down the amount of code necessary to invoke web services. Those interfaces, however, generally require additional mechanisms, such as WSDL, to simplify the programming interface. We will take a look at these dynamic proxies later in Chapter 5. For now, if you compile and run this class, you’ll end up with the same result that we saw in the Perl example:

% java samples.Hello http://localhost/soap/servlet/rpcrouter James

Calling the SOAP Server to say hello
The SOAP Server says: Hello James

%

Your Java web service is finished. If you have both the Perl and Java versions installed, run the Perl client script again but point it at the Java version of the Hello World service (the modified script is shown in Example 3-16). You’ll see that everything still works.

Posted in Soap Service | Tagged: , , , | 1 Comment »