What is RMI?
  1. Introduction
  2. Remote Interfaces
  3. Implementing the remote interface
  4. Set up the registry
  5. Create the Stubs and the Skeletons
  6. Using the remote object








Introduction
Java1.1 Remote Method Invocation allows you to send a message to some objects living on another machine and get a result as if the object lived on your local machine.
Let we see how to create our own RMI objects.



Remote Interfaces
When you create a remote object, you mask the underlying implementation by passing around an interface. Thus, when the client gets a handle to a remote object, what they really get is an interface handle, which happens to connect to some local stub code which itself talks across the network.
But you don't think about this, you just send messages via your interface handle.
When you create a remote interface, you must follow these guidelines:
1. The remote interface must be public.
2. The remote interface must extend the interface java.rmi.Remote
3. Each method in the remote interface must declare java.rmi.RemoteException in its throws clause, in addition to any application-specific exceptions.
4. A remote object passed as an argument or return value (either directly or embedded within a local object) must be declared as the remote interface, not the implementation class.


See for example:
InterCS.java
InterSMO.java
InterCCRead.java
InterCCWrite.java



Implementing the remote interface
The server must contain a class that extends UnicastRemoteObject and implements the remote interface. This class may also have additional methods, but only the methods in the remote interface will be available to the client, of course, since the client will get only a handle to the interface, not the actual class that implements it.
You must explicitely define the constructor for the remote object, even if you are only defining a default constructor that just calls the base-class constructor.
See for example:
TheServer.java
RServer.java
SMO.java



Set up the registry
In the server codes, you see a call to the static method Naming.bind().
However, this call requires that the registry be running as a separate process on the computer.
The name of the register server is rmiregistry, and to start it in the background on UNIX you say:
rmiregistry &
Like many network programs, the rmiregistry is located at the IP address of whatever machine started it up, but it must also be listening at a port.
If you invoke the rmiregistry as above, with no arguments, the registry's port will default to 1099.
If you want it to be at some other port, you add an argument at the command line to specify the port.
The information about the port must also be given to the bind() command, as well as the IP address of the machine where the registry is located. But this brings up some problem if you're expecting to test RMI programs locally.
In the JDK1.1.1 release, there a couple of problems:
- localhost does not work with RMI. Thus, to experiment with RMI on a single machine, you must provide the actual name of the machine.
- RMI will not work unless your computer has an active TCP/IP connection, even if all your components are just talking to each other on the local machine.
This means you must connect to your Internet service provider before trying to run the program.
The bind() command becomes:
Naming.bind("//machine_name/TheServer", service_name);
In a future release of JDK (after 1.1) when the localhost bug is fixed, you will be able to perform local testing by leaving off the IP address and only putting in the identifier:
Naming.bind("TheServer", service_name);
The name of the service is arbitrary; it happens to be TheServer here, just like the name of the class, but you could call it anything you want.
The important thing is that it's a unique name in the registry that the client knows to look for to procure the remote object. If the name is already in the registry, you'll get an AlreadyBoundException.
To prevent this, you can always use rebind() either adds a new entry or replaces the one that's already there.
Even though main() exits, your object has been created and registered so it's kept alive by the registry, waiting for a client to come along and request it. As long as the rmiregistry is running, the object will be there. For this reason, when you're developing your code you need to shut down the rmiregistry and restart it when you compile a new version of your remote object.



Create the Stubs and the Skeletons
You must create the stubs and the skeletons that provide the network connection operations and allow you to pretend that the remote object is just another local object on your machine.
You invoke the rmic tool on your compiled code, and it creates the necessary files.
Note: the rmic tool is particular about packages and classpaths.
You don't have to be in the directory containing TheServer.class when you execute this command, but the results will be placed in the current directory.
When rmic runs successfully, you'll have two new classes in the directory:
- TheServer_Stub.class
- TheServer_Skel.class.

Now you're ready to get the server and client to talk to each other.



Using the remote object
The whole point of RMI is to make the use of remote objects very simple.
The only extra thing you must do in your client program is to look up and fetch the remote interface from the server. From then on, it's just regular java programming: sending messages to objects.
See for example:
TheClient.java

The ID string is the same as the one used to register the object with Naming, and the first part represents the URL and port number.
Since you're using a URL, you can also specify a machine on the Internet.
What comes back from Naming.lookup() must be cast to the remote interface, not the class itself.








GO TO THE TOP