4.4.4 Compiling and Running the code

In the normal way, javac is invoked to compile the java into classes. However, we then need to use the rmic compiler to generate the code which will do the packetisation and marshalling of arguments and results into a stub file. Run the following command
rmic UserIdImpl
to generate stub and skel files for the server and client respectively. Note that in java2, you can collapse the code into a single stub class, using the generic dispatch approach.

We then need to ensure that the stub classes are accessible to the rmiregistry and client, so that they can bind the correct types of clients and servers together. The recommended way of doing this is to provide a URL accessing the directory in which the files are kept. This URL can use the http protocol or, as in this example, the file protocol, since we are using the Informatics file systems. The URL for the codebase is then file:/directory/path/to/your/work/ and you pass this into the local JVM and thence to the client by setting the java.rmi.server.codebase. The directory path to your stub files and interface classes must be globally readable and excutable in the general case, since both the rmiregistry and the client JVMs have to be able to read the files.

Finally, we need to set up a security policy for the JVM. Since RMI uses a separate classloader to bring the stub files in, the security model in java 2 requires that you specify to the runtime what code loaded through this classloader can do; in this case it can connect and accept on sockets, and in particular, to the http port (note that you may need to set up environment variables indicating that the http server has to be accessed by a proxy). In addition, if you are going to use file urls, then you'll need to specify file access permissions to allow the classloader to access the directory. Create a policy file containing the following

grant {
    permission java.net.SocketPermission "*:1024-65535",
        "connect,accept";
    permission java.net.SocketPermission "*:80", "connect";
    permission java.io.FilePermission
    "/path/to/your/classdirectory/-", "read";
};
called java.policy, and when running the server, specify the java.security.policy and codebase property to the runtime by
java -Djava.security.policy=java.policy
 -Djava.rmi.server.codebase="file:/my/url/" UserIdImpl
and when running the client by
java -Djava.security.policy=java.policy UserIdClient hostname

We are now ready to run the server and the client. If you're on a PC, then you may need to start an rmiregistry instance.

rmiregistry &
Start the server first and then the client.

If you have time, add other methods or modify the signature of the sayHello method. In particular, if you are adding callbacks to the client, then the client needs to either extend UnicastRemoteObject, or better, call

UnicastRemoteObject.exportObject(this)
and also needs to make its stub files available, by setting its own java.rmi.server.codebase property. Remember tomake sure the client starts on one of the accessible ports.

Ian Wakeman 2005-02-22