Previous | Next | Trail Map | RMI | Using Java RMI

Running the Example Programs

A Note About Security

The JDK1.2 security model is more sophisticated than the model used for JDK1.1. JDK1.2 contains enhancements for finer-grained security and requires code to be granted specific permissions to be allowed to perform certain operations.

In JDK1.1, code in the class path is trusted and can perform any operation; downloaded code is governed by the rules of the installed security manager. If you run this example in JDK1.2, you need to specify a policy file when you run your server and client. Here is a general policy file that allows downloaded code, from any codebase, to do two things:

grant {
    permission java.net.SocketPermission "*:1024-65535", 		
        "connect,accept";
    permission java.net.SocketPermission "*:80", "connect";
};
If you make your code available for downloading via HTTP URLs, you should use the policy file above when you run this example. However, if you use file URLs instead, you can use the policy file below. Note that in Windows-style file names, the backslash character needs to be represented by two backslash characters in the policy file.
grant {
    permission java.net.SocketPermission "*:1024-65535", 		
        "connect,accept";
    permission java.io.FilePermission 
        "c:\\home\\ann\\public_html\\classes\\-", "read";
    permission java.io.FilePermission 
        "c:\\home\\jones\\public_html\\classes\\-", "read";
};

This example assumes that the policy file is called java.policy and contains the appropriate permissions. If you run this example on JDK1.1, you will not need to use a policy file, since the RMISecurityManager provides all the protection you need.

Starting the Server

Before starting the compute engine, you need to start RMI's registry with the rmiregistry command. As discussed earlier in this chapter, the RMI registry is a simple server-side bootstrap naming facility that allows remote clients to get a reference to a remote object.

Note that before you start the rmiregistry, you must make sure that the shell or window in which you will run rmiregistry either has no CLASSPATH environment variable set or has a CLASSPATH environment variable that does not include the path to any classes, including the stubs for your remote object implementation classes, that you want downloaded to clients of your remote objects.

If you do start the rmiregistry and it can find your stub classes in through CLASSPATH, it will not remember that the loaded stub class can be loaded from your server's codebase (that was specified by the java.rmi.server.codebase property when you started up your server application). As a result, the rmiregistry will not convey to clients the true codebase associated with the stub class, and consequently, your clients will not be able to locate and load the stub class (or other server-side classes).

To start the registry on the server, execute the rmiregistry command. This command produces no output and is typically run in the background.


Platform-Specific Details: Starting the Registry on Default Port on Host zaphod

Windows (use javaw if start is not available):

unset CLASSPATH
start rmiregistry

UNIX:

unsetenv CLASSPATH
rmiregistry &

The registry, by default, runs on port 1099. To start the registry on a different port, specify the port number on the command line. Don't forget to unset your CLASSPATH.

Platform-Specific Details: Starting the Registry on Port 2001

Windows:

start rmiregistry 2001

UNIX:

rmiregistry 2001 &

Once the registry is started, you can start the server. First, you need to make sure that both the compute.jar file and the remote object implementation class (since that is what you are starting) are in your class path.


Platform-Specific Details: Setting the CLASSPATH Environment Variable

Windows:

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

When you start the compute engine, you need to specify, using the java.rmi.server.codebase property, where the server's classes will be made available. In this example, the server-side classes to be made available for downloading are the ComputeEngine's stub and the Compute and Task interfaces, available in ann's public_html\classes directory.


Platform-Specific Details: Starting the Compute Engine on Host zaphod

Windows:

java -Djava.rmi.server.codebase=file:/c:\home\ann\public_html\classes/
     -Djava.rmi.server.hostname=zaphod.east.sun.com
     -Djava.security.policy=java.policy
         engine.ComputeEngine

UNIX:

java -Djava.rmi.server.codebase=http://zaphod/~ann/classes/
     -Djava.rmi.server.hostname=zaphod.east.sun.com
     -Djava.security.policy=java.policy
         engine.ComputeEngine

The java command above defines several properties:

The ComputeEngine's stub class is dynamically loaded into a client's virtual machine only when the class is not already available locally and the java.rmi.server.codebase property has been set properly, to the network-accessible location of the stub class, when the server is started. Once such a stub is loaded, it will not need to be re-loaded for additional references to ComputeEngine's objects.

Starting the Client

Once the registry and engine are running, you can start the client, specifying:

First set the CLASSPATH to see jones's client and the JAR file containing the interfaces. Then start the client as follows:


Platform-Specific Details: Starting the Client on Host ford

Windows:

set CLASSPATH c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar
java -Djava.rmi.server.codebase=file:/c:\home\jones\public_html\classes/
     -Djava.security.policy=java.policy
        client.ComputePi localhost 20

UNIX:

setenv CLASSAPTH /home/jones/src:/home/jones/public_html/classes/compute.jar
java -Djava.rmi.server.codebase=http://ford/~jones/classes/
     -Djava.security.policy=java.policy 
        client.ComputePi zaphod.east.sun.com 20

Note that the class path is set on the command line so that the interpreter can find jones's client and the JAR file containing the interfaces.

After starting the client, you should see the following output on your display:

3.14159265358979323846

The figure below illustrates where the rmiregistry, the ComputeEngine server and the ComputePi client obtain classes during program execution.

The rmiregistry, ComputeEngine server and ComputePi obtaining classes during program execution.

When the ComputeEngine server binds its remote object reference in the registry, the registry downloads the ComputeEngine_Stub, as well as the Compute and Task interfaces on which the stub class depends. These classes are downloaded from the ComputeEngine's web server (or file system, as the case may be).

The ComputePi client loads the ComputeEngine_Stub, also from the ComputeEngine's web server, as a result of the Naming.lookup call. Since the ComputePi client has both the Compute and Task interfaces available in its class path, those classes are loaded from the class path, not the remote location.

Finally, the Pi class is loaded into the ComputeEngine's virtual machine when the Pi object is passed in the executeTask remote call to the ComputeEngine object. The Pi class is loaded from the client's web server.


Previous | Next | Trail Map | RMI | Using Java RMI