The JavaTM Web Services Tutorial
Home
TOC
Index
PREV TOP NEXT
Divider

JAX-RPC

The Java API for XML-based RPC (JAX-RPC) is the Java API for developing and using Web services.

Overview of JAX-RPC

An RPC-based Web service is a collection of procedures that can be called by a remote client over the Internet. For example, a typical RPC-based Web service is a stock quote service that takes a SOAP (Simple Object Access Protocol) request for the price of a specified stock and returns the price via SOAP.


Note: The SOAP 1.1 specification, available from http://www.w3.org/, defines a framework for the exchange of XML documents. It specifies, among other things, what is required and optional in a SOAP message and how data can be encoded and transmitted. JAX-RPC and JAXM are both based on SOAP.

A Web service, a server application that implements the procedures that are available for clients to call, is deployed on a server-side container. The container can be a servlet container such as Tomcat or a Java 2 Platform, Enterprise Edition (J2EE) container that is based on Enterprise JavaBeans (EJB) technology.

A Web service can make itself available to potential clients by describing itself in a Web Services Description Language (WSDL) document. A WSDL description is an XML document that gives all the pertinent information about a Web service, including its name, the operations that can be called on it, the parameters for those operations, and the location of where to send requests. A consumer (Web client) can use the WSDL document to discover what the service offers and how to access it. How a developer can use a WSDL document in the creation of a Web service is discussed later.

Interoperability

Perhaps the most important requirement for a Web service is that it be interoperable across clients and servers. With JAX-RPC, a client written in a language other than the Java programming language can access a Web service developed and deployed on the Java platform. Conversely, a client written in the Java programming language can communicate with a service that was developed and deployed using some other platform.

What makes this interoperability possible is JAX-RPC's support for SOAP and WSDL. SOAP defines standards for XML messaging and the mapping of data types so that applications adhering to these standards can communicate with each other. JAX-RPC adheres to SOAP standards, and is, in fact, based on SOAP messaging. That is, a JAX-RPC remote procedure call is implemented as a request-response SOAP message.

The other key to interoperability is JAX-RPC's support for WSDL. A WSDL description, being an XML document that describes a Web service in a standard way, makes the description portable. WSDL documents and their uses will be discussed more later.

Ease of Use

Given the fact that JAX-RPC is based on a remote procedure call (RPC) mechanism, it is remarkably developer friendly. RPC involves a lot of complicated infrastructure, or "plumbing," but JAX-RPC mercifully makes the underlying implementation details invisible to both the client and service developer. For example, a Web services client simply makes Java method calls, and all the internal marshalling, unmarshalling, and transmission details are taken care of automatically. On the server side, the Web service simply implements the services it offers and, like the client, does not need to bother with the underlying implementation mechanisms.

Largely because of its ease of use, JAX-RPC is the main Web services API for both client and server applications. JAX-RPC focuses on point-to-point SOAP messaging, the basic mechanism that most clients of Web services use. Although it can provide asynchronous messaging and can be extended to provide higher quality support, JAX-RPC concentrates on being easy to use for the most common tasks. Thus, JAX-RPC is a good choice for applications that wish to avoid the more complex aspects of SOAP messaging and for those that find communication using the RPC model a good fit. The more heavy-duty alternative for SOAP messaging, the Java API for XML Messaging (JAXM), is discussed later in this introduction.

Advanced Features

Although JAX-RPC is based on the RPC model, it offers features that go beyond basic RPC. For one thing, it is possible to send complete documents and also document fragments. In addition, JAX-RPC supports SOAP message handlers, which make it possible to send a wide variety of messages. And JAX-RPC can be extended to do one-way messaging in addition to the request-response style of messaging normally done with RPC. Another advanced feature is extensible type mapping, which gives JAX-RPC still more flexibility in what can be sent.

Using JAX-RPC

In a typical scenario, a business might want to order parts or merchandise. It is free to locate potential sources however it wants, but a convenient way is through a business registry and repository service such as a Universal Description, Discovery and Integration (UDDI) registry. Note that the Java API for XML Registries (JAXR), which is discussed later in this introduction, offers an easy way to search for Web services in a business registry and repository. Web services generally register themselves with a business registry and store relevant documents, including their WSDL descriptions, in its repository.

After searching a business registry for potential sources, the business might get several WSDL documents, one for each of the Web services that meets its search criteria. The business client can use these WSDL documents to see what the services offer and how to contact them.

Another important use for a WSDL document is as a basis for creating stubs, the low-level classes that are needed by a client to communicate with a remote service. In the JAX-RPC reference implementation (RI), the tool that uses a WSDL document to generate stubs is called wscompile.

The RI has another tool, called wsdeploy, that creates ties, the low-level classes that the server needs to communicate with a remote client. Stubs and ties, then, perform analogous functions, stubs on the client side and ties on the server side. And in addition to generating ties, wsdeploy can be used to create WSDL documents.

A JAX-RPC runtime system, such as the one included in the JAX-RPC RI, uses the stubs and ties created by wscompile and wsdeploy behind the scenes. It first converts the client's remote method call into a SOAP message and sends it to the service as an HTTP request. On the server side, the JAX-RPC runtime system receives the request, translates the SOAP message into a method call, and invokes it. After the Web service has processed the request, the runtime system goes through a similar set of steps to return the result to the client. The point to remember is that as complex as the implementation details of communication between the client and server may be, they are invisible to both Web services and their clients.

Creating a Web Service

Developing a Web service using JAX-RPC is surprisingly easy. The service itself is basically two files, an interface that declares the service's remote procedures and a class that implements those procedures. There is a little more to it, in that the service needs to be configured and deployed, but first, let's take a look at the two main components of a Web service, the interface definition and its implementation class.

