A Simple Example: HelloWorld



A Simple Example: HelloWorld

This example shows you how to create a service named HelloWorld. A remote client of the HelloWorld service can invoke the sayHello method, which accepts a string parameter and then returns a string.

1 HelloWorld at Runtime

Figure shows the structure of the HelloWorld service after it's been deployed. Here's what happens at runtime:

Figure. The HelloWorld Example at Runtime
graphics/09fig01.gif
  1. To call a remote procedure, the HelloClient program invokes a method on a stub, a local object that represents the remote service.

  2. The stub invokes routines in the JAX-RPC runtime system of the reference implementation.

  3. The runtime system converts the remote method call into a SOAP message and then transmits the message as an HTTP request.

  4. When the server receives the HTTP request, the JAX-RPC runtime system extracts the SOAP message from the request and translates it into a method call.

  5. The JAX-RPC runtime system invokes the method on the tie object.

  6. The tie object invokes the method on the implementation of the HelloWorldservice.

The application developer only provides the top layers in the stacks depicted by Figure. Figure shows where the layers originate.

Who (or What) Provides the Layers

Layer

Source

HelloClient Program

Provided by the application developer

HelloWorld Service (definition interface and implementation class)

 

Stubs Ties

Generated by the xrpcc tool, which is run by the application developer

JAX-RPC Runtime System

Included with the reference implementation

2 HelloWorld Files

To create a service, an application developer needs to provide just a few files. For the HelloWorld example, these files are in the docs/tutorial/examples/jaxrpc/hello subdirectory:

  • HelloIF.java— the service definition interface

  • HelloImpl.java— the implementation class for the HelloIF interface

  • config.xml— a configuration file read by the xrpcc tool, which creates the stub and tie classes

  • web.xml— a deployment descriptor for the Web component (a servlet) that dispatches to the service

  • HelloClient.java— the remote client that contacts the service and then invokes the sayHello method

3 Overview of Steps

The basic steps for developing a service definition are as follows:

  1. Code the service definition interface and implementation class.

  2. Compile the service definition code of step 1.

  3. Create the configuration file.

  4. Generate the stubs and ties.

  5. Create the deployment descriptor.

  6. Package the service definition.

  7. Deploy the service definition.

On the client side, these are the steps:

  1. Code the client.

  2. Compile the client code.

  3. Run the client.

4 Setting Up

Before you try out the HelloWorld example, verify that you've installed the required software and that you've set the necessary environment variables.

Required Software

For a list of the required software and supported operating systems, see the Release Notes of the Java Web Services Developer Pack.

The Java Web Services Developer Pack includes Tomcat and the ant build utility. You must use the included version of Tomcat to run the examples in this tutorial. Although you may use a separate installation of ant, we recommend that you run the included version in order to avoid confusion over incompatible versions.

Environment Variables

Before you try out the HelloWorld example, you must set some environment variables. For more information, see the Release Notes of the Java Web Services Developer Pack.

Setting build.xml Properties

If you are on a Windows system, you may skip this section.

  1. In a text editor, open the docs/tutorial/examples/jaxrpc/common/config-build.propertiesfile.

  2. If you are on a UNIX system, change the value of the script-suffix property to sh. For Windows, the value should be bat, which is the default.

  3. Save the config-build.properties file and exit the editor.

5 Coding the Service Definition Interface and Implementation Class

A service definition interface declares the methods that a remote client may invoke on the service. The interface must conform to a few rules:

  • It extends the java.rmi.Remote interface.

  • It must not have constant declarations, such as public final static.

  • The methods must throw the java.rmi.RemoteException or one of its subclasses. (The methods may also throw service-specific exceptions.)

  • Method parameters and return types must be supported JAX-RPC types. (See the JAX-RPC Specifications.)

    In this example, the service definition interface is HelloIF.java:


package hello; 

import java.rmi.Remote; 
import java.rmi.RemoteException; 

public interface HelloIF extends Remote {
    public String sayHello(String s) throws RemoteException; 
}

In addition to the interface, you'll need to code the class that implements the interface. In this example, the implementation class is called HelloImpl:


package hello; 

public class HelloImpl implements HelloIF {

    public String message = new String("Hello "); 

    public String sayHello(String s) {
        return new String(message + s); 
    } 
}

6 Compiling the Service Definition Code

To compile HelloIF.java and HelloImpl.java, go to the docs/tutorial/examples/jaxrpc/hello directory and type the following:


ant compile-server

