Chapter 22: Remote Method Innovation (RMI)

22.1: What is RMI

Normally a program can only call a method of an object in the same program. RMI enables a program to call the method of an object in another running program in another URL location, as if that object is in the same program.

RMI is not a brand new technology in Java. It is just an application designed using existing techniques: it uses Socket to communicate between the invoking client and the invoked server, and serializes objects to be sent through network using Object Serialization technique.

22.2: The Structure of a RMI Client-Server Relationship

There are three parts in this relationship:

* rmiregistry

It is a complete server program provided by Java, which listens on port 1099 (by default) for client connections. It is in jdk1.3\bin.

* Registered server object

To enable a server class to bind itself to the rmiregistry server and provide service to remote client invokes::

  1. The server class should implement an interface which extends interface java
  2. The server class should extend class UnicastRemoteObject
  3. Somebody should call class java
  4. Compile the server class with javac as usual, then with rmic:
   
   rmic -v1.2 pathname.classname

Suppose the server class is RmiServerImpl and is in package rmiserver:

   
   rmic -v1.2 rmiserver.RmiServerImpl

This will generate a stub class named RmiServerImpl_Stub.class, which will work on the remote client's side as a proxy to contact the server object. This stub class actually includes all the Socket and serialization facilities. It acts as a proxy between the client's program and the server object.

Then this server object will reside in rmiregistry server and ready to be invoked by remote clients.

   
   package rmiserver;
   
   import java.rmi.*;
   
   public interface RmiServer extends Remote {
       public void placeOrder() throws RemoteException;
       public void somethingElse() throws RemoteException;
   }
   
   
   package rmiserver;
   
   import java.rmi.Naming;
   import java.rmi.Remote;
   import java.rmi.RemoteException;
   import java.rmi.server.UnicastRemoteObject;
   import java.net.MalformedURLException;
   
   public class RmiServerImpl extends UnicastRemoteObject implements RmiServer {
   
       public RmiServerImpl() throws RemoteException, MalformedURLException
       {   super();   }
   
       public void somethingElse(){}
   
       public void placeOrder()
       {   System.out.println("Rmi server's placeOrder is called!");   }
   
       public static void main(String [] args) 
           throws RemoteException, MalformedURLException
       {
               RmiServerImpl server = new RmiServerImpl();
               Naming.rebind("//localhost/TakeOrder", server);
               System.out.println("RMI Server is up and running...");
       }
   }

* Remote Client

As a client, you need to have access to the interface implemented by the server object, and the stub class generated by rmic. Then it can simply connect to the remote rmiregistry server, get a handle of that interface. From now on it can call the remote server's methods through this handle as if it is in the same program.

   
   package rmiclient;
   
   import java.io.*;
   import java.rmi.*;
   import java.rmi.server.*;
   import java.net.MalformedURLException;
   import rmiserver.RmiServer;
   
   public class Client {
       public static void main(String [] argus)
       {
           try {
               RmiServer rmiServer =
                   (RmiServer)(Naming.lookup("//localhost/TakeOrder"));
               rmiServer.placeOrder();
           }
           catch(NotBoundException e)
           { }
           catch(MalformedURLException e)
           { }
           catch(RemoteException e)
           { }
       }
   }