The following interface definition is a simple example showing the methods a wholesale coffee distributor might want to make available to its prospective customers. Note that a service definition interface extends java.rmi.Remote and its methods throw a java.rmi.RemoteException object.

package coffees;
 
import java.rmi.Remote; 
import java.rmi.RemoteException;
 
public interface CoffeeOrderIF extends Remote { 
  public Coffee [] getPriceList() 
                  throws RemoteException; 
  public String orderCoffee(String coffeeName, int quantity)
                  throws RemoteException; 
}
 

The method getPriceList returns an array of Coffee objects, each of which contains a name field and a price field. There is one Coffee object for each of the coffees the distributor currently has for sale. The method orderCoffee returns a String that might confirm the order or state that it is on back order.

The following example shows what the implementation might look like (with implementation details omitted). Presumably, the method getPriceList will query the company's database to get the current information and return the result as an array of Coffee objects. The second method, orderCoffee, will also need to query the database to see if the particular coffee specified is available in the quantity ordered. If so, the implementation will set the internal order process in motion and send a reply informing the customer that the order will be filled. If the quantity ordered is not available, the implementation might place its own order to replenish its supply and notify the customer that the coffee is backordered.

package coffees;  
 
public class CoffeeOrderImpl implements CoffeeOrderIF { 
  public Coffee [] getPriceList() throws RemoteException; {
    . . .
  }
 
  public String orderCoffee(String coffeeName, int quantity)
                  throws RemoteException; {
    . . .
  }
}   
 

After writing the service's interface and implementation class, the developer's next step is to run the mapping tool. The tool can use the interface and its implementation as a basis for generating the stub and tie classes plus other classes as necessary. And, as noted before, the developer can also use the tool to create the WSDL description for the service.

The final steps in creating a Web service are packaging and deployment. Packaging a Web service definition is done via a Web application archive (WAR). A WAR file is a JAR file for Web applications, that is, a file that contains all the files needed for the Web application in compressed form. For example, the CoffeeOrder service could be packaged in the file jaxrpc-coffees.war, which makes it easy to distribute and install.

One file that must be in every WAR file is an XML file called a deployment descriptor. This file, by convention named web.xml, contains information needed for deploying a service definition. For example, if it is being deployed on a servlet engine such as Tomcat, the deployment descriptor will include the servlet name and description, the servlet class, initialization parameters, and other startup information. One of the files referenced in a web.xml file is a configuration file that is automatically generated by the mapping tool. In our example, this file would be called CoffeeOrder_Config.properties.

Deploying our CoffeeOrder Web service example in a Tomcat container can be accomplished by simply copying the jaxrpc-coffees.war file to Tomcat's webapps directory. Deployment in a J2EE container is facilitated by using the deployment tools supplied by application server vendors.

Coding a Client

Writing the client application for a Web service entails simply writing code that invokes the desired method. Of course, much more is required to build the remote method call and transmit it to the Web service, but that is all done behind the scenes and is invisible to the client.

The following class definition is an example of a Web services client. It creates an instance of CoffeeOrderIF and uses it to call the method getPriceList. Then it accesses the price and name fields of each Coffee object in the array returned by the method getPriceList in order to print them out.

The class CoffeeOrderServiceImpl is one of the classes generated by the mapping tool. It is a stub factory whose only method is getCoffeeOrderIF; in other words, its whole purpose is to create instances of CoffeeOrderIF. The instances of CoffeeOrderIF that are created by CoffeeOrderServiceImpl are client side stubs that can be used to invoke methods defined in the interface CoffeeOrderIF. Thus, the variable coffeeOrder represents a client stub that can be used to call getPriceList, one of the methods defined in CoffeeOrderIF.

The method getPriceList will block until it has received a response and returned it. Because a WSDL document is being used, the JAX-RPC runtime will get the service endpoint from it. Thus, in this case, the client class does not need to specify the destination for the remote procedure call. When the service endpoint does need to be given, it can be supplied as an argument on the command line. Here is what a client class might look like:

package coffees;  
 
public class CoffeeClient {
  public static void main(String[] args) {
    try { 
      CoffeeOrderIF coffeeOrder = new
         CoffeeOrderServiceImpl().getCoffeeOrderIF();
      Coffee [] priceList = 
              coffeeOrder.getPriceList():
      for (int i = 0; i < priceList.length; i++) {
        System.out.print(priceList[i].getName() + " ");
        System.out.println(priceList[i].getPrice());
      }
    } catch (Exception ex) { 
    ex.printStackTrace();
    } 
  } 
}
 

Invoking a Remote Method

Once a client has discovered a Web service, it can invoke one of the service's methods. The following example makes the remote method call getPriceList, which takes no arguments. As noted previously, the JAX-RPC runtime can determine the endpoint for the CoffeeOrder service (which is its URI) from its WSDL description. If a WSDL document had not been used, you would need to supply the service's URI as a command line argument. After you have compiled the file CoffeeClient.java, here is all you need to type at the command line to invoke its getPriceList method.

java coffees.CoffeeClient
 

The remote procedure call made by the previous line of code is a static method call. In other words, the RPC was determined at compile time. It should be noted that with JAX-RPC, it is also possible to call a remote method dynamically at run time. This can be done using either the Dynamic Invocation Interface (DII) or a dynamic proxy.

Divider
Home
TOC
Index
PREV TOP NEXT
Divider

This tutorial contains information on the 1.0 version of the Java Web Services Developer Pack.

All of the material in The Java Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.