RMI magic in 5 minutes


Nektarios, a great software architect, says that RMI is “Magic Johnson” of Java!

Indeed, Remote Method Invocation is a robust base of hot technologies like EJB and Jini. So it’s there from a world-wide bank system to the networked refrigerators of the future.

Let’s build a service that is accessible from a client on another computer = another JVM.

For this we need the following,

On the server:

  • An interface with the desired methods that are available to all clients. Let’s call it ServerRemote.
  • A concrete class that implements the desired methods. Let’s call it Server.

On the client:

  • The client class that calls the remote methods. Let’s call it Client.

A simplified view follows.

Step 1: Define the interface

The interface is the key contract between the client and the server. The client knows about the behavior (methods) available on the server through this interface. That’s very important, because

  1. The client just needs to have an interface in its classpath. (lightweight)
  2. The server may freely update the concrete implementation without having to re-distribute it to the clients. (ease of development)

Our interface must extend java.rmi.Remote.

    public interface ServerRemote extends Remote {

    }

Also any behavior defined must throw a java.rmi.RemoteException.

    public interface ServerRemote extends Remote {

        public abstract String sayHello() throws RemoteException;

    }

Here’s all the code of the server’s interface.

    import java.rmi.Remote;
    import java.rmi.RemoteException;

    /**
     * This interface defines the methods that are publicly
     * available to the remote clients.
     */
    public interface ServerRemote extends Remote {

        public abstract String sayHello() throws RemoteException;

    }

Step 2: Develop the server class

The concrete class that implements the above interface must be a UnicastRemoteObject.

    public class Server extends UnicastRemoteObject implements ServerRemote {

    }

According to the API, UnicastRemoteObject’s no-argument constructor throws a RemoteException.

    public class Server extends UnicastRemoteObject implements ServerRemote {

        protected Server() throws RemoteException {
        }

    }

We should also implement the method sayHello() defined in the interface.

    public class Server extends UnicastRemoteObject implements ServerRemote {

        protected Server() throws RemoteException {
        }

        public String sayHello() throws RemoteException {

        }

    }

Let’s say it returns the string “Hello from RMI!!”. Here’s all the code of the server class.

    import java.rmi.Remote;
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;

    /**
     * This is the concrete implementation of the server.
     * It contains the actual implementation of all methods 
     * that are available to the remote clients.
     */
    public class Server extends UnicastRemoteObject implements ServerRemote {

        protected Server() throws RemoteException {
        }

        public String sayHello() throws RemoteException {
            return "Hello from RMI!!";
        }

    }

Step 3: Deploy the server

Make a folder C:/server, copy Server.java and ServerRemote.java inside and compile them with the javac tool.

Now run the RMI compiler tool on the Server class.

This tool creates a helper class with the name Server_Stub.class.

It’s job is to handle all the communication between the client and the server. Please note that it must be in the classpath of both the client and the server.

Note: If you are using a JDK version prior to 1.6, a Server_Skeleton.class is also created. This file is on the server side only.

Now let’s initialize the RMI registry. Simply type rmiregistry on the command prompt.

So the RMI registry is up and running. Just leave this window open! We should now declare our service to the registry.

In the same folder make a simple class with just a main method.

    import java.rmi.Naming;

    /**
     * It simply declares (registers) our service to the RMI registry 
     * using JNDI.
     */
    public class RunServer {

        public static void main(String[] args) throws Exception {
            Naming.rebind("MagicJohnson", new Server());
        }

    }

Open a different command-prompt window, compile the class and run it!

So at this point we have 2 open command-prompt windows: Our service (the first window) bounded to the RMI registry (the second window).

Step 4: Develop the client

Our service has the name “MagicJohnson”. The clients can use this name to lookup our service. It’s like opening a phone-book and searching for Mr. “MagicJohnson”.

The JNDI command to search the phone-book is really simple.

    Naming.lookup("rmi://serverAddress/serviceName");
  • rmi:// is the protocol.
  • serverAddress can be the IP address of the server (e.g. 127.0.0.1), it’s hostname on the local network (e.g. mycomputer) or a DNS name (e.g. http://www.myserver.com/rmi).
  • serviceName is the JNDI name of our service, in this case “MagicJohnson”.

Make a folder C:/client and place inside

  1. the interface (ServerRemote.class)
  2. the helper class (Server_Stub.class)
  3. and the following simple class
    import java.rmi.Naming;

    /**
     * It uses JNDI to find and call our service.
     */
    public class Client {

        public static void main(String[] args) throws Exception {
            ServerRemote remote = (ServerRemote)Naming.lookup("rmi://127.0.0.1/MagicJohnson");
            System.out.println(remote.sayHello());
        }

    }

Open a command-prompt window at the client folder, compile and run it!

To try this remotely, just take the folder to another computer on the network and change 127.0.0.1 with the actual IP of the computer that RMI registry is running!

Review

  • The service available to the clients is defined in an interface.
  • This interface IS-A Remote.
  • The actual implementation of the service IS-A UnicastRemoteObject.
  • RMI uses JNDI; directory functionality like a phonebook.

On the server we need

  1. the interface
  2. the actual service, a concrete class that implements the interface
  3. the stub (generated by the JDK)
  4. the skeleton (generated by earlier JDKs)

On the client we need

  1. the interface
  2. the stub class (from the server)
  3. a simple class that calls our service

Conclusion: Just like Magic Johnson makes great passes to the hoop, RMI serves excellent technologies like EJB and Jini.

Thank you.

2 Responses to RMI magic in 5 minutes

  1. giorgos says:

    πολύ καλό blog!!!! bravo στον διαχειριστή!!!!

  2. Farzane says:

    Hi,
    I’ll be thankful if u help me about my problom
    I use NetBeans IDE6 for RMI programing, when running the program this exception appears
    Remote exception: java.rmi.ConnectException: Connection refused to host: 192.168.73.68; nested exception is:
    java.net.ConnectException: Connection refused: connect

    the code as simple as below
    import java.rmi.*;
    import java.rmi.server.*;
    import java.rmi.registry.*;

    public class SampleServerImpl extends UnicastRemoteObject
    implements SampleServer
    {
    SampleServerImpl() throws RemoteException
    {
    super();
    }

    public int sum(int a,int b) throws RemoteException
    {
    return a + b;
    }

    public static void main(String args[])
    {

    //set the security manager
    try
    {
    System.setSecurityManager(new RMISecurityManager());

    //create a local instance of the object
    SampleServerImpl Server = new SampleServerImpl();

    //put the local instance in the registry
    Registry reg = LocateRegistry.createRegistry(1097);
    Naming.rebind(“SAMPLE-SERVER” , Server);

    System.out.println(“Server waiting…..”);
    }
    catch (java.net.MalformedURLException me)
    {
    System.out.println(“Malformed URL: ” + me.toString());
    }

    catch (RemoteException re)
    {
    System.out.println(“Remote exception: ” + re.toString());
    }

    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: