Building Web Services with JAX-RPC
coauthor : Veena Gudi

In the previous chapter we took an abstract look at Web Services and technologies related with it. In this chapter we will actually translate those abstract discussions and concepts into tangible entities. The best way to do so is to develop a web service right away. Once done with it, I am sure you can better appreciate the discussion we have had in the preceding chapter.

Let us develop a simple Web Service which accepts users-name as parameter and returns a String “hello user-name”.

Following are the steps that we would have to take to build our web service

Server(Service) Side

1. At first we will have to decide on which services we are going to expose. We have already decided that. We are going to have a service that greets a user ( “hello {user-name}”).We would code the following interface so as to expose (describe) this functionality.

public interface Greet {
public String greetUser(String userName);
}

2. The next step is to write an Implementation class for this interface

public class GreetImpl extends Greet {
public String greetUser(String userName)
{
return “hello ” + userName;
}
}

3. As yet neither the interface nor Implementation class are really “Web Services ready” because none of them supports SOAP. That is to say that

a. none of them has (an interface any ways can't be expected to have) a
provision for translating JAVA objects to and from XML data types.
b. Also they do not provide any support for encapsulating XML-based RPC calls.

Thus, what immediately follows is that we will have to code a layer below the GreetImpl class that takes care of these things. We will call this layer as "The SOAP Infrastructure Layer" (This layer will in turn use some package like java.net for providing transport to the SOAP Messages).

4. Ok then! we have the interface (that lists the services we want to expose) in place. We also have its Implementation in place along with the SOAP related infrastructure (layer that does the translation of RPC calls and Data) and the transport infrastructure. By having the SOAP infrastructure we have made a provision for our service to be used by any type of client (JAVA or non-JAVA). The only thing that remains undone on the server side is creation of a document that gives a “platform neutral description” of the service. Let me re-iterate that an Interface, in general, is treated as a description of a service. This is so, since it gives you the all the information ( method signature and the return types) that you (client) need to know, to use the service. But the notion of interface used as the description of as specific to JAVA (and some other OO Languages). As we have seen in the previous chapter the true platform neutral description of a service can be given using a WSDL document.

So now we must write a WSDL document for our service. Clients that are interested will use this WSDL to understand our service.

5. With the WSDL written we are fully ready on the server side. We will now start LISTENing for RPC requests.

Client Side

6. An interested client will ask for our WSDL document which we will send down to him. The client on studying the WSDL file would know all about our service. He would mainly know about the following things

1. The name with which a particular service* identified on the server.
2. The signatures of the various services we offer. i.e. what parameters (actually type of parameters) we expect in (say) an RPC request.
3. What information would we return as response.
4. The URL of the service.

* Note : except in point 4.(above), the word “Service” refers to each method exposed by the interface. Please do not confuse it with the concept of, “Service” as defined in the WSDL 1.1 specifications.

In short it gives the client enough information so that the client knows what SOAP messages we would expect, as a REQUEST of method invocation, for each of the services we have exposed. With this information the client can now code (in its native software platform) the SOAP Infrastructure layer (with some transport layer below it). The SOAP Infrastructure layer would translate the client's RPC calls into SOAP message in a way that we expect (and have advertised in the WSDL document). Also it would do the job of un-marshaling the SOAP response and then making a suitable platform specific object/variable from it and returning it back to the invoking code.

7. Finally he will code the actual business client that will use the SOAP infrastructure layer (developed in point 6. above) to make the RPC calls. As for us, we would code our client also in JAVA though note that it wouldn't have made any difference to the steps that we have followed even if we were coding the client in some other language. The ONLY common artifact between the server and the client is a WSDL document and that is a platform neutral document. That implies that none of the sides make any assumptions about the platform used on the other side.

public class GreetClient {
public static void main(String st[])
{
GreetServiceTranslator gst = ..... // get a ref to the SOAP infrastrucure layer
String response = gst.greetUser(st[0]);
System.out.println(response);
}
}
Thats it! we already had the server Listening and now we also have the client ready. Now its just about running the client
$> java GreetClient hrishikesh
hello hrishikesh
$>

This section may have been a major disappointment for you because i did not show you the real thing. Where is the code for the “SOAP Infrastructure Layer”? Well to write that sort of a code requires detailed knowledge of specifications like WSDL (1.1)and SOAP (1.1) and which quite frankly I don't have. Most wont have ! But this shouldn't be a reason to feel panicky for it is typical in systems, developed using OO philosophy, to have programmers code only for the domain they know best and leave the support for every thing else on external libraries or frameworks. If you are wondering, that I am about to ask you to find out external support for “SOAP Infrastructure Layer”and use it, you are partly right and partly wrong. You are right because i would certainly advice use to use an external library/tool/framework or any thing like that to have your “SOAP Infrastructure Layer” in place. This is like saying, “if you are an expert in developing EJB's, stick to it, don't get into the business of writing your own Application Server. Leave it up to the Big guys (iPlanet,Oracle,BEA,IBM) etc”. I also said that you are partly wrong and thats because I don't want you to search for such a framework, i would rather introduce you to one in the next section. In the next section we will actually see a Web Service running End to End. You won't be disappointments there and thats a promise!

JAX-RPC role in webservices

Javasoft's JAX-RPC specifications enable JAVA programmer to quickly develop and deploy web services without they being required to know (at least theoretically) anything about SOAP,WSDL and other XML based technologies. In fact one of my intentions through all the preceding discussions had always been to just touch upon these technologies and not get into their syntactical or semantic details. That was the reason why until now, i have just been saying thing like “wsdl file describes a service“ but have never gone into telling you which tag in the wsdl really stands for what. Thats because as users of JAX-RPC framework you should not really care about it. You wont have to take the learning curve !

Thus JAX-RPC defines a framework that provides you with our so-called “SOAP Infrastructure Layer” shielding you totally from any efforts of knowing anything about XML and related technologies. The only thing you do is write 3 pieces of code

1. The interface
2. The Implementation class
3. the Client code
and then place these in the right slots in the framework, thats it !

For our purpose we are going to use the JAX-RPC implementation provided by SUN called Java Web Services Developer Pack - Early Access 2. Click on the link to download the same

Follow these steps

Installation

Extract the .zip file you downloaded, to a suitable directory. We would here after refer to the home directory as JWSDP_HOME.
The pack includes

1. Tomcat Web Server
2. Ant build utility.

Even if you already have these installed on your system, it is recommended that you use the ones provided with the pack so as to avoid confusion over version incompatibility. Note that in our example we won't use Ant but rather do the “build” task manually.

Development (server side)

a. The Service Definition Interface
In the previous section we had developed the Greet Interface. We will continue with that interface, with some modifications as are required in the interface for JAXRPC framework.

package edu.webservice.first;
public interface Greet extends Remote {
public String greetUser(String userName) throws RemoteException ;
}

The JAX-RPC framework calls this interface as a the “service definition interface” and requires that every “service definition interface” must

1. extends from java.rmi.Remote interface.
2. must not have constant declarations, such as public final static.
3. all methods must throw the java.rmi.RemoteException or one of its subclasses.
4. Method parameters and return types must be supported JAX-RPC types.
(See Appendix A or section 5.1 of the JAX-RPC Specifications.)

5. The methods may also throw service-specific exceptions provided Exception classes
follow the rule mentioned in Appendix A. Note that in addition to the Rules pertaining to Exceptions
stated in Appendix A
In addition, the current implementation from SUN also puts the following restriction

Service specific exceptions must have only one public constructor that
has one argument. The type of this constructor must match at least one
method which has a name that starts with get, takes no arguments, and
returns the same type as the constructor.
For example:

public class MyException extends Exception {
private MyType type;
// MyType must be a supported Type. Refer Appendix A
public MyException(MyType type) {
this.type = type;
}
public MyType getType() {
return type;
}
}

b. The Service Implementation class
The implementation remains unchanged. Note that the implementation class is not throwing the RemoteException.

package edu.webservice.first;

public class GreetImpl implements Greet {
public String greetUser(String userName)
{
return “hello ” + userName;
}
}

Now that the two classes are written we will compile them. Let us assume the following directory structure. A directory “ws” contains above 2 java files the another directory “classes”.ws may be an directory on your system and may be totally unrelated to JWSDP_HOME.

$\ws> javac *.java -d classes

"$" only signifies the path between the root and ws

Generating the Server Side Artifacts

1. Set the environment variable, JWSDP_HOME.
2. Add the all jar files in JWSDP_HOME\common\lib to your classpath.
3. Add the classes directory to the classpath

4. Add the xrpcc.bat to your path
$\ws>set path=JWSDP_HOME\bin;%PATH%

Ant does have tags set the classpath,compile code and create war files, but not all of us are well conversant with ANT, so we will take this slightly longer way. However this way you would know each step to the last detail.

The xrpcc is a tool that can take either of the two as input.

1. A Java Interface.
2. A WSDL document.

Both of these essentially do that same task, i.e. to describe the service. What's meant by describing a service .. ? well read “describing the Service” of chapter 1.Thus when xrpcc is fed with the Service Description, it can generate stubs, skeletons and other tie classes which are specific to our service. These generated classes with the help of other more general purpose classes provided in the SUN's JAX-RPC implementation do the job of broking the RPC requests and also undertake data conversion between JAVA and XML, thereby shielding us completely from knowing SOAP, WSDL etc. Thus these generated classes with other classes provided in the Sun's implementation form the “SOAP Infrastructure layer” in our application
To run the xrpcc tool we need to first create a file config.xml in the ws directory, as follows


then execute the following command

$\ws>xrpcc -classpath classes -server -d classes config.xml

-d and -classpath : have the same meaning as for java.exe
-server : generate the server side artifacts (does not generate the client
side stubs). Other options are -client, -both

This will generate all the skeleton and tie classes needed by our application. In addition it will create the following files in the classes directory MyFirstWebService.wsdl and a GreetingService_Config.properties file.

To know more about xrpcc please refer to SUN's documentation. I would strictly recommended that after you are through with this tutorial you must take a look at this documentation.


Deployment on Web Server

The implementation that we are using provides support for deploying a web service in a Servlet Container. Hence we must make a "war" file of our service and deploy it into the Tomcat server that we have in the JWSDP pack.

To do so we must first make a web.xml file and here is the code


create another directory “deployment” under ws. create a folder WEB-INF under deployment and move (cut and paste) the web.xml and GreetingService_Config.properties file in it. copy the classes folder of ws into WEB-INF


then from ws execute the following command

$\ws\deployment>jar -cvfM greet.war WEB-INF

copy the greet.war file in JWSDP_HOME\webapps folder. Run JWSDP_HOME\bin\startup.bat. The server must start without any complaints. If it does ..... well we are done !! You may stop the server for now.

Exporting the WSDL

As per the discussion we previously had, any client that feels interested in our Greeting service will now ask for the WSDL document.

In this case we ourselves, are going to code the client and that too in JAVA and so may well use the server side Interface (rather than the wsdl) to generate the client side stubs. However since I would like you to have the real feel of how XML based RPC truly decouples the server and the client side, I am going to hypnotize you and and then ask you forget somethings.

“boom... boom ... Forget that you have written the server side code..... Forget that the server side is coded in JAVA...... You know nothing about the server side.....Someone else has coded the server side in some platform and you don't know, exactly which one ....you are a client, searching for a Greeting Service......while in you quest, as you surf the internet, you come across this site that provides you with the service... you negotiate the business terms (cost of service,etc) and then request for the wsdl”

The owner of the Service email-ed you the WSDL. Note that, most generally, we need the WSDL at the design time and not at run time. Remember that using the WSDL you actually generate classes (stubs/skeletons/ties) which at run time can pass/accept SOAP messages and hence WSDL is needed at design time and not at run time.



Let use create an altogether separate directory called wsclient. Since we are assuming that we have no access to the server's code we must not make this directory within ws but at the same level as ws.

we must now copy the WSDL (MyFirstWebService.wsdl) into the wsclient directory.

Generating the client side artifacts

We know that xrpcc is a tool that can take WSDL as an input parameter and generate corresponding stubs. "For making xrpcc, accept WDSL as the input we will write to the wsclient folder a new config.xml as shown below

[1] - name ( MyFirstWebService.wsdl )
[2] - location ( .\MyFirstWebService.wsdl )
[3] - package (package in which the client wants to build the stubs. edu.webservice.client )

Now with this config.xml ready and present in wsclient we will run the xrpcc tool again this time with -client option. Before we do so create,classes directory in wsclient

$\wsclient>xrpcc -classpath classes -client -d classes config.xml

You will find the package structure (edu\webservice\client) created in the classes folder. The generated classes are client side stubs and other helper classes needed by the stub.

Writing the client code

We will now code the actual client. In this code when the client want to make an RPC it will actually instantiate the generated Stub and make a call on it. Here is the client code.

import edu.webservice.client;
public class GreetingsClient
{
public static void main(String args[])
{
GreetPort_Stub stub = (GreetPort_Stub)(new GreetingServiceImpl().getGreetPort());
stub._setTargetEndpoint(args[0]);
String strgreeting = stub.greetUser(args[1]);
System.out.println("Message is ”+strgreeting);
}
}

Even though the client code consists of just three lines, you might already be wondering about "where did these classes with such weird names came from ?".

Do you remember the files you generated in the previous section ? Take a look at those files. At a first glance you may understand nothing, at least I didn't but if you carefully look into the wsdl document, thing might just start to make some sense.

The xml structure indicates that there is some "service" and it has some "port". Now what do you mean by port and services?. Well, loosely talking a Port stands for the interface (Greet) and a service is a collection of ports. The GreetingServiceImpl is a class that represents the Service. It has methods to get you the correct stub for a Port. The GreetPort_Stub is one such stub (for port "Greet").These are the important classes that will be called from the client side. Rest of them mainly form a set of helper classes.

With this basic understanding let us review the client code again. By now the first line must be clear to you, but what does the targetEndpoint stand for?. This is the location where the service is listening. In the wsdl document the “soap:address location” gives you the information about the location of the end point. When the service vendor publishes the wsdl document, he would specify such information.

For us the endpoint is

http://localhost:8080/greet/jaxrpc/Greet

The greet portion of the URL is the context of the servlet that implements the Greeting Service (ie the name of the .war file we deployed on the server). The jaxrpc string matches the value of the <url-pattern> element of the web.xml deployment descriptor in greet.war. And finally, Greet is the name of the interface that defines the service.

Thats all and your client code is ready!!!. Once you get the stub from the service then you can invoke all your business methods that are exposed by the service interface and advertised in the wsdl document.

That means you are back to the wsdl document, now for the last time let us peep into the wsdl document. The operation tag contains the information about all the business methods that are supported. The input and output tags gives information about their parameters. Simply pick up all the method names from the operation tag with their corresponding input and output parameters and you have all the business methods with you.

For better understanding of all these tags and required input and output parameters go through the Understanding WSDL.

Run.

Compile the client code.Ensure that you have all the necessary jars in classpath. (At the most you would need all jars in JWSDP_HOME\common\lib)

1. Start the server.
2. Check the url http://local:8080/jaxrpc-Greet/jaxrpc/Greet on the browser,
It should say Greet Service deployed, else got through the server deployment steps again :(
3. run the GreetingsClient client code

$\wsclient>java edu.webservice.client.GreetingsClient http://localhost:8080/greet/jaxrpc/Greet <your name>


Table of Contents Next Previous