The Java TM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: RMI
Lesson: Using Java RMI

## Compiling the Example Programs

> In a real-world scenario in which a service like the compute engine is deployed, a developer would likely create a JAR (Java ARchive) file that contains the `Compute` and `Task` interfaces for server classes to implement and client program to use. Next, a developer, perhaps the same developer of the interface JAR file, would write an implementation of the `Compute` interface and deploy that service on a machine available to clients. Developers of client programs can use the `Compute` and the `Task` interfaces, contained in the JAR file, and independently develop a task and client program that uses a `Compute` service.

> In this section you learn how to set up the JAR file, server classes, and client classes. You will see that the client's `Pi` class will be downloaded to the server at runtime. Also, the `ComputeEngine`'s remote stub will be downloaded from the server to the client at runtime.

> The example separates the interfaces, remote object implementation, and client code into three packages:

> - `compute` ( `Compute` and `Task` interfaces)
> - `engine` ( `ComputeEngine` implementation class and its stub)
> - `client` ( `ComputePi` client code and `Pi` task implementation)

> Let's first build the interface JAR file to provide to server and client developers.

### Build a JAR File of Interface Classes

> First, you need to compile the interface source files in the `compute` package and then build a JAR file that contains their class files. Let's suppose a user, `waldo`, has written these particular interfaces and has placed the source files in `c:\home\waldo\src\compute` (on UNIX:`/home/waldo/src/compute`). Given these paths, you can use the following commands to compile the interfaces and create the JAR file.

> > Win32:

> >       cd c:\home\waldo\src
> >       javac compute\Compute.java
> >       javac compute\Task.java
> >       jar cvf compute.jar compute\*.class

> > UNIX:

