Friday 2 August 2013

Java RMI Basics With Example

Remote Method Invocation (RMI)

RMI is a mechanism to create a distributed application or a multi-tiered application in Java. RMI allows an object to access Remote APIs in a separate server there by allowing the application to be split into separate tiers like web tier, business tier, persistence tier etc.
The details of working of RMI is covered at Working of Java RMI And Serialization
You can go through Working of Java RMI after finishing this chapter.

How to write a simple RMI application


Following are the steps for developing a simple RMI program:

(1) Create an interface for your API to be invoked remotely, extend it with java.rmi.Remote

The interface of the API that needs to be invoked should extend java.rmi.Remote for the JVM to identify itself as an interface whose methods can be invoked from another JVM.
A sample interface is given below:


package com.prasune.rmi;

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

public interface TestRemote extends Remote {

      public String execute(String message) throws RemoteException;
}



(2) Implement your Remote API and extend it with java.rmi.server.UnicastRemoteObject

We are extending Remote API Implementation with java.rmi.server.UnicastRemoteObject to make use of its constructors that export the object. Exporting a remote object makes it available for client calls by listening on a TCP port.
The exportObject method returns a Remote stub object of the acual implementation and the Remote API implementation remains in the JVM in which it was created.

package com.prasune.rmi;

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

public class TestRemoteImpl extends UnicastRemoteObject implements TestRemote {

      public TestRemoteImpl() throws RemoteException {
            super();
      }

      @Override
      public String execute(String message) throws RemoteException {
            System.out.println("Received message: " + message);
            return "Invoked remote method successfully";
      }    
}



(3) Create a RMI server class to register the remote implementation in RMI Registry

This is a class for registering the Remote API Implementation in RMI Registry so that the export method of UnicastRemoteObject makes the API available for incoming RMI client invocations.

package com.prasune.rmi.server;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;

import com.prasune.rmi.TestRemote;
import com.prasune.rmi.TestRemoteImpl;

public class TestRMIServer {

      public static void start() throws RemoteException, MalformedURLException {
            TestRemote test = new TestRemoteImpl();
            Naming.rebind("rmi://localhost:1099/TestRemoteService", test);
      }

      public static void main(String[] args) throws RemoteException,
                  MalformedURLException {
            TestRMIServer.start();
      }
}



(4) Create a RMI Client class in a separate java project, which does the look up of the remote object and access the remote API via stub. You need to copy Remote interface to the class path or copy the Remote Interface source file.

The RMI client code looks up the RMI Registry to get the Remote Object Stub registered by the server. This returns RMI stub of the implementation. The RMI client application invokes the Remote API on the stub of actual implementation.

package com.prasune.rmi.client;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import com.prasune.rmi.TestRemote;

public class TestRMIClient {

      public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
          TestRemote test = 
(TestRemote) Naming.lookup("rmi://localhost:1099/TestRemoteService");
            System.out.println(test.execute("RMI invocation"));
      }
}



(5) Compile the all the files (will happen by default if you are using an IDE)

(6) Generate Stub class by using rmic command:

You will have rmic utility in your JDK/bin.
Go to command prompt.
Got to directory in which class files are generated.
execute rmic.exe com.test.rmi.TestRemoteImpl from this location.
This will generate TestRemoteImpl_Stub.class

(7) Start the RMI Registry

You will have the RMI registry in your JDK/bin which you can make use of. The default port of RMI Registry is 1099, you can start on a port of your choice by specifying the port in rmic command. In that case, the binding URL needs to be changed accordingly.

(8) Run the Server side class

Once the registry is started, you can start the server. The RMI registry needs to know the RMI server code base to download and register RMI stub in its registry. So, if you run the RMI Server program now, you may get ClassNotFound exception for the RMI stub.

To handle this problem, set the java.rmi.server.codebase property. The property requires that a directory path be terminated with a forward slash.
Example:
-Djava.rmi.server.codebase=file:D:\TestRMI\rmi\bin\


(9) Copy the generated stub to client project class path and Run the Client side class(at another JVM)
The remote object we gets via lookup is the object of the stub class and the remote object is invoked through this stub like a local method.

Output:
The server JVM will show a print of "Received message <message you pass as parameter>".
The client JVM will show a print saying "Invoked remote method succesfully".

Now, you can go through the details of working of RMI is covered at Working of Java RMI And Serialization


No comments:

Post a Comment