Consuming the SAAJ Web Service

To use your Web Service you need a client. For the purposes of this exercise, this client will be a standard Java class with a main method. However, it could also be a J2EE component such as a JSP or EJB or a non-Java client. The client will create a SOAP message containing a given location, send the service a request for a list of jobs at that location and print out the list when it returns.

Sending a Basic SOAP Message

The SAAJ API provides a simple way to send a straightforward SOAP message. An SAAJ client will create a SOAP message using the SAAJ API and send that message to a SOAP server at a specified URL.

The first thing to do is create the SOAP message. To do this, you need an instance of the MessageFactory class that you saw earlier. From this you obtain a SOAPMessage to populate with your request. This is identical to the way you created the response SOAPMessage in the servlet earlier.

You now have an empty SOAP envelope you can populate. The message to be sent in this case is a request for a list of jobs. You have the same marshaling issues as on the server-side and these are discussed shortly from the client perspective. The client class, SAAJAgencyClient, uses a ClientMarshaler helper class to marshal between Java and XML. The method addRequestToMessage() takes the message type (“jobsAtLocation”) together with the location itself and creates a request document in the given SOAPMessage. Listing 21.11 shows the client creating a SOAPMessage and populating it.

Listing 21.11. Creating the SOAP Message
public class SAAJAgencyClient
{
    private static String location = "%";

    public static void main(String[] args)
    {
        // Obtain location from command line arguments
        ...

        MessageFactory messageFactory = MessageFactory.newInstance();
							// Populate message with request type of "jobsAtLocation"
							// and location
							SOAPMessage soapRequest = messageFactory.createMessage();
							ClientMarshaler.addRequestToMessage("jobsAtLocation", location, soapRequest);

        ...
    }
}

Now that the message is ready, the client needs a javax.xml.soap.SOAPConnection to send the message. This is created from a javax.xml.soap.SOAPConnectionFactory. As with the MessageFactory, the SOAPConnectionFactory can be instantiated directly using the newInstance() method or can be obtained through JNDI if one is registered with the J2EE container in which the component is running. The createConnection() method of the SOAPConnectionFactory returns a SOAPConnection.

As SAAJ is used to make direct SOAP calls to servers, you must specify the address (or endpoint) of the target server using a java.net.URL. In this case, the target URL is that of the server you deployed earlier, namely http://localhost:8000/wsagency/LocationServices.

The SOAP server happens to be implemented using Java and SAAJ but this is not essential. The server could equally well be implemented in Perl or as an ASP.NET components written in C#. Note that the URL for the Web Service looks just like any other servlet address and contains no special indications that it is a Web Service rather than an HTML interface.

You now have the two things you need—a message and somewhere to send it—so you can now send the message using the SOAPConnection's call() method. The call() method takes as parameters the message itself and the target endpoint to which it should be delivered. The sequence of obtaining the connection and making the call is shown in Listing 21.12.

Listing 21.12. Sending the SOAP Message
public class SAAJAgencyClient
{
    ...
    public static void main(String[] args)
    {
        ...

        SOAPConnectionFactory connectionFactory = SOAPConnectionFactory. newInstance();
							SOAPConnection connection = connectionFactory.createConnection();
							URL endpoint = new URL("http://localhost:8000/wsagency/LocationServices");
							// Send request
							soapResponse = connection.call(soapRequest, endpoint);

        ...
    }
}

Message-Style Web Services and Web Service Registries Because the service you are calling is a synchronous, request/response service, you will receive a SOAP message as a response. In application terms, this message contains an XML document listing the jobs at the location you provided. To process this list, you need to retrieve the XML document from the SOAP message. This XML document will be contained in the SOAP envelope. Once again, the ClientMarshaler class encapsulates the conversion from XML to Java and provides a getJobsFromMessage() method that creates an array of Java Strings. These strings can then be printed out as shown in Listing 21.13.