This command places the resulting class files in the build subdirectory.

7 Creating the Configuration File

The config.xml file contains information needed by the xrpcc tool, which you'll run in the next section.

In the file listing that follows, note the values defined in the <service> element. The name of the service, HelloWorld, will be used as the prefix of the HelloWorldImpl class name. Generated by the xrpcc tool, the HelloWorldImplis instantiated by the client class. (See Coding the Client (page 315).) The packageName attribute, hello, is the name of the package of the classes generated by xrpcc. In the <interface> subelement, the name attribute corresponds to the fully qualified name of the service definition interface, hello.HelloIF. The servantName attribute is the name of the interface's implementation class, hello.HelloImpl.

Here is the config.xml file:


<?xml version="1.0" encoding="UTF-8"?> 
<configuration 
   xmlns="http://java.sun.com/jax-rpc-ri/xrpcc-config"> 
   <rmi name="HelloWorldService" 
      targetNamespace="http://hello.org/wsdl" 
      typeNamespace="http://hello.org/types"> 
      <service name="HelloWorld" packageName="hello"> 
         <interface name="hello.HelloIF" 
         servantName="hello.HelloImpl"/> 
      </service> 
   </rmi> 
</configuration>

For more information about the syntax of the tool's configuration file, see the section Configuration File (page 486).

Note

Although required for the reference implementation of JAX-RPC, the configuration file and xrpcc tool are not defined in the specifications. Their syntax and usage may change in future releases.


8 Generating the Stubs and Ties

The xrpcc tool generates the stubs and ties, which are lower-level classes that enable the client and server to communicate. The tool also creates a properties file and a WSDL file. Used internally by the reference implementation, the properties file is not defined in the specifications. For information about the relationship between JAX-RPC technology and WSDL files, please refer to the JAX-RPC Specifications.

In this example, the tool reads the service definition interface and the configuration file. (Alternatively, the tool may read a WSDL file instead of the interface. See Starting with a WSDL Document (page 488) for more information.)

The xrpcc tool is a script— xrpcc.sh for UNIX or xprcc.bat for Windows.

To create the stubs and ties, run the tool as follows:

UNIX:


xrpcc.sh -classpath build -both -d build config.xml

Windows:


xrpcc.bat -classpath build -both -d build config.xml

The -both option instructs xrpcc to generate both stubs and ties. The -doption denotes the destination directory for the generated files. See the section Syntax (page 485) for the full syntax of the xrpcc tool.

9 Creating the Deployment Descriptor

A deployment descriptor is an XML file that provides configuration information for the Web server about the Web components (JSP pages or servlets) that are in a Web application. Because the HelloWorld service is deployed as a servlet, the deployment descriptor has some elements that are related to the service. This section describes only those elements; for more information about deployment descriptors, see the Java Servlet Specifications.

Let's take a quick look at a couple of the elements in the deployment descriptor (web.xml). First, note the HelloWorld_Config.properties value of the <init-param> element. This properties file was generated by the xrpcc tool. The name of the file is the HelloWorld service name (which was defined in the configuration file) appended by the _Config.properties string. The value of the <url-pattern> element, /jaxrpc/*, is part of the URL that designates the service's endpoint. This URL is passed to the HelloClient program as a command-line parameter. See Running the Client (page 316).

The web.xml deployment descriptor follows:


<?xml version="1.0" encoding="UTF-8"?> 

 <!DOCTYPE web-app PUBLIC 
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
     "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"> 
