Monday, 20 January 2014

Singleton object in Clustered Environment - An RMI Approach

RMI (Remote Method Invocation), helps application to call remote objects  on different JVM on Different host.
For example, consider the scenario where Singleton objects in Clustered Environments.
There will be one object presents per JVM. But if the design says, there should be one and only singleton object in the distributed environment, then how to achieve this?

Luckily RMI can be used to achieve this. ( But there are some limitations when the server singleton object crashes. This is discussed in the following link.http://www.javaspecialists.eu/archive/Issue052.html)

There will be one singleton object created in one clustered machine, and all other machines can use RMI to call this remote object.

This is the singleton class which creates its own object.
package intro;
importjava.io.Serializable;
public class SingletonObjectimplements Serializable {
private static final long serialVersionUID = 1L;
private static SingletonObjectsingletonObject = null;
privateSingletonObject() {
}
public static synchronized SingletonObjectgetSingletonObject() {
if (singletonObject == null) {
singletonObject = newSingletonObject();
}
return singletonObject;
}
}

Once RMI client find the remote object by lookup method, it uses this interface directly to access object.

RMI remote interface

package intro;
import java.rmi.*;
public interface SingletonGetterextends Remote {
public SingletonObjectgetSingleton() throws RemoteException;
}

This implements the interface method and defines the functionality.

RMI interface implementation:

package intro;
import java.rmi.*;
importjava.rmi.server.UnicastRemoteObject;
public class SingletonGetterImplextendsUnicastRemoteObject implements SingletonGetter {
public SingletonGetterImpl() throws RemoteException{}
public SingletonObject getSingleton() throws RemoteException{
returnSingletonObject.getSingletonObject();
}
}

The server RMI, which creates the remote object and binds that with the rmi registry.
Server Cluster
package intro;
import java.rmi.*;
import java.net.*;
public class SingletonRMIClusterServer{
public static void main(String[] args) {
try {
SingletonGetterImpllocalObject = new SingletonGetterImpl();
Naming.rebind("rmi:///SingletonObject", localObject);
} catch(RemoteExceptionre) {
re.printStackTrace();
} catch(MalformedURLExceptionmfe) {
mfe.printStackTrace();
}
}
}

The cluster which requires the singleton object, uses the server host and bind name to get the remote object. And using the remote object it gets the singleton object.

Client Cluster:

package intro;

import java.rmi.*;
import java.net.*;

public class SingletonRMIClusterConsumer{
public static void main(String[] args) {
try {
String host =
(args.length > 0) ? args[0] : "localhost";
SingletonGetter remObject =
(SingletonGetter)Naming.lookup("rmi://" + host +"/SingletonObject");
System.out.println(remObject.getSingleton());
} catch(RemoteException re) {
re.printStackTrace();
} catch(NotBoundException nbe) {
nbe.printStackTrace();
} catch(MalformedURLException mfe) {
mfe.printStackTrace();

}
}
}

Troubleshooting: 


Problem:

java.rmi.ConnectException: Connection refused to host: x.x.x.x; nested exception is:
    java.net.ConnectException: Connection refused: connect
Solution:
Go to command prompt and execute the below statement

 start rmiregistry

Problem:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: intro.SingletonGetter

Solution:
Navigate to the class files location and execute the command,
start rmiregistry

Also use the same JVM for running the RMI registry and server / RMI registry and client

No comments:

Post a Comment