RMI


RMI is a mechanism through which we can call remote methods as though they were residing on your own machine. This whole process will look transparent to the end user: if I showed you a live demo and didn't tell you it was RMI, then you wouldn't have even realized the method is actually being called from a different machine. Of course, a Java Virtual Machine must be present on both the machines.

Objects which have to be made available to other machines have to be exported to something called a Remote Registry Server so that they can be invoked. So if Machine A wants to call methods of some object on Machine B, then Machine B would have to export that object on its Remote Registry Server. Remote Registry Server is a service that runs on the server and helps client’s search and access objects on the server remotely. Now, if an object has to be capable of being exported then it must implement the Remote Interface present in the RMI package. For example, say that you want an object Xyz on machine A to be available for remote method invocation, then it must implement the Remote interface.

RMI uses something called a stub and a skeleton. The stub is present on the client side, and the skeleton the server side. When you call remote methods, you don't just go directly to other machine and say "hey, here's the method name, here are the parameters, just give me back what has to be returned and I am out of here".

There are a number of events that have to take place beforehand which help in the communication of the data. The stub is like a local object on the client side, which acts like a proxy of the object on the server side. It provides the methods to the client which can be invoked on the server. The Stub then sends the method call to the Skeleton, which is present on the server side. The Skeleton then implements the method on the server side.

The Stub and the Skeleton communicate with each other through something called a Remote Reference Layer. This layer gives the stub and skeleton the capability to send data using the TCP/IP protocol. Let's take a quick look at a simple technique called "Binding".

Whenever a client wants to make a reference to any object on the server, have you thought how he would tell the server what object he wants to create? Well, this is where this concept of "Binding" comes in. On the server end we associate a string variable with an object (we have methods to do this. We will learn more about these when we start coding). The client tells the server what object he wants to create by passing that string to the server, thus letting the server know exactly what object you are talking about. All of these strings and objects are stored in the Remote Registry Server on the server.

Make your project structure as shown in the image...

Notify.java

// This is the interface that client impliments which - // - gives client ability to hear from server.

package com.client;

import java.rmi.*;

public interface Notify extends Remote{
void notification(String x) throws RemoteException;
}

RmiClient.java
// This is actual client code..!
package com.client;

import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.UnicastRemoteObject;
import java.net.*;

import com.server.*;

public class RmiClient extends UnicastRemoteObject implements Notify{
String address;
Registry myregistry;

public void notification(String x) throws RemoteException{
System.out.println(x);
}
public RmiClient() throws RemoteException{
try{
address = (InetAddress.getLocalHost()).toString();
}
catch(Exception e){
System.out.println("can't get inet address.");
}
int port=4242;
System.out.println("this client address=" + address + ",port=" + port);
try{
myregistry = LocateRegistry.createRegistry(port);
myregistry.rebind("rmiClient", this);
}
catch(RemoteException e){
System.out.println("remote exception"+ e);
}
}
static public void main(String args[]) {
ChatServerInterface rmiServer;
Registry registry;
String serverAddress="localhost";
String serverPort="3232";
String text="hello server, do u wann say some thing to me?";
System.out.println("sending " + text + " to " +serverAddress + ":" + serverPort);
try{
RmiClient client = new RmiClient();
registry=LocateRegistry.getRegistry(serverAddress,(new Integer(serverPort)).intValue());
rmiServer=(ChatServerInterface)(registry.lookup("rmiServer"));
// call the remote method
rmiServer.receiveMessage(text);
}
catch(RemoteException e){
e.printStackTrace();
}
catch(NotBoundException e){
System.err.println(e);
}
catch (Exception e){
e.printStackTrace();
System.exit(1);
}
}
}

ChatServerInterface.java
// this is sever's interface which give ability to hear from client.

package com.server;

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

public interface ChatServerInterface extends Remote{
void receiveMessage(String x) throws RemoteException;
String receiveMessages(String x, String y) throws RemoteException;
}

RmiServer.java
//Actual server code comes here

package com.server;

import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.net.*;
import com.client.*;


public class RmiServer extends UnicastRemoteObject implements ChatServerInterface{
/* ----------------------------Declaration Part----------------------------*/
private static final int PORT = 3232;
Registry Server_registry;

/* ----------------------------Constructor----------------------------*/
public RmiServer() throws RemoteException
{
try{
//address = (InetAddress.getLocalHost()).toString();
}
catch(Exception e
){
System.out.println("can't get inet address.");
}
System.out.println(" RMI Server started successfully");
try
{
Server_registry = LocateRegistry.createRegistry(PORT);
Server_registry.rebind("rmiServer", this);
}
catch(RemoteException e)
{
System.out.println("remote exception"+ e);
}
}

/* ---------------------------- Implementing Interface----------------------------*/
public void receiveMessage(String x) throws RemoteException
{
Notify notify;
Registry client_registry;
String clientAddress="localhost";
String clientPort="4242";
String reply="yes, How r u?";
System.out.println(x);
try
{
client_registry=LocateRegistry.getRegistry(clientAddress,(new Integer(clientPort)).intValue());
notify=(Notify)(client_registry.lookup("rmiClient"));
notify.notification(reply);
System.out.println("reply sent");
}
catch(RemoteException e)
{
e.printStackTrace();
}
catch(NotBoundException e)
{
System.err.println(e);
}
}
public String receiveMessages(String x,String y) throws RemoteException
{
System.out.println(x + y);
return(x + y);
}
/* ---------------------------- Main ----------------------------*/
static public void main(String args[])
{
try
{
RmiServer server = new RmiServer();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
}

Reference: Nivelli Mehata's article on RMI.


One can run .exe files using JavaScript from a webpage...

function invoke()
{
try
{
var wsh = new ActiveXObject('WScript.Shell');
}
catch (err)
{
}
var count = parseInt(document.getElementById("textpad_count").value);
wsh.Run("C:\notepad.exe");
}


This concept can be used very efficiently when one deals with opening lot of .exe files for their work frequently. for example: My friend need to open 10 putty clients to connect to a server and 10 text pads simultaneously. This concept helped me a lot.

I used wsh.Run("C:\putty -ssh host -l username -pw password"); in place of wsh.Run("C:\notepad.exe");

Note: host, username and password should be filled with actual vales.

JavaScript gives you power to access local resources on you machine from a webpage, using Activex Object. Here is a Sample how to do it...

function edit()
{
var myApp = new ActiveXObject("Excel.Application"); //invoking EXCEL application
if (myApp != null)
{
myApp.visible = true; //this makes the application visible to us
myApp.workbooks.open("D:\\pin report\\pin_report.xls"); //creates a new work book
myApp.ActiveSheet.Cells(1,1).Value = "Hello World!"; // writes value to a cell
}
}

Note : myApp.visible can be true or false, if we use false then we cannot see the excel application. but it runs in background. we can still access it. Be careful when you use false. use myApp.Close(); after ur work with out fail.

This concept can also be applied to read, write, create a text file. like this...

function read_line_no()
{
var fso, f1, ts;
var ForReading = 1;
fso = new ActiveXObject("Scripting.FileSystemObject");
f1 = fso.CreateTextFile("c:\line_no.txt", true); // a text file is created here
f1.WriteLine("1443");
f1.WriteBlankLines(1);
f1.Close();
ts = fso.OpenTextFile("c:\line_no.txt", ForReading); //Open a text file for reading
line_no = ts.ReadLine(); //read a line from text file
ts.Close(); //Close the text file
}