RMI Remote Method Invocation
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.
Client-Server Review
RMI applications often comprise two separate programs, a server and a client. A typical server program creates some remote objects, makes references to these objects accessible, and waits for clients to invoke methods on these objects. A typical client program obtains a remote reference to one or more remote objects on a server and then invokes methods on them. RMI provides the mechanism by which the server and the client communicate and pass information back and forth. Such an application is sometimes referred to as a distributed object application.
Distributed object applications need to do the following:
1. Locate remote objects. Applications can use various mechanisms to obtain references to remote objects. For example, an application can register its remote objects with RMI's simple naming facility, the RMI registry. Alternatively, an application can pass and return remote object references as part of other remote invocations.
2. Communicate with remote objects. Details of communication between remote objects are handled by RMI. To the programmer, remote communication looks similar to regular Java method invocations.
3. Load class definitions for objects that are passed around. Because RMI enables objects to be passed back and forth, it provides mechanisms for loading an object's class definitions as well as for transmitting an object's data.
The following illustration depicts an RMI distributed application that uses the RMI registry to obtain a reference to a remote object. The server calls the registry to associate (or bind) a name with a remote object. The client looks up the remote object by its name in the server's registry and then invokes a method on it. The illustration also shows that the RMI system uses an existing web server to load class definitions, from server to client and from client to server, for objects when needed.
Remote Procedure Calls
Using RMI to develop a distributed application involves these general steps:
1. Designing and implementing the components of your distributed application.
2. Compiling sources.
3. Making classes network accessible.
4. Starting the application.
Remote Method Invocation
Like any other Java application, a distributed application built by using Java RMI is made up of interfaces and classes. The interfaces declare methods. The classes implement the methods declared in the interfaces and, perhaps, declare additional methods as well. In a distributed application, some implementations might reside in some Java virtual machines but not others. Objects with methods that can be invoked across Java virtual machines are called remote objects.
An object becomes remote by implementing a remote interface, which has the following characteristics:
1. A remote interface extends the interface java.rmi.Remote.
2. Each method of the interface declares java.rmi.RemoteException in its throws clause, in addition to any application-specific exceptions.
RMI treats a remote object differently from a non-remote object when the object is passed from one Java virtual machine to another Java virtual machine. Rather than making a copy of the implementation object in the receiving Java virtual machine, RMI passes a remote stub for a remote object. The stub acts as the local representative, or proxy, for the remote object and basically is, to the client, the remote reference. The client invokes a method on the local stub, which is responsible for carrying out the method invocation on the remote object.
A stub for a remote object implements the same set of remote interfaces that the remote object implements. This property enables a stub to be cast to any of the interfaces that the remote object implements. However, only those methods defined in a remote interface are available to be called from the receiving Java virtual machine.
First, determine your application architecture, including which components are local objects and which components are remotely accessible. This step includes:
1. Defining the remote interfaces. A remote interface specifies the methods that can be invoked remotely by a client. Clients program to remote interfaces, not to the implementation classes of those interfaces. The design of such interfaces includes the determination of the types of objects that will be used as the parameters and return values for these methods. If any of these interfaces or classes do not yet exist, you need to define them as well.
2. Implementing the remote objects. Remote objects must implement one or more remote interfaces. The remote object class may include implementations of other interfaces and methods that are available only locally. If any local classes are to be used for parameters or return values of any of these methods, they must be implemented as well.
3. Implementing the clients. Clients that use remote objects can be implemented at any time after the remote interfaces are defined, including after the remote objects have been deployed.
RMI Architecture
The General RMI Architecture
1. The server must first bind its name to the registry
2. The client lookup the server name in the registry to establish remote references.
3. The Stub serializing the parameters to skeleton, the skeleton invoking the remote method and serializing the result back to the stub.
1. A remote interface extends the interface java.rmi.Remote.
2. Each method of the interface declares java.rmi.RemoteException in its throws clause, in addition to any application-specific exceptions.
RMI treats a remote object differently from a non-remote object when the object is passed from one Java virtual machine to another Java virtual machine. Rather than making a copy of the implementation object in the receiving Java virtual machine, RMI passes a remote stub for a remote object. The stub acts as the local representative, or proxy, for the remote object and basically is, to the client, the remote reference. The client invokes a method on the local stub, which is responsible for carrying out the method invocation on the remote object.
A stub for a remote object implements the same set of remote interfaces that the remote object implements. This property enables a stub to be cast to any of the interfaces that the remote object implements. However, only those methods defined in a remote interface are available to be called from the receiving Java virtual machine.
First, determine your application architecture, including which components are local objects and which components are remotely accessible. This step includes:
1. Defining the remote interfaces. A remote interface specifies the methods that can be invoked remotely by a client. Clients program to remote interfaces, not to the implementation classes of those interfaces. The design of such interfaces includes the determination of the types of objects that will be used as the parameters and return values for these methods. If any of these interfaces or classes do not yet exist, you need to define them as well.
2. Implementing the remote objects. Remote objects must implement one or more remote interfaces. The remote object class may include implementations of other interfaces and methods that are available only locally. If any local classes are to be used for parameters or return values of any of these methods, they must be implemented as well.
3. Implementing the clients. Clients that use remote objects can be implemented at any time after the remote interfaces are defined, including after the remote objects have been deployed.
RMI Architecture
The General RMI Architecture
1. The server must first bind its name to the registry
2. The client lookup the server name in the registry to establish remote references.
3. The Stub serializing the parameters to skeleton, the skeleton invoking the remote method and serializing the result back to the stub.
• A client invokes a remote method, the call is first forwarded to stub.
• The stub is responsible for sending the remote call over to the server-side skeleton
• The stub opening a socket to the remote server, marshaling the object parameters and forwarding the data stream to the skeleton.
• A skeleton contains a method that receives the remote calls, unmarshals the parameters, and invokes the actual remote object implementation.
Remote Interfaces
RMI Registry
Start the RMI registry
Deployment and Implementation
Steps for Developing an RMI System
1. Define the remote interface
2. Develop the remote object by implementing the remote interface.
3. Develop the client program.
4. Compile the Java source files.
5. Generate the client stubs and server skeletons.
6. Start the RMI registry.
7. Start the remote server objects.
8. Run the client
1. To create an RMI application, the first step is the defining of a remote interface between the client and server objects.
/* SampleServer.java */
import java.rmi.*;
public interface SampleServer extends Remote
{
public int sum(int a,int b) throws RemoteException;
}
2. Develop the remote object and its interface
• The server is a simple unicast remote server.
• Create server by extending java.rmi.server.UnicastRemoteObject.
• The server uses the RMISecurityManager to protect its resources while engaging in remote communication.
/* SampleServerImpl.java */
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
public class SampleServerImpl extends UnicastRemoteObject
implements SampleServer
{
SampleServerImpl() throws RemoteException
{
super();
}
• Implement the remote methods
/* SampleServerImpl.java */
public int sum(int a,int b) throws RemoteException
{
return a + b;
}
}
• The server must bind its name to the registry, the client will look up the server name.
• Use java.rmi.Naming class to bind the server name to registry. In this example the name call “SAMPLE-SERVER”.
• In the main method of your server object, the RMI security manager is created and installed.
/* SampleServerImpl.java */
public static void main(String args[])
{
try
{
System.setSecurityManager(new RMISecurityManager());
//set the security manager
//create a local instance of the object
SampleServerImpl Server = new SampleServerImpl();
//put the local instance in the registry
Naming.rebind("SAMPLE-SERVER" , Server);
System.out.println("Server waiting.....");
}
catch (java.net.MalformedURLException me) {
System.out.println("Malformed URL: " + me.toString()); }
catch (RemoteException re) {
System.out.println("Remote exception: " + re.toString()); }
}
3. Develop the client program
• In order for the client object to invoke methods on the server, it must first look up the name of server in the registry. You use the java.rmi.Naming class to lookup the server name.
• The server name is specified as URL in the from ( rmi://host:port/name )
• Default RMI port is 1099.
• The name specified in the URL must exactly match the name that the server has bound to the registry. In this example, the name is “SAMPLE-SERVER”
• The remote method invocation is programmed using the remote interface name (remoteObject) as prefix and the remote method name (sum) as suffix.
import java.rmi.*; import java.rmi.server.*;
public class SampleClient
{
public static void main(String[] args)
{
// set the security manager for the client
System.setSecurityManager(new RMISecurityManager());
//get the remote object from the registry
try
{
System.out.println("Security Manager loaded");
String url = "//localhost/SAMPLE-SERVER";
SampleServer remoteObject = (SampleServer)Naming.lookup(url);
System.out.println("Got remote object");
System.out.println(" 1 + 2 = " + remoteObject.sum(1,2) );
}
catch (RemoteException exc) {
System.out.println("Error in lookup: " + exc.toString()); }
catch (java.net.MalformedURLException exc) {
System.out.println("Malformed URL: " + exc.toString()); }
catch (java.rmi.NotBoundException exc) {
System.out.println("NotBound: " + exc.toString());
} } }
4&5. Compile the Java source files & Generate the client stubs and server skeletons
• Assume the program compile and executing at elpis on ~/rmi
• Once the interface is completed, you need to generate stubs and skeleton code. The RMI system provides an RMI compiler (rmic) that takes your generated interface class and procedures stub code on its self.
elpis:~/rmi> set CLASSPATH=”~/rmi”
elpis:~/rmi> javac SampleServer.java
elpis:~/rmi> javac SampleServerImpl.java
elpis:~/rmi> rmic SampleServerImpl
elpis:~/rmi> javac SampleClient.java
6. Start the RMI registry
• The RMI applications need install to Registry. And the Registry must start manual by call rmiregisty.
• The rmiregistry us uses port 1099 by default. You can also bind rmiregistry to a different port by indicating the new port number as : rmiregistry
elpis:~/rmi> rmiregistry
• Remark: On Windows, you have to type in from the command line:
> start rmiregistry
7&8. Start the remote server objects & Run the client
• Once the Registry is started, the server can be started and will be able to store itself in the Registry.
• Because of the grained security model in Java 2.0, you must setup a security policy for RMI by set java.security.policy to the file policy.all
elpis:~/rmi> java –Djava.security.policy=policy.all SampleServerImpl
elpis:~/rmi> java –Djava.security.policy=policy.all SampleClient
• The stub is responsible for sending the remote call over to the server-side skeleton
• The stub opening a socket to the remote server, marshaling the object parameters and forwarding the data stream to the skeleton.
• A skeleton contains a method that receives the remote calls, unmarshals the parameters, and invokes the actual remote object implementation.
Remote Interfaces
RMI Registry
Start the RMI registry
1. The RMI applications need install to Registry. And the Registry must start manual by call rmiregisty.
2. The rmiregistry us uses port 1099 by default. You can also bind rmiregistry to a different port by indicating the new port number as :
rmiregistry <new port>
elpis:~/rmi>
rmiregistry
3. Remark: On Windows, you have to type in from the command
line:
> start
rmiregistry
1. Define the remote interface
2. Develop the remote object by implementing the remote interface.
3. Develop the client program.
4. Compile the Java source files.
5. Generate the client stubs and server skeletons.
6. Start the RMI registry.
7. Start the remote server objects.
8. Run the client
1. To create an RMI application, the first step is the defining of a remote interface between the client and server objects.
/* SampleServer.java */
import java.rmi.*;
public interface SampleServer extends Remote
{
public int sum(int a,int b) throws RemoteException;
}
2. Develop the remote object and its interface
• The server is a simple unicast remote server.
• Create server by extending java.rmi.server.UnicastRemoteObject.
• The server uses the RMISecurityManager to protect its resources while engaging in remote communication.
/* SampleServerImpl.java */
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
public class SampleServerImpl extends UnicastRemoteObject
implements SampleServer
{
SampleServerImpl() throws RemoteException
{
super();
}
• Implement the remote methods
/* SampleServerImpl.java */
public int sum(int a,int b) throws RemoteException
{
return a + b;
}
}
• The server must bind its name to the registry, the client will look up the server name.
• Use java.rmi.Naming class to bind the server name to registry. In this example the name call “SAMPLE-SERVER”.
• In the main method of your server object, the RMI security manager is created and installed.
/* SampleServerImpl.java */
public static void main(String args[])
{
try
{
System.setSecurityManager(new RMISecurityManager());
//set the security manager
//create a local instance of the object
SampleServerImpl Server = new SampleServerImpl();
//put the local instance in the registry
Naming.rebind("SAMPLE-SERVER" , Server);
System.out.println("Server waiting.....");
}
catch (java.net.MalformedURLException me) {
System.out.println("Malformed URL: " + me.toString()); }
catch (RemoteException re) {
System.out.println("Remote exception: " + re.toString()); }
}
3. Develop the client program
• In order for the client object to invoke methods on the server, it must first look up the name of server in the registry. You use the java.rmi.Naming class to lookup the server name.
• The server name is specified as URL in the from ( rmi://host:port/name )
• Default RMI port is 1099.
• The name specified in the URL must exactly match the name that the server has bound to the registry. In this example, the name is “SAMPLE-SERVER”
• The remote method invocation is programmed using the remote interface name (remoteObject) as prefix and the remote method name (sum) as suffix.
import java.rmi.*; import java.rmi.server.*;
public class SampleClient
{
public static void main(String[] args)
{
// set the security manager for the client
System.setSecurityManager(new RMISecurityManager());
//get the remote object from the registry
try
{
System.out.println("Security Manager loaded");
String url = "//localhost/SAMPLE-SERVER";
SampleServer remoteObject = (SampleServer)Naming.lookup(url);
System.out.println("Got remote object");
System.out.println(" 1 + 2 = " + remoteObject.sum(1,2) );
}
catch (RemoteException exc) {
System.out.println("Error in lookup: " + exc.toString()); }
catch (java.net.MalformedURLException exc) {
System.out.println("Malformed URL: " + exc.toString()); }
catch (java.rmi.NotBoundException exc) {
System.out.println("NotBound: " + exc.toString());
} } }
4&5. Compile the Java source files & Generate the client stubs and server skeletons
• Assume the program compile and executing at elpis on ~/rmi
• Once the interface is completed, you need to generate stubs and skeleton code. The RMI system provides an RMI compiler (rmic) that takes your generated interface class and procedures stub code on its self.
elpis:~/rmi> set CLASSPATH=”~/rmi”
elpis:~/rmi> javac SampleServer.java
elpis:~/rmi> javac SampleServerImpl.java
elpis:~/rmi> rmic SampleServerImpl
elpis:~/rmi> javac SampleClient.java
6. Start the RMI registry
• The RMI applications need install to Registry. And the Registry must start manual by call rmiregisty.
• The rmiregistry us uses port 1099 by default. You can also bind rmiregistry to a different port by indicating the new port number as : rmiregistry
elpis:~/rmi> rmiregistry
• Remark: On Windows, you have to type in from the command line:
> start rmiregistry
7&8. Start the remote server objects & Run the client
• Once the Registry is started, the server can be started and will be able to store itself in the Registry.
• Because of the grained security model in Java 2.0, you must setup a security policy for RMI by set java.security.policy to the file policy.all
elpis:~/rmi> java –Djava.security.policy=policy.all SampleServerImpl
elpis:~/rmi> java –Djava.security.policy=policy.all SampleClient