Thursday, 31 December 2015

Java Remote Method invocation

Java RMI:

The Java Remote Method Invocation (RMI) system allows an object running in one Java virtual machine to invoke methods on an object running in another Java
virtual machine. RMI provides for remote communication between programs written in the Java programming language.

only supports making calls from one JVM to another. The protocol underlying this Java-only implementation is known as Java Remote Method Protocol (JRMP).

In order to support code running in a non-JVM context, a CORBA version was later developed.

RMI provides the mechanism by which the server and the client communicate and pass information back and forth

Client -->Stub-->RRL(remote reference Layer)-->Transport Layer
Server<--Skeleton<--RRL <--Transport Layer

Stub is the proxy of the Remote object at client side.
Sending objects from client to server and from server to client happens with marshaling mechanism
which actually serializes the objects and adds header to that and sends, at the receiving end Unmarshaling happens which actually re-creates the object(de-serialization) .

When a client communicates with the Server object it opens a socket for the communication

Once the server creates the Remote Object, it places the Remote object into RMI registry with the unique bind name.
//Exports the remote object to make it available to receive incoming calls, using the particular supplied port
Hello stub = (Hello) UnicastRemoteObject.exportObject(server, 0);
Registry registry = LocateRegistry.getRegistry();
//Binds a remote reference to the specified name in this registry.
registry.bind("Hello", stub);
at this point Server becomes client and Registry becomes Server and again Remote call happens between Server to Registry to store remote Object into Registry.

Client uses this bind name to look up for, to get the respective remote object and calls the Remote methods on that.

Registry registry = LocateRegistry.getRegistry();
// Returns the remote reference bound to the specified name in this registry
Hello response = (Hello) registry.lookup("Hello");


RMI Implementation

Write an Interface:

It contains all Business methods invoked by the client
The interface must extend Remote interface of RMI
all the methods must throw RemoteException


Write an Implementation Class :

Implement the above interface and extend the UnicastRemoteObject class
if not possible(i.e., if the class already extending some other class) need to export object

Server program :

Create the instance of the implementation class
place remote object into RMI Registry
ie., Naming.bind("bindName", object); (or)
Naming.rebind("bindName", object);[it is for localhost]

Naming.rebind("machineName:port:bindName",);
Client program:
Fetch the Remote object
Naming.lookup("rmi://machineNme:port/bindName");
Downcast it and invoke the method


Finally, the client invokes the sayHello method on the remote object's stub, which causes the following actions to happen:



  • The client-side runtime opens a connection to the server using the host and port information in the remote object's stub and then serializes the call data.
  • The server-side runtime accepts the incoming call, dispatches the call to the remote object, and serializes the result (the reply string ) to the client.
  • The client-side runtime receives, deserializes, and returns the result to the caller.

Code:

Interface :

package com.awf.org;

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

public interface Hello extends Remote{
String sayHello(String clientName) throws RemoteException;
}

Implementing Class and Server Program:

package com.awf.org;

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
/**
*
*this class has Interface implementation and Server program i.e., bind related stuff
*/
public class Server implements Hello {

public Server() {

}

@Override
public String sayHello(String clientName) throws RemoteException {
return "Hello " + clientName + "...!!!";
}

public static void main(String args[]) {
Server server = new Server();
try {
// Exports the remote object to make it available to receive
// incoming calls, using the particular supplied port
Hello stub = (Hello) UnicastRemoteObject.exportObject(server, 0);
Registry registry = LocateRegistry.getRegistry();
// Binds a remote reference to the specified name in this registry.
registry.bind("Hello", stub);
System.out.println("Server started...!");
} catch (RemoteException e) {
e.printStackTrace();
} catch (AlreadyBoundException e) {
// this exception occurs if we try to bind the object with the same
// bindName using registry.bind() method
// it can be avoided using Naming.rebind("bindName", object);it
// actually replaces the object
e.printStackTrace();
}
}
}

// We can also write a server class as below
public class Server extends UnicastRemoteObject implements Hello {
}
in another class
Server rmiDemoObj = new Server();//throws RemoteException
Naming.rebind("RMIDemo", rmiDemoObj);// throws MalformedURLException

Client Class:

package com.awf.org;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {

public static void main(String[] args) {

try {
Registry registry = LocateRegistry.getRegistry();
// Returns the remote reference bound to the specified name in this
// registry
Hello response = (Hello) registry.lookup("Hello");
System.out.println("Server response ::"
+ response.sayHello("Supreme"));
} catch (RemoteException | NotBoundException e) {
e.printStackTrace();
}
}
}



Running RMI application:

a)Compile interface, Implementation class, server, client classes using javac
    b)start RMI Registry using command (start rmiregistry)
    c)Run server program using below command
    the below command sets the code base which downloads the stub dinamically and client uses this stub to call remote methods.
    It opens new command prompt to display execution result of Server
start java -classpath C:\MyJavaWorld\MyExperiments\RMIApp\bin\ -Djava.rmi.server.codebase=C:\MyJavaWorld\MyExperiments\RMIApp\bin\ com.awf.org.Server
    d)open another command prompt to run the client program.
Example:
In eclipse create project RMIApp
under source create package com.awf.org
create Above classes[Hello interface, Server,Client Classes]

a)if java files are created using eclise, class files will be there under bin folder of the project bin/com/awf/org/<classfiles>

b)open a command prompt
C:\Users\IBM_ADMIN>cd C:\MyJavaWorld\MyExperiments\RMIApp\bin
C:\MyJavaWorld\MyExperiments\RMIApp\bin>start rmiregistry
[Result :This opens a new CMD to run RMI Registry]

c)C:\MyJavaWorld\MyExperiments\RMIApp\bin>start java -classpath C:\MyJavaWorld\MyE
xperiments\RMIApp\bin\ -Djava.rmi.server.codebase=C:\MyJavaWorld\MyExperiments\R
MIApp\bin\ com.awf.org.Server

[Result: opens a new command prompt and prints Server output below]
Server started...!


    d)in new CMD to run Client program
C:\MyJavaWorld\MyExperiments\RMIApp\bin>java com.awf.org.Client
Server response ::Hello Supreme...!!!




Note: Prior to J2SE 5.0 release Step c) needs to be replaced with the below
The below rmic commad is used for compiling Remote Implementation class[here its Server. We can write Implementation class and Server class separately also]
C:\MyJavaWorld\MyExperiments\RMIApp\bin>rmic com.awf.org.Server
[Result: Generates the Stub class Server_stub.class]

C:\MyJavaWorld\MyExperiments\RMIApp\bin> java com.awf.org.Server
Server started...!

No comments:

Post a Comment