Listing 21.13. Printing Out the List of Jobs
public class SAAJAgencyClient
{
    ...
    public static void main(String[] args)
    {
        ...

        // Retrieve job list from response
							System.out.println("Job list: ");
							String[] jobs = ClientMarshaler.getJobsFromMessage(soapResponse);
							for(int i = 0; i < jobs.length; i++)
							{
							System.out.println(jobs[i]);
							}
							System.out.println("
Done
");

        ...
    }
}

Client-side Marshaling Between Java and XML

The client-side marshaling is very similar to the server-side marshaling except that it performs the actions in reverse. The addRequestToMessage() and getJobsFromMessage() methods create instances of the Name class and manipulate instances of SOAPEnvlope, SOAPBody and SOAPEnvelope. The ClientMarshaler is shown in Listing 21.14.

Listing 21.14. The ClientMarshaler
package client;

import java.util.Iterator;

import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

public class ClientMarshaler
{
  static final String nsAgency = "http://J2EE21/agency";
  static final String prefixAgency = "agency";

  public static void addRequestToMessage(String type, String location, SOAPMessage
 soapMessage) throws SOAPException
  {
    SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
    SOAPBody soapBody = soapEnvelope.getBody();

    // Create a request element under the body
    Name requestName = soapEnvelope.createName("request", prefixAgency, nsAgency);
    SOAPBodyElement soapRequest = soapBody.addBodyElement(requestName);

    // Create a type element under the agencyRequest
    Name typeName = soapEnvelope.createName("type", prefixAgency, nsAgency);
    SOAPElement soapType = soapRequest.addChildElement(typeName);
    soapType.addTextNode(type);

    // Create a location element under the agencyRequest
    Name locationName = soapEnvelope.createName("location", prefixAgency, nsAgency);
    SOAPElement soapLocation = soapRequest.addChildElement(locationName);
    soapLocation.addTextNode(location);
  }
  public static String[] getJobsFromMessage(SOAPMessage soapMessage) throws SOAPException
  {
    SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
    SOAPBody soapBody = soapEnvelope.getBody();

    // Retrieve the response element from under the body
    Name responseName = soapEnvelope.createName("response", prefixAgency, nsAgency);
    SOAPElement soapResponse = getChildElementByName(responseName, soapBody);

    // Retrieve the numJobs element from under the response
    Name numJobsName = soapEnvelope.createName("numJobs", prefixAgency, nsAgency);
    SOAPElement soapNumJobs = getChildElementByName(numJobsName, soapResponse);

    int numJobs = Integer.parseInt(soapNumJobs.getValue());
    String[] jobs = new String[numJobs];

    // Retrieve the jobs element from under the response
    Name jobsName = soapEnvelope.createName("jobs", prefixAgency, nsAgency);
    SOAPElement soapJobs = getChildElementByName(jobsName, soapResponse);

    // Retrieve the jobs and put them in an array
    Iterator jobIterator = soapJobs.getChildElements();

    for (int i = 0; i < numJobs && jobIterator.hasNext(); i++)
    {
      SOAPElement jobElement = (SOAPElement)jobIterator.next();
      jobs[i] = jobElement.getValue();
    }

    return jobs;
  }

  private static SOAPElement getChildElementByName(Name name, SOAPElement element)
                                                   throws SOAPException
  {
    Iterator childIterator = element.getChildElements(name);

    if (childIterator.hasNext())
    {
      SOAPElement childElement = (SOAPElement)childIterator.next();

      return childElement;
    }
    else
    {
      throw new SOAPException("element " + name.getQualifiedName() + " is missing");
    }
  }
}

As with the server-side marshaling, SOAPExceptions might be thrown by the various methods and constructors used. Please refer to the SAAJ API documentation for specific details.

Running the Simple Client

You compile and run your client as you would any other Java application. The client is built as part of the following Ant directive:

asant build

You can run the client program using

asant run

This will prompt you for a location and then send a SOAP message to the SAAJ web service you deployed earlier. Provide the location “London” and you should see the following message printed out (depending on how many jobs you have registered for London):

[java] Using Location: London
[java] Job list:
[java] winston/Cigar trimmer

[java] Done

So, now you have created, deployed, and invoked a simple Web Service under J2EE using SAAJ.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.19.174