<web-app> 
   <display-name>HelloWorldApplication</display-name> 
   <description>Hello World Application</description> 
   <servlet> 
      <servlet-name>JAXRPCEndpoint</servlet-name> 
      <display-name>JAXRPCEndpoint</display-name> 
      <description> 
         Endpoint for Hello World Application 
      </description> 
      <servlet-class> 
        com.sun.xml.rpc.server.http.JAXRPCServlet 
      </servlet-class> 
      <init-param> 
         <param-name>configuration.file</param-name> 
         <param-value> 
          /WEB_INF/HelloWorld_Config.properties 
        </param-value> 
      </init-param> 
      <load-on-startup>0</load-on-startup> 
   </servlet> 
   <servlet-mapping> 
      <servlet-name>JAXRPCEndpoint</servlet-name> 
      <url-pattern>/jaxrpc/*</url-pattern> 
   </servlet-mapping> 
   <session-config> 
      <session-timeout>60</session-timeout> 
   </session-config> 
</web-app>

Packaging the Service Definition

A service definition is packaged in a Web application archive (WAR), a JAR file whose contents is defined by the Java Servlet specifications. WAR files make it easy to distribute and install (deploy) the service on various sites. In a later step, you will deploy the jaxrpc-hello.war file on Tomcat. For JAX-RPC, a WAR file contains the following files:

  • One or more service definition interfaces

    Each service definition has a single interface, but a WAR file may contain the files for more than one service. In this example, the service definition interface is HelloIF.class.

  • One or more service definition classes that implement the interfaces

    For each service definition interface, you must provide a corresponding service implementation class (HelloImpl.class).

  • Classes for pluggable serializers and deserializers

    This example does not require these files. (See the JAX-RPC Specifications for more information.)

  • Other files required by the service implementation classes

    Examples of these files are: helper classes, JPEG images, and XML documents. Since it's so simple, the HelloImpl class does not need any of these other files.

  • A deployment descriptor

    All WAR files require a deployment descriptor (web.xml).

  • An optional WSDL file that describes the service

    In a previous section, you created the HelloWorldService.wsdl file by running the xrpcc tool.

In addition to the preceding list of files, in the JAX-RPC reference implementation a WAR file also contains several files generated by the xrpcc tool: tie, servlet, and helper classes; and a server configuration file (HelloWorld_Config.properties).

To package the HelloWorld service definition, type the following:


ant package

This command creates the jaxrpc-hello.war file.

Deploying the Service Definition

To deploy the service definition, you simply copy the WAR file to Tomcat's webapps directory:


ant deploy

The first time you deploy a WAR file, Tomcat must be started. For subsequent deployments of the same WAR file, you do not need to start or restart Tomcat. Because you are about to deploy the jaxrpc-hello.war file for the first time, if Tomcat is running now, you must shut it down and then restart it.

To shut down (stop) Tomcat, type the following command in a terminal window:

UNIX:


shutdown.sh

Windows:


shutdown

To start Tomcat, type this command:

UNIX:


startup.sh

Windows:


startup

To verify that the HelloWorld service has been deployed, open a browser window and specify this URL:

http://localhost:8080/jaxrpc-hello/jaxrpc

The browser should display these lines:


A Web Service is installed at this URL. 

It supports the following ports: "HelloIF" 
(http://localhost:8080/jaxrpc-hello/jaxrpc/HelloIF)

Coding the Client

The HelloClient is a standalone program that calls the sayHello method of the HelloWorld service. It makes this call through a stub, a local object which acts as a proxy for the remote service.

In the code listing that follows, note the names of the HelloIF_Stub and HelloWorldImpl classes, which were generated by the xrpcc tool. The HelloIFprefix matches the name of the service definition interface and the HelloWorldprefix corresponds to the service name specified in the configuration file. The HelloWorldImpl class is the implementation of a service as described in the JAX-RPC Specifications. The client gets a reference to the stub by calling the getHelloIF method of HelloWorldImpl.

The parameter of the _setTargetEndpoint method is a URI that denotes the address of the target service port. For details on this URI, see Running the Client (page 316).

The source code for the HelloClient follows:


package hello; 

public class HelloClient {
    public static void main(String[] args) {
        try {
            HelloIF_Stub stub = 
                (HelloIF_Stub)(new HelloWorldImpl().getHelloIF()); 
            stub._setTargetEndpoint(args[0]); 
            System.out.println(stub.sayHello("Duke!")); 
        } catch (Exception ex) {
            ex.printStackTrace(); 
        } 
    } 
}

Compiling the Client Code

Because the client code refers to classes generated by the xrpcc tool, be sure to run the tool before compiling the client. To compile the client, type the following:


ant compile-client

Running the Client

To run the HelloClient program, type the following:


ant run

The program should display this line:


Hello Duke!

The run target executes this command:


java -classpath <cpath> hello.HelloClient <endpoint>

We created the run-hello target because the classpath includes many JAR files. (The classpath will be simplified in a later release.) The command-line parameter for the HelloClient program is the service endpoint:

http://localhost:8080/jaxrpc-hello/jaxrpc/HelloIF

The jaxrpc-hello portion of the URL is the context of the servlet that implements the HelloWorld service. This portion corresponds to the prefix of the jaxrpc-hello.war file. The jaxrpc string matches the value of the <url-pattern> element of the web.xml deployment descriptor. And finally, HelloIFis the name of the interface that defines the service.