Previously we explored how remote method invocation (RMI) is used to establish remote interaction, allowing programmers to concentrate on other issues besides the communications infrastructure. In this article, we'll take a look at how we implement client programs to connect with RMI servers and how we generate the runtime deployment classes for these clients.
Implementing an RMI client program
A RMI client must obtain a reference to a remote object from an RMI server's registry before methods on the remote object can be called. When working with the Java remote method protocol (JRMP), references are obtained using the lookup method of the java.rmi.Naming class.
The lookup method accepts a URL-formatted name for the remote object, including a hostname and an optional port number, along the lines of rmi://localhost/RMIServer. The remote object's stub class must be accessible using the current classpath. Once the remote stub is found, communication is established and the client program is free to call methods on the remote object as if the object were located in the client object's own JVM.
The example in Listing A does a lookup for a remote object with the name rmi://myhost/RMIExampleObject. If the remote object is found (i.e., no exceptions are thrown), the client program then proceeds to call the getMessage method on the remote object.
RMI clients and proxy objects
When creating an RMI server, you must compile the .java source files as you would any normal Java classes. However, you must then run the RMI compiler (rmic) to create client-side proxy classes and server-side proxy classes. A client-side proxy, known as a stub, forwards RMI calls to the server-side proxy, which in turn forwards the call to the actual remote object implementation. A server-side proxy is known as a skeleton when using the JRMP protocol, and as a tie when using the IIOP protocol. A server-side proxy contains methods that dispatch calls to the actual remote object implementation.
Figure A illustrates the relationships between client objects, remote objects, stubs, and skeletons/ties.
To create the server-side proxy files, you must run the rmic against the fully qualified package names of previously compiled class files containing remote object implementations. The rmic command takes one or more class names as an argument and generates class files following the pattern of RemoteObject_Skel.class and RemoteObject_Stub.class. Invoking rmic with the -iiop option generates stubs and ties that conform to the following naming convention:
The generated stub class implements exactly the same set of remote interfaces as the remote object itself. This means that a client can use the Java programming language's built-in operators for casting and type checking. It also means that remote objects written for the Java platform support true object-oriented polymorphism.
Running an RMI client
RMI client programs require no special tools or steps in order to run. Provided that the RMI server's stub classes can be located within the JVM's classpath, the client can be executed just like any ordinary Java class. Note that method calls on any remote object should be enclosed within try/catch blocks that catch objects of type java.rmi.RemoteException.