Wednesday, December 24, 2003

java rmi basics

rmi stands for remote method invocation. rmi is not a sun,java name but actually a generic concept. you also have rmi in c++ by a different name.

the name suggests what rmi is supposed to do. i remotely run methods.. which is sort of a client-server app. i guess an example will explain things better. three files are required.

1. Interface
import java.rmi.*;
public interface RmiInter extends Remote{
public int add(int a, int b) throws RemoteException;
}

2. Server
import java.net.*;
import java.rmi.*;
import java.rmi.server.*;

public class RmiServer extends UnicastRemoteObject implements RmiInter {
public RmiServer() throws RemoteException{
}

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

public static void main(String arg[]){
try{
RmiServer rS = new RmiServer();
Naming.rebind("Inter",rS);
System.out.println("in Server");
}catch(RemoteException re){
}catch(MalformedURLException mue){
}
}
}

3. Client
import java.net.*;
import java.rmi.*;
public class RmiClient{
public static void main(String arg){
try{
int x;
RmiInter r = (RmiInter)Naming.lookup("Inter");
x = r.add(2,3);
System.out.println(x);

}catch(RemoteException re){
}catch(NotBoundException nbe){
}catch(MalformedURLException nbe){
}
}
}

the interface class RmiInter defines the signature/prototype of the method to be made remote and it throws a RemoteException. the server class RmiServer actually defines the method. and the Client app simply uses the method.

in RMI, the client can call code just by knowing the method as defined in the interface. the actual implementation will be on a different server class over the network. thus the client runs code as it were local though it is actually working remotely.

now some steps to make this code work. firstly java all files. then you have to
$ rmic RmiServer
this will autogenerate two files with form *_stub.class and *_skel.class. these are known as stub and skeleton classes. rmic is actually a proprietory network protocol. just like any network app, a rmi app has to pass code thru the app layer, transport layer etc. these two classes define how data is to be transferred between the client and server side. rmic basically checks all the remote methods defined and generates the two classes. the stub is on the server side and skel is on the client side. hence the client app communicates with the skel which talks over the network to the stub which to the server class. in this way the app works over the network.

another major thing in a network is a directory or naming service. as in the client should know where the server is deployed. it asks the naming service where the server is and then connects to it. so first a registry is started by
$ rmiregistry
a port is opened and rmiregistry waits and listens for connections.

the server binds to the rmiregistry in the line with a name Inter
Naming.rebind("Inter",rS);
this name is used by the client to ask for the server. now the registry knows where to redirect a client when he asks for Inter.
the client asks for Inter in the line
RmiInter r = (RmiInter)Naming.lookup("Inter");
an interface instance of RmiInter is returned by the lookup. this instance is used to call the remote methods..

the actual continued steps are
$ java RmiServer
$ java RmiClient
all will be in different shells. now the client simply returns an answer over the network. i guess remote apps don't come simpler than this.

you might ask .. where was the remote part. in a real world app my client lookup can be like this..
RmiInter rmiInter = (RmiInter)java.rmi.Naming.lookup("rmi://152.51.64.12/Inter");
notice the arg in the lookup method. rmi:// shows that the rmi app layer protocol is used. the ip add of the server and bind name is also provided. also a psedo name can be provided for the server app like Inter in this case in the naming registry. the client actually only gets the client side code, the interface and the skel class. all other code remains remote.

No comments: