ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Java and XML: SOAP
Pages: 1, 2, 3, 4, 5, 6, 7

Deploying the service

At this point, you've got a working deployment descriptor and a set of code artifacts to expose, and you can deploy your service. Apache SOAP comes with a utility to do this task, provided you have done the setup work. First, you need a deployment descriptor for your service, which I just talked about. Second, you need to make the classes for your service available to the SOAP server. The best way to do this is to jar up the service class from the last section:

jar cvf javaxml2.jar javaxml2/CDCatalog.class

Take this jar file and drop it into your lib/ directory (or wherever libraries are auto-loaded for your servlet engine), and restart your servlet engine.

WARNING: When you do this, you have created a snapshot of your class file. Changing the code in the CDCatalog.java file and recompiling it will not cause the servlet engine to pick up the changes. You'll need to re-jar the archive and copy it over to your lib/ directory each time code changes are made to ensure your service is updated. You'll also want to restart your servlet engine to make sure the changes are picked up by the engine as well.

With your service class (or classes) accessible by your SOAP server, you can now deploy the service, using Apache SOAP's org.apache.soap.server.ServiceManager utility class:

C:\javaxml2\Ch12>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter deploy xml\CDCatalogDD.xml

The first argument is the SOAP server and RPC router servlet, the second is the action to take, and the third is the relevant deployment descriptor. Once this has executed, verify your service was added:

(gandalf)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient
  http://localhost:8080/soap/servlet/rpcrouter list
Deployed Services:
    urn:cd-catalog
    urn:AddressFetcher
    urn:xml-soap-demo-calculator

At a minimum, this should show any and all services you have available on the server. Finally, you can easily undeploy the service, as long as you know its name:

C:\javaxml2\Ch12>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter undeploy urn:cd-catalog

Every time you update your service code, you must undeploy and then redeploy to ensure the SOAP server is running the newest copy.

An RPC Client

Next up is the client. I'm going to keep things simple, and just write a couple of command-line programs that invoke SOAP-RPC. It would be impossible to try and guess your business case, so I just focus on the SOAP details and let you work out integration with your existing software. Once you have the business portion of your code working, there are some basic steps you'll take in every SOAP-RPC call:

  • Create the SOAP-RPC call
  • Set up any type mappings for custom parameters
  • Set the URI of the SOAP service to use
  • Specify the method to invoke
  • Specify the encoding to use
  • Add any parameters to the call
  • Connect to the SOAP service
  • Receive and interpret a response

That may seem like a lot, but most of the operations are one- or two-line method invocations. In other words, talking to a SOAP service is generally a piece of cake. Example 12-6 shows the code for the CDAdder class, which allows you to add a new CD to the catalog. Take a look at the code, and then I'll walk you through the juicy bits.

Example 12-6: The CDAdder class

package javaxml2;
 
import java.net.URL;
import java.util.Vector;
import org.apache.soap.Constants;
import org.apache.soap.Fault;
import org.apache.soap.SOAPException;
import org.apache.soap.rpc.Call;
import org.apache.soap.rpc.Parameter;
import org.apache.soap.rpc.Response;
 
public class CDAdder {
 
  public void add(URL url, String title, String artist)
    throws SOAPException {
 
    System.out.println("Adding CD titled '" + title + "' by '" +
      artist + "'");
 
    // Build the Call object
    Call call = new Call( );
    call.setTargetObjectURI("urn:cd-catalog");
    call.setMethodName("addCD");
    call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
 
    // Set up parameters
    Vector params = new Vector( );
    params.addElement(new Parameter("title", String.class, title, null));
    params.addElement(new Parameter("artist", String.class, artist, null));
    call.setParams(params);
 
    // Invoke the call
    Response response;
    response = call.invoke(url, "");
 
    if (!response.generatedFault( )) {
      System.out.println("Successful CD Addition.");
    } else {
      Fault fault = response.getFault( );
      System.out.println("Error encountered: " + fault.getFaultString( ));
    }
  }
 
  public static void main(String[] args) {
    if (args.length != 3) {
      System.out.println("Usage: java javaxml2.CDAdder [SOAP server URL] " +
        "\"[CD Title]\" \"[Artist Name]\"");
      return;
    }
 
    try {
      // URL for SOAP server to connect to
      URL url = new URL(args[0]);
 
      // Get values for new CD
      String title = args[1];
      String artist = args[2];
 
      // Add the CD
      CDAdder adder = new CDAdder( );
      adder.add(url, title, artist);
    } catch (Exception e) {
      e.printStackTrace( );
    }
  }
}

