Sunday, March 22, 2009

RMI

Here is a short summary about RMI. A simple example can be found in my post here.

A RMI based application has the following minimum pieces:

1. RemoteInterface (import java.rmi.*;)

- Defines the interface.
- The interface extends java.rmi.Remote and declares remote methods.
- Each remote method throws java.rmi.RemoteException.


public interface RemoteInterface extends Remote {
public String concat(String s1, String s2) throws RemoteException;
}



2. Implementation of the RemoteInterface (import java.rmi.*;)

- Implements all methods of remote interface.
- Has a constructor which throws RemoteException


public class RemoteInterfaceImpl implements RemoteInterface{
//Has constructor which throws RemoteException
public RemoteInterfaceImpl() throws RemoteException{
}
//Implements all methods of the RemoteInterface
public String concat(String s1, String s2) throws RemoteException{
.....
}
}



3. The server (import java.rmi.registry.*; import java.rmi.*;)

- Creates and exports the remote objects.
- Gets handle to the RMI registry. (It runs at default port 1099.
if you start at a different port specify port when trying to get registry).
- Bind/register the remote object stubs with the registry.


public class Server {
public static void main(String[] args) {
try {
RemoteInterfaceImpl rii = new RemoteInterfaceImpl();
RemoteInterface stub = UnicastRemoteObject.exportObject(rii, 0);

Registry registry = LocateRegsitry.getRegistry();
registry.bind("concat", stub);

catch(RemoteException e) {
.....
}
}
}



4. Client (import java.rmi.registry.*;)

- Do following:

1. Get the stub to the registry on the remote host.If registry running on different port provide it too.
Registry registry = LocateRegistry.getRegistry(host);


2. Lookup the remote object's stub using its name in the registry.
ri = (RemoteInterface)registry.lookup("concat");

3. Invoke the methods on the remote object using the stub.
String c = ri.concat("1","2");

where

concat is a method defined in the RemoteInterface
The object returned or method parameters must be Serializable (Remember: String class implements Seriableable)
RemoteException must be caught and do something valuable with it.




5.Running them

- Compile source files using javac.
- start the rmiregistry. (uses port 1099 by default).
- start the server.
- start the client.


More on RMI:


Here are a few high level things to remember about RMI:

Passing parameters in RMI

RMI deals with 3 types of parameters:

- Primitive paramters: Always passed by value. Copy is made and sent across.
- Object parameters: A copy of the object itself is made and sent across. Note, the reference to the object is not passed the object itself is passed. The object should be Serializable. If the object is composed of other objects, they are also sent across, so they must also be Serializable.
- Remote Object parameters: The remote object parameter is substituted with the remote proxy/stub and sent across.

 

Garbage collection of remote objects:

- It is done using Distributed Garbage Collection and reference counting.
- When the client creates a remote reference, it lets the server side know this by calling dirty() on the Distributed Garbage Collector(DGC) of the server.
- The client keeps renewing the lease periodically on the remote reference by calling dirty().
- Once the client is done with the remote reference(GCed on the client), the client calls clean() on th server-side DGC, indicating that the server-side DGC no longer needs to keep the remote object alive for this client
- The server-side DGC keeps track of all its remote references and does not GC them and if they are being used.


rmiregistry:

- RMIRegistry is purely for bootstraping purposes, so that clients can get a remote object stub. If the client can get a remote object stub through another mechanism then the rmiregistry is not needed.
- rmiregistry and server can run on different machines but sometimes the registry may give AccessException if you try to bind from non local host.I have never tried this, so cannot provide more insight on this.
- You can also create the registry from within your code using createRegistry() API.If you do this, you dont have to explicity start the rmiregistry, it is started when the server is started.
Registry registry = LocateRegistry.createRegistry(port);



Exporting Objects:

- UnicastRemoteObject.exportObject(), exports the remote object receive incoming remote invocation by making it listen on an anonymous TCP port in the machine.
- It returns a stub to the remote object which has the info on the port on which the remote object is listening.
- This remote object stub is returned to the client when it does a lookup on the rmiregistry. Now the client through the remote stub knows how to contact and call methods on the remote object.


RMI stubs:

- rmic is no longer required to generate stub post 1.5. stub classes are generated at runtime.
- When a stub's method is invoked, it does the following:

- initiates a connection with the remote JVM containing the remote object,
- marshals (writes into byte stream and transmits) the parameters to the remote JVM,
- waits for the result of the method invocation,
- unmarshals (reads) the return value or exception returned, and
- returns the value to the caller.


 

No comments:

Post a Comment