Remote Method Calls with SOAP


This section is adapted from Geary and Horstmann, Core JavaServer Faces [Sun Microsystems Press 2004].

In recent years, web services have emerged as a popular technology for remote method calls. Technically, a web service has two components:

  • A server that can be accessed with the Simple Object Access Protocol (SOAP) transport protocol

  • A description of the service in the Web Service Description Language (WSDL) format

SOAP is an XML protocol that, like CORBA's IIOP, provides a protocol for invoking remote methods. Just as you can program CORBA clients and servers without knowing anything about IIOP, you don't really need to know any details about SOAP to call a web service.

WSDL is analogous to IDL. It describes the interface of the web service: the methods that can be called, and their parameter and return types. In this section, we discuss only the implementation of a client that connects to an existing web service. Someone else has already prepared the WSDL file in this situation.

Implementing a web service is beyond the scope of this book. For more information on this topic, see Chapter 8 of the J2EE tutorial at http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html.

To make web services easy to understand, we look at a concrete example: the Amazon web service, described at http://www.amazon.com/gp/aws/landing.html. The Amazon web service allows a programmer to interact with the Amazon system for a wide variety of purposes. For example, you can get listings of all books with a given author or title, or you can fill shopping carts and place orders. Amazon makes this service available for use by companies that want to sell items to their customers, using the Amazon system as a fulfillment backend. To run our example program, you will need to sign up with Amazon and get a free developer token that lets you connect to the service.

Alternatively, you can adapt the technique described in this section to any other web service. The site http://www.xmethods.com lists many freely available web services that you can try.