This program captures the URL of the SOAP server to connect to, as well as information needed to create and add a new CD to the catalog. Then, in the add( ) method, the code creates the SOAP Call object, on which all the interesting interaction occurs. The target URI of the SOAP service and the method to invoke are set on the call, both of which match up to values from the service's deployment descriptor, from Example 12-5. Next, the encoding is set, which should always be the constant Constants.NS_URI_SOAP_ENC unless you have very unique encoding needs.

It creates a new Vector populated with SOAP Parameter objects. Each of these represents a parameter to the specified method, and since the addCD( ) method takes two String values, this is pretty simple. Supply the name of the parameter (for use in the XML and debugging), the class for the parameter, and the value. The fourth argument is an optional encoding, if a single parameter needs a special encoding. For no special treatment, the value null suffices. The resulting Vector is then added to the Call object.

Once your call is set up, use the invoke( ) method on that object. The return value from this method is an org.apache.soap.Response instance, which is queried for any problems that resulted. This is fairly self-explanatory, so I'll leave it to you to walk through the code. Once you've compiled your client, and followed the instructions earlier in this chapter for setting up your classpath, run the sample as follows:

C:\javaxml2\build>java javaxml2.CDAdder
  http://localhost:8080/soap/servlet/rpcrouter   "Riding the Midnight Train" "Doc Watson"
 
Adding CD titled 'Riding the Midnight Train' by 'Doc Watson'
Successful CD Addition

Example 12-7 is another simple class, CDLister, which lists all current CDs in the catalog. I won't go into detail on it, as it's very similar to Example 12-6, and is mainly reinforcement of what I've already talked about.

Example 12-7: The CDLister class

package javaxml2;
 
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.apache.soap.Constants;
import org.apache.soap.Fault;
import org.apache.soap.SOAPException;
import org.apache.soap.rpc.Call;
import org.apache.soap.rpc.Parameter;
import org.apache.soap.rpc.Response;
 
public class CDLister {
 
  public void list(URL url) throws SOAPException {
    System.out.println("Listing current CD catalog.");
 
    // Build the Call object
    Call call = new Call( );
    call.setTargetObjectURI("urn:cd-catalog");
    call.setMethodName("list");
    call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
 
    // No parameters needed
 
    // Invoke the call
    Response response;
    response = call.invoke(url, "");
 
    if (!response.generatedFault( )) {
      Parameter returnValue = response.getReturnValue( );
      Hashtable catalog = (Hashtable)returnValue.getValue( );
      Enumeration e = catalog.keys( );
      while (e.hasMoreElements( )) {
        String title = (String)e.nextElement( );
        String artist = (String)catalog.get(title);
        System.out.println(" '" + title + "' by " + artist);
      }
    } else {
      Fault fault = response.getFault( );
      System.out.println("Error encountered: " + fault.getFaultString( ));
    }
  }
 
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java javaxml2.CDAdder [SOAP server URL]");
      return;
    }
 
    try {
      // URL for SOAP server to connect to
      URL url = new URL(args[0]);
 
      // List the current CDs
      CDLister lister = new CDLister( );
      lister.list(url);
    } catch (Exception e) {
      e.printStackTrace( );
    }
  }
}

The only difference in this method from the CDAdder class is that the Response object has a return value (the Hashtable from the list( ) method). This is returned as a Parameter object, which allows a client to check its encoding and then extract the actual method return value. Once that's done, the client can use the returned value like any other Java object, and in the example simply runs through the CD catalog and prints out each one. You can now run this additional client to see it in action:

C:\javaxml2\build>java javaxml2.CDLister
  http://localhost:8080/soap/servlet/rpcrouter
Listing current CD catalog.
 'Riding the Midnight Train' by Doc Watson
 'Taproot' by Michael Hedges
 'Nickel Creek' by Nickel Creek
 'Let it Fall' by Sean Watkins
 'Aerial Boundaries' by Michael Hedges

That's really all there is to basic RPC functionality in SOAP. I'd like to push on a bit, though, and talk about a few more complex topics.

Pages: 1, 2, 3, 4, 5, 6, 7

Next Pagearrow