Java Tutorial/Trail: RMI
RMI
editThe Java Remote Method Invocation (RMI) system is a network communication framework for client–server communication. RMI is java-centric because the framework expects both sides of the communication to be implemented in Java; other frameworks are more usually at least specified language agnostic. The java-centric design makes RMI quite convenient for network communication in the Java programming language. The RMI system has, however, been retrofitted to support the Corba Internet Inter-ORB protocol (RMI-IIOP) in addition to the native protocol JRMP.
Server
editThe RMI server (cvs) exports an implementing class (in this example RemoteDatabase
), which is derived from an interface (in this example RemoteDatabaseIfc
) that specifies the methods available through RMI. All methods of the interface must throw the RemoteException and the interface must extend the Remote interface, thus marking the interface as an exportable interface.
The interface is a tagging interface and thus does not require the implementing class to implement any methods.
public void exportDatabaseService () throws RemoteException
{
RemoteDatabase database = new RemoteDatabase ();
Registry registry = locateOrCreateRegistry (port);
RemoteDatabaseIfc stub = (RemoteDatabaseIfc) UnicastRemoteObject.exportObject (database);
registry.rebind (DATABASE_SERVICE_NAME, stub);
}
Client
editA simple RMI client (cvs) can connect to the server and make the interface locally available in a different virtual machine and possibly on a different computer.
package org.wikiversity.java_tutorial;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RmiClient
{
/**
* Connects to the remote database on the specified host.
* @param hostName the name of the host
* @param registryPort the port of the RMI registry on the remote host
* @return RemoteDatabaseIfc
* @throws RemoteException if remote communication with the registry failed
* @throws NotBoundException if the named service is not currently bound
*/
public RemoteDatabaseIfc connectToDatabase (String hostName, int registryPort) throws RemoteException, NotBoundException
{
Registry registry = LocateRegistry.getRegistry (hostName, registryPort == 0 ? Registry.REGISTRY_PORT : registryPort);
return (RemoteDatabaseIfc) registry.lookup (RmiService.DATABASE_SERVICE_NAME);
}
}
(source code from vsrs.svn.sourceforge.net)
Serializable
editThe interface Serializable must be implemented by all classes that are meant to be transported through an RMI connection; this interface is also a tagging interface, which tells ObjectOutputStream that the object in question is suitable for serialization.
It is recommended but not required for classes that implement the Serializable interface to declare a special static final variable:
private static final long serialVersionUID = 0xCABAL;
This variable substitutes version information that is otherwise generated by the virtual machine and that is meant to ensure that the classes on both sides of the RMI connection are compatible with each other. If the classes implement a well-defined interface (or wire format) one could, for instance, use the current version of the interface that is implemented as the serialVersionUID
(e.g 100000000 for 1.0.0, 100100000 for 1.1.0 and so on).
The Java RMI compiler
editThe Java RMI compiler rmic (or grmic for the GNU variant) generates internal objects that are required for RMI connections. The simplest invocation of rmic is rmic package.Class
, which compiles the class "Class" in the package "package", provided that the compiled class can be found in the directory corresponding to the package name.