A primary attraction of web services is that they are language-neutral. We access the Amazon Web Services by using Java programs, but other developers can equally well use C++ or Visual Basic. The WSDL descriptor describes the services in a language-independent manner. For example, the WSDL for the Amazon Web Services (located at http://soap.amazon.com/schemas3/AmazonWebServices.wsdl) describes an AuthorSearchRequest operation as follows:

 <operation name="AuthorSearchRequest">    <input message="typens:AuthorSearchRequest"/>    <output message="typens:AuthorSearchResponse"/> </operation> . . . <message name="AuthorSearchRequest">    <part name="AuthorSearchRequest" type="typens:AuthorRequest"/> </message> <message name="AuthorSearchResponse">    <part name="return" type="typens:ProductInfo"/> </message> 

Elsewhere, it defines the data types. Here is the definition of AuthorRequest:

 <xsd:complexType name="AuthorRequest">    <xsd:all>       <xsd:element name="author" type="xsd:string"/>       <xsd:element name="page" type="xsd:string"/>       <xsd:element name="mode" type="xsd:string"/>       <xsd:element name="tag" type="xsd:string"/>       <xsd:element name="type" type="xsd:string"/>       <xsd:element name="devtag" type="xsd:string"/>       <xsd:element name="sort" type="xsd:string" minOccurs="0"/>       <xsd:element name="locale" type="xsd:string" minOccurs="0"/>       <xsd:element name="keywords" type="xsd:string" minOccurs="0"/>       <xsd:element name="price" type="xsd:string" minOccurs="0"/>    </xsd:all> </xsd:complexType> 

When this description is translated into Java, the AuthorRequest type becomes a class.

 public class AuthorRequest {    public AuthorRequest(String author, String page, String mode, String tag, String type,       String devtag, String sort, String locale, String keyword, String price) { . . . }    public String getAuthor() { . . . }    public void setAuthor(String newValue) { . . . }    public String getPage() { . . . }    public void setPage(String) { . . . }    . . . } 

To call the search service, construct an AuthorRequest object and call the authorSearchRequest of a "port" object.

[View full width]

AmazonSearchPort port = (AmazonSearchPort) (new AmazonSearchService_Impl() .getAmazonSearchPort()); AuthorRequest request = new AuthorRequest(name, "1", "books", "", "lite", "", token, "", "", ""); ProductInfo response = port.authorSearchRequest(request);

The port object translates the Java object into a SOAP message, passes it to the Amazon server, and translates the returned message into a ProductInfo object. The port classes are automatically generated.

NOTE

The WSDL file does not specify what the service does. It only specifies the parameter and return types.


Download the Java Web Services Developer Pack (JWSDP) from http://java.sun.com/webservices/webservicespack.html and install it.

To generate the required Java classes, place a config.xml file with the following contents into the directory of the client program:

 <?xml version="1.0" encoding="UTF-8"?> <configuration    xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">       <wsdl          location="http://soap.amazon.com/schemas3/AmazonWebServices.wsdl"          packageName="com.amazon" /> </configuration> 

Then run these commands:


jwsdp/jaxrpc/bin/wscompile.sh -import config.xml
jwsdp/jaxrpc/bin/wscompile.sh -gen -keep config.xml

Here, jwsdp is the directory into which you installed the JWSDP, such as /usr/local/jwsdp-1.4 or c:\jwsdp-1.4. (As usual, Windows users need to use \ instead of / and .bat instead of .sh.)

The first command imports the WSDL file from the given location. The second command generates the classes that the client needs. The -keep option keeps the source files. This is not strictly necessary, but you may find it interesting to look at some of them. As a result of these commands, a large number of classes are created in the specified package directory (here, com/amazon). Have a look at some of them, in particular com/amazon/AuthorRequest.java and com/amazon/Details.java. We use these classes in the sample application.

Our sample application (in Example 5-22) is straightforward. The user specifies an author name and clicks the Search button. We simply show the first page of the response (see Figure 5-11). This shows that the web service is successful. We leave it as the proverbial exercise for the reader to extend the functionality of the application.

Figure 5-11. Connecting to a web service


To compile this application, add the library file jwsdp/jaxrpc/lib/jaxrpc-impl.jar to your class path.

To run this application, your class file must contain the following:


. (the current directory)
jwsdp/jaxrpc/lib/jaxrpc-api.jar
jwsdp/jaxrpc/lib/jaxrpc-impl.jar
jwsdp/jaxrpc/lib/jaxrpc-spi.jar
jwsdp/jwsdp-shared/lib/activation.jar
jwsdp/jwsdp-shared/lib/mail.jar
jwsdp/saaj/lib/saaj-api.jar
jwsdp/saaj/lib/saaj-impl.jar

If you compile and run from the command line, you may want to use a shell script to automate this task.

This example shows that calling a web service is fundamentally the same as making any other remote method call. The programmer calls a local method on a proxy object, and the proxy connects to a server. Since web services are springing up everywhere, this is clearly an interesting technology for application programmers. Web services will become even easier to use when the tools and libraries are bundled into a future version of the JDK.

Example 5-22. SOAPTest.java
   1. import com.amazon.*;   2. import java.awt.*;   3. import java.awt.event.*;   4. import java.rmi.*;   5. import java.util.*;   6. import javax.swing.*;   7.   8. /**   9.    The client for the warehouse program.  10. */  11. public class SOAPTest  12. {  13.    public static void main(String[] args)  14.    {  15.       JFrame frame = new SOAPTestFrame();  16.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  17.       frame.setVisible(true);  18.    }  19. }  20.  21. /**  22.    A frame to select the book author and to display the server response.  23. */  24. class SOAPTestFrame extends JFrame  25. {  26.    public SOAPTestFrame()  27.    {  28.       setTitle("SOAPTest");  29.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  30.  31.       JPanel panel = new JPanel();  32.  33.       panel.add(new JLabel("Author:"));  34.       author = new JTextField(20);  35.       panel.add(author);  36.  37.       JButton searchButton = new JButton("Search");  38.       panel.add(searchButton);  39.       searchButton.addActionListener(new  40.          ActionListener()  41.          {  42.             public void actionPerformed(ActionEvent event)  43.             {  44.                result.setText("Please wait...");  45.                new Thread(new  46.                   Runnable()  47.                   {  48.                      public void run()  49.                      {  50.                         String name = author.getText();  51.                         String books = searchByAuthor(name);  52.                         result.setText(books);  53.                      }  54.                   }).start();  55.             }  56.          });  57.  58.       result = new JTextArea();  59.       result.setLineWrap(true);  60.       result.setEditable(false);  61.  62.       add(panel, BorderLayout.NORTH);  63.       add(new JScrollPane(result), BorderLayout.CENTER);  64.    }  65.  66.    /**  67.       Calls the Amazon web service to find titles that match the author.  68.       @param name the author name  69.       @return a description of the matching titles  70.    */  71.    private String searchByAuthor(String name)  72.    {  73.       try  74.       {  75.          AmazonSearchPort port = (AmazonSearchPort)  76.             (new AmazonSearchService_Impl().getAmazonSearchPort());  77.  78.          AuthorRequest request  79.             = new AuthorRequest(name, "1", "books", "", "lite", "", token, "", "", "");  80.          ProductInfo response = port.authorSearchRequest(request);  81.  82.          Details[] details = response.getDetails();  83.          StringBuilder r = new StringBuilder();  84.          for (Details d : details)  85.          {  86.             r.append("authors=");  87.             String[] authors = d.getAuthors();  88.             if (authors == null) r.append("[]");  89.             else r.append(Arrays.asList(d.getAuthors()));  90.             r.append(",title=");  91.             r.append(d.getProductName());  92.             r.append(",publisher=");  93.             r.append(d.getManufacturer());  94.             r.append(",pubdate=");  95.             r.append(d.getReleaseDate());  96.             r.append("\n");  97.          }  98.          return r.toString();  99.       } 100.       catch (RemoteException e) 101.       { 102.          return "Exception: " + e; 103.       } 104.    } 105. 106.    private static final int DEFAULT_WIDTH = 450; 107.    private static final int DEFAULT_HEIGHT = 300; 108. 109.    private static final String token = "your token goes here"; 110. 111.    private JTextField author; 112.    private JTextArea result; 113. } 



    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net