Remote Method Invocation ( RMI )
• RMI is a
distributed object system that enables you to easily develop distributed Java
applications. Developing distributed applications in RMI is simpler than
developing with sockets since there is no need to design a protocol, which is
an error-prone task.
• In RMI,
the developer has the illusion of calling a local method from a local class
file, when in fact the arguments are shipped to the remote target and
interpreted, and the results are sent back to the callers.
The Genesis of an RMI Application
Developing
a distributed application using RMI involves the following steps:
1. Define a
remote interface
2. Implement
the remote interface
3. Develop
the server
4. Develop a
client
5. Generate
Stubs and Skeletons, start the RMI registry, server, and client
Example: File Transfer
Application
This application allows a client to transfer (or
download) any type of file (plain text or binary) from a remote machine. The
first step is to define a remote interface that specifies the signatures of the
methods to be provided by the server and invoked by clients.
1. Define a remote interface
The
interface FileInterface provides one method downloadFile that takes a String
argument (the name of the file) and returns the data of the file as an array of
bytes.
FileInterface.java import
java.rmi.Remote;
import
java.rmi.RemoteException;
public interface FileInterface extends Remote {
public byte[] downloadFile(String fileName) throws RemoteException;
}
Note the
following characteristics about the FileInterface:
• It must
be declared public, in order for clients to be able to load remote objects
which implement the remote interface.
• It must
extend the Remote interface, to fulfill the requirement for making the object a
remote one.
• Each
method in the interface must throw a java.rmi.RemoteException.
2. Implement the remote interface
In
addition to implementing the FileInterface, the FileImpl class is extending the
UnicastRemoteObject. This indicates that the FileImpl class is used to create a
single, non-replicated, remote object that uses RMI's default TCP-based
transport for communication.
FileImpl.java
import
java.io.*; import java.rmi.*;
import
java.rmi.server.UnicastRemoteObject;
public class FileImpl extends UnicastRemoteObject
implements FileInterface {
private String name;
public FileImpl(String s) throws RemoteException{
super();
name = s;
}
public byte[] downloadFile(String fileName){
try {
File file
= new File(fileName);
byte
buffer[] = new byte[(int)file.length()];
BufferedInputStream
in = new BufferedInputStream(new FileInputStream(fileName));
in.read(buffer,0,buffer.length);
in.close();
return(buffer);
}
catch(Exception e){
System.out.println("FileImpl:
"+e.getMessage()); e.printStackTrace();
return(null);
}
}
}
3. Develop the server
The third
step is to develop a server. There are three things that the server needs to
do:
• Create an
instance of the RMISecurityManager and install it
• Create an
instance of the remote object (FileImpl in this case)
• Register
the object created with the RMI registry.
FileServer.java
import
java.io.*; import java.rmi.*;
public
class FileServer {
public static void main(String argv[]) {
if(System.getSecurityManager() == null) {
System.setSecurityManager(new
RMISecurityManager());
}
try {
FileInterface
fi = new FileImpl("FileServer");
Naming.rebind("//127.0.0.1/FileServer",
fi);
}
catch(Exception e) {
System.out.println("FileServer:
"+e.getMessage()); e.printStackTrace();
}
}
}
The
statement Naming.rebind("//127.0.0.1/FileServer", fi) assumes that
the RMI registry is running on the default port number, which is 1099. However,
if you run the RMI registry on a different port number it must be specified in
that statement. For example, if the RMI registry is running on port 4500, then
the statement becomes: Naming.rebind ("//127.0.0.1:4500/FileServer",
fi)
. Also,
it is important to note here that we assume the rmi registry and the server
will be running on the same machine. If they are not, then simply change the
address in the rebind method.
4. Develop a client
The
client remotely invokes any methods specified in the remote interface
(FileInterface). To do so however, the client must first obtain a reference to
the remote object from the RMI registry. Once a reference is obtained, the
downloadFile method is invoked. In this implementation, the client accepts two
arguments at the command line: the first one is the name of the file to be
downloaded and the second one is the address of the machine from which the file
is to be downloaded, which is the machine that is running the file server.
FileClient.java
Running the Application
To
generate stubs and skeletons, use the rmic compiler: prompt> rmic FileImpl
This will
generate two files: FileImpl_Stub.class and FileImpl_Skel.class. The stub is a
client proxy and the skeleton is a server skeleton.
• To
compile the server and the client. Use the javac compiler to do this. Note
however, if the server and client are developed on two different machines, in
order to compile the client you need a copy of the interface (FileInterface).
• To start
the RMI registry and run the server and client. To start the RMI registry on
the default port number, use the command rmiregistry or start rmiregistry on
Windows. To start the RMI registry on a different port number, provide the port
number as an argument to the RMI registry:
prompt> rmiregistry
portNumber
Once the
RMI registry is running, you can start the server FileServer. However, since
the RMI security manager is being used in the server application, you need a
security policy to go with it. Here is a sample security policy:
grant {
permission
java.security.AllPermission "", "";
};
To start
the server you need a copy of all the classes (including stubs and skeletons)
except the client class (FileClient.class). To start the server use the
following command, assuming that the security policy is in a file named
policy.txt:
prompt> java
-Djava.security.policy=policy.txt FileServer
To start
the client on a different machine, you need a copy of the remote interface
(FileInterface.class) and stub (FileImpl_Stub.class). To start the client use
the command:
prompt> java
FileClient fileName machineName
where
fileName is the file to be downloaded and machineName is the machine where the
file is located (the same machine runs the file server
To run
the client we mentioned that you need a copy of the interface and stub. A more
appropriate way to do this is to use RMI dynamic class loading. The idea is you
do not need copies of the interface and the stub. Instead, they can be located
in a shared directory for the server and the client, and whenever a stub or a
skeleton is needed, it is downloaded automatically by the RMI class loader. To
do this you run the client, for example, using the following command:
java
-Djava.rmi.server.codebase=http://hostname/locationOfClasses FileClient
fileName machineName.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.