Hi! guys this tutorial will give you the basic idea about "What RMI stands for and how does it work.Let's start it.
Submitted On | |
By | Indee |
Level | Intermediate |
User Rating | 4.3 (34 globes from 8 users) |
Compatibility | Java (JDK 1.1), Java (JDK 1.2) |
Category | Miscellaneous |
World | Java |
Archive File |
The Remote Method Invocation (RMI) API is a core component of the Java programming language, and adds the capability to develop fully distributed applications. i.e. an application that will execute across multiple host systems. Since Java is designed to be a language for the Internet, it must include support for communication between programs on different machines. RMI enables objects executing on one host to invoke methods of objects on remote hosts to assist them in performing their tasks. These methods execute on the remote hosts, and this is where the term remote method invocation stems from.
So what exactly is RMI? RMI is a term used to describe not only the act of invoking a method defined in a different address space, but also the changes made to the Java language to support remote method calls. These changes included new tools, APIs and run-time support. RMI enables the methods of an object in one virtual machine to call the method of an object in another virtual machine with the same syntax and ease as a local machine invocation.
There are a number of approaches that have been taken when developing a distributed system, e.g. the Internet is an example of a distributed system that makes use of TCP/IP in a client/server fashion. There are three main approaches to tackling a distributed system within Java, all have their pros and cons:
- Distributed Component Object Model (DCOM)
DCOM uses remote procedure calls that invoke the methods of objects running on other systems. It is an excellent framework upon which to develop a distributed object-based system. However, it has a heavy bias towards legacy Windows applications, and as a result cannot provide a 100% pure Java solution.
- Common Object Request Broker Architecture
(CORBA)
CORBA is a framework that provides support for the development of distributed systems in the form of a language-independent model. Although this would appear to be a big advantage in the development of a distributed system, when it comes to Java we can consider it a disadvantage as it forces Java applications to use an external object model. On the plus side to using CORBA, it allows a variety of programming languages to interact.
- Remote Method Invocation (RMI)
RMI is the Java way to approaching the development of a distributed system. Its main advantage is that it is closely integrated into the Java object model as an API. However, it is limited in use to pure Java applications only. If you are developing a distributed system that contains objects written in other languages, then CORBA is the best solution to use.
There are a few terms that you might come across when discussing the RMI API, most of which relate to the concept that RMI is built upon- that of local and remote objects.
- Local objects - objects that execute on the host machine
- Remote objects - objects that execute on all other hosts
- Exported - objects on remote hosts are exported, allowing remote invocation
- Remote registry server - an object exports itself by registering with the remote registry server. It also assists objects on other hosts to remotely access its registered objects using a database of names that are associated with objects.
- Client object - any local object that invokes a remote objects method (also known simply as a client).
- Server object - any remote object whose methods may be invoked by a local object (also known simply as a server).
- Stub - a local object that acts as a local proxy for the remote object, providing the same methods as the remote object.
- Skeleton - a proxy for the remote object that is situated on the same host as the remote object. The stub on the local host and skeleton then communicate with each other via a remote reference layer.
Probably the best way to get a better idea of what is actually happening here is to look at an example!.
Follow the following steps
- First copy all the files for this exercise into a directory of your
choice. The required files are:
CalculatorService.java
import java.rmi.*; import java.rmi.Naming; import java.io.*; // // // CalculatorClient // // public class CalculatorClient { public static void main(String args[]) throws Exception { // Check for hostname argument if (args.length != 1) { System.out.println ("Syntax - CalculatorClient host"); System.exit(1); } // Assign secuirty manager if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } // Call registry for PowerService CalculatorService service = (CalculatorService) Naming.lookup ("rmi://" + args[0] + "/CalculatorService"); DataInputStream din = new DataInputStream (System.in); for (;;) { System.out.println ("1 - Calculate square"); System.out.println ("2 - Calculate power"); System.out.println ("3 - Exit"); System.out.println(); System.out.print ("Choice : "); String line = din.readLine(); Integer choice = new Integer(line); int value = choice.intValue(); switch (value) { case 1: System.out.print ("Number : "); line = din.readLine();System.out.println(); choice = new Integer (line); value = choice.intValue(); // Call remote method System.out.println ("Answer : " + service.square(value)); break; case 2: System.out.print ("Number : "); line = din.readLine(); choice = new Integer (line); value = choice.intValue(); System.out.print ("Power : "); line = din.readLine(); choice = new Integer (line); int power = choice.intValue(); // Call remote method System.out.println ("Answer : " + service.power(value, power)); break; case 3: System.exit(0); default : System.out.println ("Invalid option"); break; } } } }
CalculatorServer.java
import java.math.*; import java.rmi.*; import java.rmi.server.*; // // // CalculatorServer // // Server for a RMI service that calculates // public class CalculatorServer extends UnicastRemoteObject implements CalculatorService { public CalculatorServer () throws RemoteException { super(); } // Calculate the square of a number public BigInteger square ( int number ) throws RemoteException { String numrep = String.valueOf(number); BigInteger bi = new BigInteger (numrep); // Square the number bi = bi.multiply(bi); return (bi); } // Calculate the power of a number public BigInteger power ( int num1, int num2) throws RemoteException { String numrep = String.valueOf(num1); BigInteger bi = new BigInteger (numrep); bi = bi.pow(num2); return (bi); } public static void main ( String args[] ) throws Exception { // Assign a security manager, in the event that dynamic classes are loaded if (System.getSecurityManager() == null) System.setSecurityManager ( new RMISecurityManager() ); // Create an instance of our power service server ... CalculatorServer svr = new CalculatorServer(); // ... and bind it with the rmi registry Naming.bind ("CalculatorService", svr); System.out.println ("Service bound...."); } }
CalculatorClient.java
import java.math.BigInteger; import java.rmi.*; // // // CalculatorService Interface // // Interface for a RMI service that calculates powers // public interface CalculatorService extends java.rmi.Remote { // Calculate the square of a number public BigInteger square ( int number ) throws RemoteException; // Calculate the power of a number public BigInteger power ( int num1, int num2) throws RemoteException; }
java.policy
for java.policy file, type the following text in notepad and save as "java.policy"
grant { permission java.net.SocketPermission "*:1024-65535", "connect,accept,resolve"; permission java.net.SocketPermission "*:1-1023", "connect,resolve"; };
- Now compile all the .java files by isuuing the following command:
>javac *.java
- Next create the stubs and skeletons required by the program. The stubs and
skeletons communicate through a remote reference. This layer enables communication
via a transport protocol. Currently RMI uses TCP.
>rmic CalculatorServer
Note that no extension is specified as rmic takes a .class file as its default. This will produce the following files in the current directory:
CalculatorClient.java
CalculatorServer.java
CalculatorService.java
java.policy
CalculatorService.class
CalculatorClient.class
CalculatorServer.class
CalculatorServer_Stub.class
CalculatorServer_Skel.class
As you can see, the _Stub and _Skel.class have been automatically created.
- For RMI to work we will need to start a program that acts as a remote registry
server. This is simply a program that listens on the default port 1099 for
incoming requests to access named objects. The named objects must register
themselves with the remote registry program in order to be made available
to requesters. Type the following command to start up the remote registry
server:
>start rmiregistryThis will initiate another DOS window, which must be left open while this exercise is running. Minimise it if you wish.
- Now all we need is to actually execute the server and client programs. However,
owing to the security restrictions imposed by Java 2, you will need to issue
the following commands.
Execute the server from your current command prompt:
>java -Djava.security.policy=java.policy CalculatorServerThis will then report a “Service bound…” message – your server is up and running!
Now do the same with the client, but this time start up another DOS window and change into the directory where you invoked the previous command. Here’s the command:
>java -Djava.security.policy=java.policy CalculatorClient localhostYou will now see something that looks like this:
1 - Calculate square 2 - Calculate power 3 - Exit Choice :
Experiment with this program.
So what is actually happening here? The file CalculatorService.java is our interface- in other words, a method that contains abstract methods. Another class must implement these methods, and this is exactly what RMI is all about. Here’s the code for CalculatorService.java:
import java.math.BigInteger; import java.rmi.*; // // // CalculatorService Interface // // Interface for a RMI service that calculates powers // public interface CalculatorService extends java.rmi.Remote { // Calculate the square of a number public BigInteger square ( int number ) throws RemoteException; // Calculate the power of a number public BigInteger power ( int num1, int num2) throws RemoteException; }
Now we need to implement the interface, i.e., the actual code of the square and power methods. The main() method will be responsible for creating an instance of the CalculatorServer and registering (or binding) the service with the RMIRegistry. It is also responsible for assigning the security manager. Here is the CalculatorServer program where the actual power and square code is situated:
import java.math.*; import java.rmi.*; import java.rmi.server.*; // // // CalculatorServer // // Server for a RMI service that calculates // public class CalculatorServer extends UnicastRemoteObject implements CalculatorService { public CalculatorServer () throws RemoteException { super(); } // Calculate the square of a number public BigInteger square ( int number ) throws RemoteException { String numrep = String.valueOf(number); BigInteger bi = new BigInteger (numrep); // Square the number bi = bi.multiply(bi); return (bi); } // Calculate the power of a number public BigInteger power ( int num1, int num2) throws RemoteException { String numrep = String.valueOf(num1); BigInteger bi = new BigInteger (numrep); bi = bi.pow(num2); return (bi); } public static void main ( String args[] ) throws Exception { // Assign a security manager, in the event that dynamic classes are loaded if (System.getSecurityManager() == null) System.setSecurityManager ( new RMISecurityManager() ); // Create an instance of our power service server ... CalculatorServer svr = new CalculatorServer(); // ... and bind it with the rmi registry Naming.bind ("CalculatorService", svr); System.out.println ("Service bound...."); } }
Next we need a client that will make use of the service we have created. The client simply calls the registry to obtain a reference to the remote object and call the available methods. Any underlying communication is hidden.
The line
CalculatorService service = (CalculatorService) Naming.lookup ("rmi://" + args[0] + "/CalculatorService");instantiates a new instance of CalculatorService which is created by a call to the registry, and to identify the service we specify an RMI URL. This URL is the hostname on which the service is located, in this case “localhost” and the logical name of the service. The returned object can then be treated just like any other local object:
System.out.println("Answer : " + service.square(value)); System.out.println("Answer : " + service.power(value, power));Finally, here is the full source code for CalculatorClient:
import java.rmi.*; import java.rmi.Naming; import java.io.*; // // // CalculatorClient // // public class CalculatorClient { public static void main(String args[]) throws Exception { // Check for hostname argument if (args.length != 1) { System.out.println ("Syntax - CalculatorClient host"); System.exit(1); } // Assign secuirty manager if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } // Call registry for PowerService CalculatorService service = (CalculatorService) Naming.lookup ("rmi://" + args[0] + "/CalculatorService"); DataInputStream din = new DataInputStream (System.in); for (;;) { System.out.println ("1 - Calculate square"); System.out.println ("2 - Calculate power"); System.out.println ("3 - Exit"); System.out.println(); System.out.print ("Choice : "); String line = din.readLine(); Integer choice = new Integer(line); int value = choice.intValue(); switch (value) { case 1: System.out.print ("Number : "); line = din.readLine();System.out.println(); choice = new Integer (line); value = choice.intValue(); // Call remote method System.out.println ("Answer : " + service.square(value)); break; case 2: System.out.print ("Number : "); line = din.readLine(); choice = new Integer (line); value = choice.intValue(); System.out.print ("Power : "); line = din.readLine(); choice = new Integer (line); int power = choice.intValue(); // Call remote method System.out.println ("Answer : " + service.power(value, power)); break; case 3: System.exit(0); default : System.out.println ("Invalid option"); break; } } } }
ok that's it. I hope you got a fair idea about the RMI. For any clarification on this tutorial please feel free to ask question in our java forum.