RMI


rmic  MyServiceImpl_Stub is  generated using rmic command run on the MyServiceImpl - MyServiceImpl_Skel will not be generated and a generic one will be used at runtime instead

skeleton and stub do the network IO  of the calls and parameters (un)marshaling

Execution

client looks up in the RMI registry for the required object 
MyService myService = (MyService) Naming.lookup("rmi://ip of server/My Shared Object");

RMI registry running on the server finds the object, returns the stub of the object to the client (client has the class file of the stub)
Client makes a method call on the object 
 myService.serve();
Skeleton on the server receives the method call and parameters, calls th method and responds back the result



Files

MyService.java : is the interface providing the signature of the service required. Every method should throw a RemoteException
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface MyService extends  Remote {

    public String getInfo(String systemProperty) throws RemoteException ;
       
        public void sayHello() throws RemoteException ;   
}

MyServiceImpl.java : is the actual implementation of the services declared in MyService
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class MyServiceImpl extends UnicastRemoteObject implements MyService {

public static String testString = "test String value";

    protected MyServiceImpl() throws RemoteException {
        super();
    }

    @Override
    public String getInfo(String systemProperty) {
        return "System Property("+systemProperty+"): "+System.getProperty(systemProperty);
    }

        public void sayHello(){
                System.out.println("Hi!");
        }

    public static void main(String[] args) {
        try {
            MyServiceImpl myServiceImpl = new MyServiceImpl();
           

            Naming.rebind("MyRemoteObject", myServiceImpl);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

Client.java
import java.rmi.*;

public class Client {

    public static void main(String[] args) {

        try {
            MyService service = (MyService) Naming
                    .lookup("rmi://192.168.0.90/MyRemoteObject");           

            service.sayHello();
           
            String s = null;
            s = service.getInfo("os.name");
           
            System.out.println(s);
           
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

----

Make the Required Class Files

All the three files mentioned above at a same directory:
$ javac MyServiceImpl.java   // will create MyServiceImpl.class, MyService.class
$ rmic MyServiceImpl    // will create
$ javac Client.java

Put .Class Files at Proper Machines

On Server Machine

MyService.class
MyServiceImpl.class
MyServiceImpl_Stub.class

On Client Machine

Client.class
MyService.class
MyServiceImpl_Stub.class

To Run

On Server Machine

$ rmiregistry    // run as a process in the server machine

$ java -Djava.rmi.server.hostname=192.168.0.90 MyServiceImpl   //put the ip address of the server there before running the server

On Client Machine

$ java Client.java  // Here it works!

To avoid lots of method calls for an object (which performs remotely and returns the result by RMI) have a method in the object to return theobject itself. since the object is serialized all its content will be transfered once and other subsequent calls will be local) - Meanwhile the content of the object might become stale, so you should trade-off between network calls or less updated data.















Subpages (1): Jini
Comments