What is RMI?
- Introduction
- Remote Interfaces
- Implementing the remote interface
- Set up the registry
- Create the Stubs and the Skeletons
- 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