Hello World Web Service

This is a simple example that will show you how to develop a Web Service client and service starting from a Java remote interface (RMI). The development process can roughly be divided into the following steps:
  1. Write the remote Java interface for the service.
  2. Compile the interface.
  3. Create stubs and skeletons using the rmi2soapcompiler.
  4. Implement the client.
  5. Implement the server.
  6. Deploy the server in a servlet container.
  7. Run the client against the server.
The build process is conveniently represented in the build.sh and build.bat files, which are included with each example. Before running the build scripts, you need to setup your environment as stated in the README. You can use the env.bat, env.sh, or env.csh file to easily set up your build environment.

1 Hello Remote Interface

Below is the RMI for the Hello World Application. The Hello interface has one method, sayHello which takes no parameters and returns a string. The RMI serves as a contract between the object implementation and its clients.
package hello;
                                                                           
import java.rmi.Remote;
import java.rmi.RemoteException;
                                                                           
public interface Hello extends Remote
{
    String sayHello() throws RemoteException;
}

2 Compiling the Interface

We'll use the target directory WEB-INF/classes, since this directory structure is necessary when creating the servlet WAR file later. If the directory doesn't already exist, use the following commands to create it:
mkdir WEB-INF

cd WEB-INF
mkdir classes
Then compile the interface using the familiar javac compiler. On UNIX systems:
javac -d WEB-INF/classes Hello.java
On Windows systems:
javac -d WEB-INF\classes Hello.java

3 Generating the SOAP Bindings

Before generating the SOAP bindings, you must have the classes directory available in the CLASSPATH. Set your CLASSPATH as follows (depending on operating system and shell):
set CLASSPATH=WEB-INF/classes:$CLASSPATH
Also, ensure that the Novell exteNd WSSDK binaries are in your PATH. Adapt the below examples to fit the location where you installed Novell exteNd WSSDK on your system. On Unix (bash):
export PATH=/usr/local/wssdk/bin/solaris;$PATH
On Windows:
set PATH=C:\wssdk\bin\win32;%PATH%
Finally, you must ensure that the Servlet library is in your CLASSPATH. If you're using Tomcat you might do:
set CLASSPATH=%CLASSPATH%;C:\jakarta-tomcat-4.0.1\lib\servlet.jar
Run the
rmi2soap compiler on the Hello.class file to generate the SOAP bindings from the above Java remote interface.
rmi2soap -d WEB-INF/classes hello.Hello
The rmi2soap compiler generates the Java code to the WEB-INF/classes directory, and compiles the generated Java code to the same directory. The following classes are created in the hello Java package:
 
Hello_Stub.class // stub
_Hello_ServiceSkeleton.class // inheritance based skeleton
_Hello_ServiceTieSkeleton.class // delegation based skeleton
HelloService.class // service interface
HelloServiceImpl.class // service implementation class

You can run rmi2soap with the -keep flag if you wish to keep the source files for the stubs and skeletons. Please consult the rmi2soap man page for a detailed description of the command line flags.

4 Implementing the Client

The client implementation uses JNDI to lookup the service object. The service can in turn be used to create a stub for the remote service. The source for the client is shown below:
package hello;
                                                                           
import javax.xml.rpc.Stub;
import javax.naming.InitialContext;
                                                                           
public class Client
{
    public static void main(String[] args) throws Exception
    {
    |   // get the initial context
    |   InitialContext ctx = new InitialContext();
    |                                                                      
    |   // lookup the service for Hello
    |   HelloService svc = (HelloService)
    |       ctx.lookup("xmlrpc:soap:hello.HelloService");
    |                                                                      
    |   // get the hello stub
    |   Hello hello = (Hello) svc.getHelloPort();
    |                                                                      
    |   // set the end point address
    |   ((Stub)hello)._setProperty("javax.xml.rpc.service.endpoint.address",
    |       args.length > 0 ? args[0] :"http://localhost:9090/hello");
    |                                                                      
    |   // invoke the service
    |   System.out.println(hello.sayHello());
    }
}
The preferred way to set an end point address on the stub is to use the javax.xml.rpc.service.endpoint.address property. Once you're done you can compile the client part of your Web Service:
javac -d WEB-INF/classes Client.java

5 Implementing the Server

The server implementation is much as if you were implementing any other Java interface. The server implementation class must extend the _Hello_Skeleton class. In this case the server is very simple as shown below:
package hello;
                                                                           
import java.rmi.Remote;
import java.rmi.RemoteException;
                                                                           
public class HelloImpl extends Hello_ServiceSkeleton
{
    public String sayHello() throws RemoteException
    {
    |   return "Hello World!";
    }
}
Once you're done you can compile the server part of your Web Service:
javac -d WEB-INF/classes HelloImpl.java

6 Deploying the Server

You can now create a WAR file and deploy the server in your favorite servlet container. Before creating the WAR you need to supply a standard web.xml file, which must be located in the WEB-INF directory. Please consult the one in the hello directory for an example. Then create the WAR as follows:
jar -cfM services.war WEB-INF
If you're using Tomcat, you can copy the services.war file into the Tomcat webapps directory and restart Tomcat. Then you're ready to run the client and test the Hello World application.

As an alternative to using a servlet container, you can use the simple Web Server that ships with Novell exteNd WSSDK. You can start jwebserv like this:

jwebserv -verbose services.war
For a full description of how to use the Novell exteNd WSSDK Server, please look
here.

7 Running the Client

Running the client is now straightforward. If you're using jwebserv you can run the client without any arguments, as http://localhost:9090/hello is the default binding. Below is the command line to run against Tomcat:
java hello.Client http://localhost:8080/services/hello
The client program will print "Hello World!".

You can now use the tunnel tool to inspect what goes over the wire. Run the tunnel on port 9999 like this:

tcptunnel 9999 localhost 9090
In the above command line 9999 is the tunnel port and 9090 is the port where you Web Service is running (note the default is 8080 for Tomcat). After running this command you should see a window with two panels.

You now need to run the client again through the tunnel:

java hello.Client http://localhost:9999/hello
What goes over the HTTP connection to the servlet container is the following SOAP message:
 
<Envelope
 xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'
 xmlns='http://schemas.xmlsoap.org/soap/envelope/'
 xmlns:xsd='http://www.w3.org/1999/XMLSchema'
 xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance'
 xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'>
 <Body>
  <ns1:sayHello SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
   xmlns:ns1='http://www.hello'>
  </ns1:sayHello>
 </Body>
</Envelope>
Figure 1: The SOAP message going from client to server in Hello World.

And below is the SOAP response message coming back from the server:

<Envelope
 xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'
 xmlns='http://schemas.xmlsoap.org/soap/envelope/'
 xmlns:xsd='http://www.w3.org/1999/XMLSchema'
 xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance'
 xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'>
 <Body>
  <ns1:sayHelloResponse SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
   xmlns:ns1='http://www.hello'>
   <result xsi:type='xsd:string'>Hello World!</result>
  </ns1:sayHelloResponse>
 </Body>
</Envelope>
Figure 2: The SOAP message going from server back to client in Hello World.
Copyright © 2000-2003, Novell, Inc. All rights reserved.