> >       cd /home/waldo/src
> >       javac compute/Compute.java
> >       javac compute/Task.java
> >       jar cvf compute.jar compute/*.class

> The `jar` command displays the following output (due to the `-v` option):

> >     added manifest
> >     adding: compute/Compute.class (in=281) (out=196)
> >         	(deflated 30%)
> >     adding: compute/Task.class (in=200) (out=164)
> >         	(deflated 18%)

> Now you can distribute the `compute.jar` file to developers of server and client applications so that they can make use of the interfaces.

> When you build either server- or client-side classes with the `javac` and `rmic` compilers, you generally need to specify where the resulting class files should reside so that they are network accessible. In this example this location is, for UNIX, `/home/user/public_html/classes`, because some web servers allow accessing a user's `public_html` directory via an HTTP URL constructed as `http://host/~user/`. If your web server does not support this convention, you could use a file URL instead. The file URLs take the form `file:/home/user/public_html/classes/` on UNIX or, on the Win32 platform, `file:/c:/home/user/public_html/classes/`. You may also select another type of URL, as appropriate.

> The network accessibility of the class files allows the RMI runtime to download code when needed. Rather than defining its own protocol for code downloading, RMI uses URL protocols supported by the Java platform (for example, HTTP) to download code. Note that a full, heavyweight web server is not needed to accomplish this downloading of class files. In fact, a simple HTTP server that provides all of the functionality needed to make classes available for downloading in RMI via HTTP can be found at ftp://java.sun.com/pub/jdk1.1/rmi/class-server.zip.

### Build the Server Classes

> The `engine` package contains only one server-side implementation class, `Com-puteEngine`, the remote object implementation of the `Compute` interface. Since `ComputeEngine` is an implementation of a remote interface, you need to generate a stub for the remote object so that clients can contact the remote object.

> Let's say that `ann`, the developer of the `ComputeEngine` class, has placed `ComputeEngine.java` in the `c:\home\ann\src\engine` directory and is deploying the class files for clients to use in a subdirectory of her `public_html` directory, `c:\home\ann\public_html\classes` (on UNIX that would be `/home/ann/public_html/classes`, accessible via some web servers as `http://host/~ann/classes/`).

> Now let's assume that the `compute.jar` file is located in the directory `c:\home\ann\public_html\classes`. To compile the `ComputeEngine` class, your class path must include the `compute.jar` file and the source directory itself.

> > Note: Normally we recommend that you set the class path on the command line, using the `-classpath` option. However, for several compounding reasons this example uses the `CLASSPATH` environment variable, because both `javac` and `rmic` require a class path and the `-classpath` option is treated differently in JDK 1.1 and JDK 1.2. For detailed information on `CLASSPATH` refer to:

> > Solaris:
> > http://java.sun.com/products/jdk/1.2/docs/tooldocs/solaris/classpath.html

> > Win32:
> > http://java.sun.com/products/jdk/1.2/docs/tooldocs/win32/classpath.html

> > We recommend that you do not set `CLASSPATH` in a login or startup file and that you remember to unset it when you're finished working with this example.

> Here's how to set the `CLASSPATH` environment variable

> > Win32:

> >     set CLASSPATH=c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar

> > UNIX:

> >     setenv CLASSPATH /home/ann/src:/home/ann/public_html/classes/compute.jar

> Now you compile the `ComputeEngine.java` source file, generate a stub for the `ComputeEngine` class, and make that stub network accessible. To create stub (and optionally skeleton files), run the `rmic` compiler on the fully qualified class names of the remote object implementations that must be found in the class path. The `rmic` command takes one or more class names as input and produces as output class files of the form `ClassName_Stub.class` and `ClassName_Skel.class`. A skeleton file will not be generated if you run `rmic` with the `-v1.2` option. This option should be used only if all of your clients will be running JDK 1.2 or compatible versions.

> > Win32:

> >       cd c:\home\ann\src
> >       javac engine\ComputeEngine.java
> >       rmic -d . engine.ComputeEngine
> >       mkdir c:\home\ann\public_html\classes\engine
> >       cp engine\ComputeEngine_*.class
> >           c:\home\ann\public_html\classes\engine

> > UNIX:

> >       cd /home/ann/src
> >       javac engine/ComputeEngine.java
> >       rmic -d . engine.ComputeEngine
> >       mkdir /home/ann/public_html/classes/engine
> >       cp engine/ComputeEngine_*.class
> >           /home/ann/public_html/classes/engine

> The `-d` option tells the `rmic` compiler to place the generated class files, `ComputeEngine_Stub.class` and `ComputeEngine_Skel.class`, in the directory c:`\home\ann\src\engine`. You also need to make the stubs and the skeletons network accessible, so you must copy the stub and the skeleton class to the area: `public_html\classes`.

> Since the `ComputeEngine`'s stub implements the `Compute` interface, which refers to the `Task` interface, you need to make these two interface class files network accessible along with the stub. So the final step is to unpack the `compute.jar` file in the directory `c:\home\ann\public_html\classes` to make the `Compute` and the `Task` interfaces available for downloading.

> > Win32:

> >       cd c:\home\ann\public_html\classes
> >       jar xvf compute.jar

> > UNIX:

> >       cd /home/ann/public_html/classes
> >       jar xvf compute.jar

> The `jar` command displays the following output:

> >     created: META-INF/
> >     extracted: META-INF/MANIFEST.MF
> >     extracted: compute/Compute.class
> >     extracted: compute/Task.class

> Now the compute engine is ready to deploy. You could do that now or wait until after you have built the client. While we are on a building spree, let's build the client-side program next.

### Build the Client Classes

> Let's assume that user `jones` has created the client code in the directory `c:\home\jones\src\client` and will deploy the `Pi` class, so that it can be downloaded to the compute engine, in the network-accessible directory`c:\home\jones\public_html\classes`, also available via some web servers as `http://host/~jones/classes/`. The two client-side classes are contained in the files `Pi.java` and `ComputePi.java` in the `client` subdirectory.

> In order to build the client code, you need the `compute.jar` file that contains the `Compute` and the `Task` interfaces that the client uses. Let's say that the `compute.jar` file is located in `c:\home\jones\public_html\classes`. The client classes can be built as follows:

> > Win32:

> >       set CLASSPATH=c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar
> >       cd c:\home\jones\src
> >       javac client\ComputePi.java
> >       javac -d c:\home\jones\public_html\classes client\Pi.java

> > UNIX:

> >       setenv CLASSPATH /home/jones/src:/home/jones/public_html/classes/compute.jar
> >       cd /home/jones/src
> >       javac client/ComputePi.java
> >       javac -d /home/jones/public_html/classes client/Pi.java

> Only the `Pi` class needs to be placed in the directory `public_html\classes\
> client`. (The `client` directory is created by `javac` if it does not exist.) The reason is that only the `Pi` class needs to be available for downloading to the compute engine's virtual machine. Now you can run the server and then the client.

| Start of Tutorial > Start of Trail > Start of Lesson | Search