Implementation of RMI in Java
Implementation of RMI in Java
1. Objectives
• To understand and implement Remote Method Invocation (RMI) in Java for enabling
method calls between objects on different JVMs.
2. Theory
Introduction
Remote Method Invocation (RMI) is a Java API that enables an object in one Java Virtual
Machine (JVM) to invoke methods on an object running in another JVM. It simplifies
distributed computing by allowing seamless communication between remote objects. At its
core, Java RMI is a system that simplifies the development of distributed Java applications.
Its primary purpose is to enable remote communication between Java programs, abstracting
away the intricate details of network programming.
RMI Architecture
The architecture of the RMI system is layered, providing a clear separation of concerns
and facilitating the complex interactions between distributed objects. The complete RMI
system is structured into four distinct layers, each responsible for a specific aspect of remote
communication:
• Application Layer: This is the topmost layer, encompassing the actual business
logic of both the client and server applications. On the server side, this layer contains
the concrete implementation of the remote objects and their methods. On the client
side, it represents the part of the application that initiates remote method calls and
processes their results.
• Proxy Layer (Stub/Skeleton Layer): This layer acts as the crucial intermedi-
ary between the client and the server. It consists of two primary components: the
Stub, which resides on the client side, and the Skeleton, which resides on the server
1
side. These proxies handle the marshalling and unmarshalling of data and the actual
invocation of remote methods.
• Remote Reference Layer (RRL): Positioned beneath the Proxy Layer, the RRL is
responsible for managing the references to remote objects. It handles the semantics of
remote object invocation, including the serialization (marshalling) of method param-
eters into a byte stream on the client side and the deserialization (unmarshalling) of
this binary data back into objects on the server side. The RRL effectively acts as a
communication link between the client-side and server-side RRLs.
• Transport Layer: This is the lowest layer of the RMI architecture, directly man-
aging the network connection between the client and the server. Its responsibilities
include establishing new connections, managing existing ones, and handling the low-
level transmission of data packets across the network.
RMI Components
Beyond the layered architecture, an RMI application fundamentally comprises three key
components that interact to facilitate remote method invocation: the RMI Server, the RMI
Client, and the RMI Registry.
• RMI Server: The RMI server is the component that hosts the remote objects. These
are instances of Java classes whose methods are designed to be invoked from other
JVMs. The server is responsible for creating these remote objects and then making
their references accessible to clients by binding them to the RMI registry.
2
• RMI Client: The RMI client is the program that seeks to utilize the services provided
by remote objects. It initiates communication by requesting a reference to a remote
object from the RMI registry. Once a reference is obtained, the client can then invoke
methods on that remote object, treating it much like a local object.
• RMI Registry: The RMI registry functions as a naming service, serving as a central-
ized directory for remote objects. RMI server programs use this service to register their
remote objects, associating them with unique names. Clients, in turn, use these names
to look up and obtain references to the desired remote objects. The registry typically
operates on a default port, 1099, and must be initiated before the server attempts to
bind any objects.
3. Algorithm
1. Define the Remote Interface
1. Import java.rmi.Remote and java.rmi.RemoteException.
3
3. Develop the RMI Client
1. Import java.rmi.registry.LocateRegistry and java.rmi.registry.Registry.
4. Source Code
Calculator.java
1 import java.rmi.Remote;
2 import java.rmi.RemoteException;
3
CalculatorServer.java
1 import java.rmi.RemoteException;
2 import java.rmi.server.UnicastRemoteObject;
3 import java.rmi.registry.Registry;
4 import java.rmi.registry.LocateRegistry;
5
4
8 protected CalculatorServer() throws RemoteException {
9 super();
10 }
11
12 @Override
13 public double add(double a, double b) throws RemoteException {
14 System.out.println("Server: Adding " + a + " + " + b);
15 return a + b;
16 }
17
18 @Override
19 public double subtract(double a, double b) throws RemoteException {
20 System.out.println("Server: Subtracting " + a + " - " + b);
21 return a - b;
22 }
23
24 @Override
25 public double multiply(double a, double b) throws RemoteException {
26 System.out.println("Server: Multiplying " + a + " * " + b);
27 return a * b;
28 }
29
30 @Override
31 public double divide(double a, double b) throws RemoteException {
32 System.out.println("Server: Dividing " + a + " / " + b);
33 if (b == 0) {
34 throw new RemoteException("Division by zero is not allowed");
35 }
36 return a / b;
37 }
38
39 @Override
40 public String getMessage() throws RemoteException {
41 return "Hello from Remote Calculator Server!";
42 }
5
43 public static void main(String[] args) {
44 try {
45 // Create and export a remote object
46 CalculatorServer server = new CalculatorServer();
47
58 } catch (Exception e) {
59 System.err.println("Server exception: " + e.toString());
60 e.printStackTrace();
61 }
62 }
63 }
CalculatorClient.java
1 import java.rmi.registry.LocateRegistry;
2 import java.rmi.registry.Registry;
3 import java.util.Scanner;
4
6
12 // Lookup the remote object
13 Calculator calculator = (Calculator) registry.lookup("Calculator");
14
21 while (true) {
22 System.out.println("\nChoose an operation:");
23 System.out.println("1. Addition");
24 System.out.println("2. Subtraction");
25 System.out.println("3. Multiplication");
26 System.out.println("4. Division");
27 System.out.println("5. Exit");
28 System.out.print("Enter your choice: ");
29
32 if (choice == 5) {
33 System.out.println("Goodbye!");
34 break;
35 }
36
43 double result = 0;
44 String operation = "";
45
46 switch (choice) {
7
47 case 1:
48 result = calculator.add(num1, num2);
49 operation = "Addition";
50 break;
51 case 2:
52 result = calculator.subtract(num1, num2);
53 operation = "Subtraction";
54 break;
55 case 3:
56 result = calculator.multiply(num1, num2);
57 operation = "Multiplication";
58 break;
59 case 4:
60 result = calculator.divide(num1, num2);
61 operation = "Division";
62 break;
63 }
64
71 scanner.close();
72
73 } catch (Exception e) {
74 System.err.println("Client exception: " + e.toString());
75 e.printStackTrace();
76 }
77 }
78 }
8
5. Output
9
6. Discussion
In this lab, we successfully implemented a distributed system using Java’s Remote Method
Invocation (RMI) framework. The system was designed with a remote interface, a server
implementing the remote methods, and a client capable of invoking these methods over the
network. The use of a Calculator example provided a clear and practical understanding of
how RMI enables distributed communication between Java Virtual Machines (JVMs). It
allowed us to focus on the RMI architecture—such as the creation of stubs, object binding
with the RMI registry, and method invocation—without the complexity of real-world busi-
ness logic. The exercise illustrated how RMI hides the underlying network communication,
allowing developers to concentrate on interface design and method implementation.
7. Conclusion
In conclusion, this lab reinforced the concept of remote method invocation using Java RMI.
The successful execution of remote methods proved the effectiveness of Java RMI in building
simple distributed applications.
10