CACS355 Network Programming

Network ProgrammingUnit 415 min read

Remote Method Invocation (RMI): Architecture, Implementation & Use Cases

Unit 4 of Network Programming introduces Remote Method Invocation (RMI), a Java framework for distributed object communication, covering its architecture, key classes, security, and real-world applications like banking systems and e-commerce APIs.

TAKEAWAYS:

  • RMI enables objects in different JVMs to invoke methods as if they were local, using serialization and stubs/skeletons.
  • The RMI architecture consists of client, server, registry, and remote objects, with Java RMI Registry acting as a naming service.
  • Remote interfaces and skeletons/stubs handle method calls transparently, while serialization ensures data transfer.
  • Security in RMI includes authentication, encryption, and firewall rules to prevent unauthorized access.
  • RMI vs. HTTP/REST: RMI is object-oriented and synchronous, while REST is stateless and text-based.
  • Real-world use: eSewa’s transaction validation and Daraz’s inventory checks use RMI-like distributed systems for real-time data access.

1. Introduction to Remote Method Invocation (RMI)

RMI allows Java objects in different JVMs to communicate as if they were in the same process. Unlike HTTP (which transfers text), RMI transfers Java objects directly, making it ideal for distributed systems like banking, e-commerce, and cloud services.

Key Concepts

  • Remote Object: An object whose methods are invoked from a different JVM.
  • Stub: A local proxy for the remote object (handles method calls).
  • Skeleton: A server-side object that receives calls from stubs and invokes the real remote object.
  • Registry: A naming service (like a phonebook) that maps remote object names to their network addresses.

2. RMI Architecture

RMI follows a client-server model with four main components:

flowchart TD
    A["Client JVM"] -->|"Calls remote method"| B["Stub (Local Proxy)"]
    B -->|"Serializes request"| C["Network"]
    C -->|"Delivers to server"| D["Skeleton (Server-side Proxy)"]
    D -->|"Invokes real object"| E["Remote Object (Server JVM)"]
    E -->|"Returns result"| D
    D -->|"Serializes response"| C
    C -->|"Sends back"| B
    B -->|"Deserializes"| A

Components Explained

Component Role
Client Calls methods on remote objects via stubs.
Stub Local proxy that serializes requests and deserializes responses.
Skeleton Server-side proxy that receives calls and invokes the real remote object.
Registry Maps remote object names to network addresses (default port: 1099).
Remote Object Actual object whose methods are called remotely.

3. How RMI Works (Step-by-Step)

  1. Client requests a remote object from the registry.
  2. Registry returns a stub (local proxy) to the client.
  3. Client calls a method on the stub → stub serializes the request.
  4. Request travels over the network to the server.
  5. Skeleton receives the request, deserializes it, and calls the real remote object.
  6. Remote object processes the call and returns a result.
  7. Result is serialized and sent back to the client via the stub.

4. Key Classes in RMI

Class/Interface Purpose
Remote Marker interface for remote objects.
RemoteException Thrown when RMI fails (e.g., network error).
UnicastRemoteObject Base class for implementing remote objects.
RMISocketFactory Customizes socket creation (e.g., for firewalls).
java.rmi.Naming Registry lookup methods (e.g., Naming.lookup()).
java.rmi.server.RMIClientSocketFactory Customizes client-side sockets.
RemoteObjectRemoteExceptionUnmarshalExceptionMarshalExceptionNamingAccessException
Hierarchy of core RMI exception classes (simplified)

5. Serialization in RMI

RMI uses Java’s serialization to convert objects into a byte stream for network transfer.

Example: Serializable Class

import java.io.Serializable;

public class Triangle implements Serializable {
    private double base;
    private double height;

    public double calculateArea() {
        return 0.5 * base * height;
    }
}
  • Why? Non-serializable objects cannot be sent over RMI.

6. Implementing a Remote Object (Worked Example)

Goal: Calculate the area of a triangle using RMI.

RemoteInterface0Stub1Skeleton2RealObject3
RMI's proxy-skeleton architecture: how stubs and skeletons bridge client-server calls

Step 1: Define the Remote Interface

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface TriangleCalculator extends Remote {
    double calculateArea(double base, double height) throws RemoteException;
}

Step 2: Implement the Remote Object

import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;

public class TriangleCalculatorImpl extends UnicastRemoteObject
    implements TriangleCalculator {

    public TriangleCalculatorImpl() throws RemoteException {
        super();
    }

    @Override
    public double calculateArea(double base, double height) throws RemoteException {
        return 0.5 * base * height;
    }
}

Step 3: Start the RMI Registry

rmiregistry 1099

(Run this in a terminal before starting the server.)

Step 4: Export the Remote Object

import java.rmi.Naming;

public class Server {
    public static void main(String[] args) {
        try {
            TriangleCalculator calculator =
                new TriangleCalculatorImpl();
            Naming.rebind("rmi://localhost:1099/TriangleCalculator", calculator);
            System.out.println("Server ready.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Step 5: Client Code to Call the Remote Method

import java.rmi.Naming;

public class Client {
    public static void main(String[] args) {
        try {
            TriangleCalculator calculator =
                (TriangleCalculator) Naming.lookup("rmi://localhost:1099/TriangleCalculator");
            double area = calculator.calculateArea(4.0, 6.0);
            System.out.println("Area: " + area);  // Output: 12.0
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

7. RMI vs. Other Networking Models

Feature RMI HTTP/REST gRPC
Data Format Java objects (serialized) JSON/XML (text-based) Protocol Buffers (binary)
Communication Synchronous (blocking) Stateless (asynchronous) Streaming (bidirectional)
Use Case Distributed Java apps Web APIs (cross-language) Microservices (high performance)
Language Java-only Language-agnostic Primarily Go, Java, Python

8. Security in RMI

RMI includes built-in security but requires configuration:

  • Authentication: Clients must authenticate via login.conf (Java’s policy file).
  • Encryption: Uses SSL/TLS for secure communication.
  • Firewall Rules: Custom socket factories (RMISocketFactory) help bypass firewalls.

Example: Secure RMI Setup

  1. Edit java.policy (in $JAVA_HOME/lib/security):
    grant {
        permission java.net.SocketPermission "localhost:1099", "connect, accept";
    };
    
  2. Run the server with:
    java -Djava.security.policy=java.policy Server
    

9. Real-World Applications of RMI-Like Systems

In the Real World

  1. eSewa’s Transaction Validation

    • How? eSewa uses distributed systems where user requests (e.g., fund transfer) are processed by remote servers.
    • RMI-like Idea: The client (user’s phone) calls a remote method to verify funds before processing.
    • Example: When you transfer ₨500 from eSewa, the app calls a remote server to check your balance—just like RMI’s remote method call.
  2. Daraz’s Inventory Management

    • How? Daraz’s backend servers (in different data centers) communicate to check stock levels.
    • RMI-like Idea: A seller’s dashboard calls a remote method to fetch real-time inventory data.
    • Worked Example: Suppose a seller lists 100 units of a product. When a customer buys 50 units, Daraz’s system calls a remote method to deduct 50 from the inventory and update the database.
  3. Nepal Rastra Bank’s Loan Processing

    • How? Banks use distributed systems where loan applications are processed by remote servers.
    • RMI-like Idea: A bank’s loan officer submits an application, and the system calls a remote method to check credit score and approve/reject the loan.

10. Common Pitfalls & Best Practices

Pitfall Solution
Serialization errors Ensure all fields are Serializable.
Firewall blocking RMI Use custom RMISocketFactory to bypass restrictions.
Port conflicts Change the registry port (default: 1099).
Security vulnerabilities Use SSL/TLS and restrict permissions in java.policy.
Performance bottlenecks Avoid heavy objects; use lightweight data transfer objects (DTOs).

11. Exam Tips

  1. Understand the RMI Architecture

    • Always draw the client-stub-skeleton-registry flow. Examiners love diagrams!
    • Know the roles of stub, skeleton, and registry.
  2. Code Implementation

    • Must include:
      • A remote interface (extends Remote).
      • A remote object implementation (extends UnicastRemoteObject).
      • Serialization (all classes must implement Serializable).
      • Registry binding (Naming.rebind()).
    • Trace the execution:
      • Show serialization/deserialization steps.
      • Explain how the stub calls the skeleton.
  3. Compare RMI with Other Models

    • HTTP/REST: Stateless, text-based, language-agnostic.
    • gRPC: Binary, high-performance, streaming.
    • RMI: Java-only, object-oriented, synchronous.
  4. Security Questions

    • Mention authentication, encryption, and policy files.
    • Example: "How would you secure an RMI-based banking system?" → Answer: "Use SSL/TLS, restrict permissions in java.policy, and validate client certificates."
  5. Real-World Mapping

    • Link RMI to eSewa, Daraz, or Ncell’s call routing (e.g., "How does Ncell’s call forwarding use remote method calls?").
    • Example answer:

      "Ncell’s call forwarding system uses a distributed architecture where a remote method is called to check the subscriber’s plan before forwarding a call—similar to how RMI invokes methods on remote objects."


12. Sample Exam Questions & Answers

Q1: Explain the role of the RMI Registry.

Naming.lookup()Returns stubNaming.rebind()ClientRegistryServer
Registry interaction: Clients query stubs via `Naming.lookup()`, servers register objects via `Naming.rebind()`

Answer: The RMI Registry acts as a naming service that maps remote object names (e.g., "rmi://localhost/TriangleCalculator") to their network addresses. It:

  1. Stores remote objects when the server calls Naming.rebind().
  2. Returns stubs to clients when they call Naming.lookup().
  3. Runs on port 1099 by default (can be changed).

Without the registry, clients wouldn’t know where to find remote objects.

Q2: Write a program to list all interfaces implemented by a remote object.

import java.lang.reflect.*;

public class ListInterfaces {
    public static void main(String[] args) {
        Class<?> clazz = TriangleCalculatorImpl.class;
        Class<?>[] interfaces = clazz.getInterfaces();
        System.out.println("Interfaces implemented:");
        for (Class<?> iface : interfaces) {
            System.out.println("- " + iface.getName());
        }
    }
}

Output:

Interfaces implemented:
- TriangleCalculator

Explanation:

  • Use getInterfaces() to list all interfaces a class implements.
  • In RMI, remote objects must implement at least one Remote interface.

13. Full Code Example: RMI-Based Chat Server

(Bonus for advanced students—shows multithreading in RMI.)

Server (ChatServer.java)

import java.rmi.*;
import java.rmi.server.*;
import java.util.*;

public class ChatServer extends UnicastRemoteObject implements ChatServerInterface {
    private List<String> messages = new ArrayList<>();

    public ChatServer() throws RemoteException {
        super();
    }

    @Override
    public synchronized void sendMessage(String msg) throws RemoteException {
        messages.add(msg);
        notifyAll(); // Wake up waiting clients
    }

    @Override
    public synchronized String getLatestMessage() throws RemoteException {
        while (messages.isEmpty()) {
            try { wait(); } catch (InterruptedException e) { }
        }
        return messages.remove(0);
    }

    public static void main(String[] args) {
        try {
            ChatServer server = new ChatServer();
            Naming.rebind("rmi://localhost:1099/ChatServer", server);
            System.out.println("Chat server running...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Client (ChatClient.java)

import java.rmi.*;

public class ChatClient {
    public static void main(String[] args) {
        try {
            ChatServerInterface server =
                (ChatServerInterface) Naming.lookup("rmi://localhost:1099/ChatServer");
            server.sendMessage("Hello, RMI!");
            String latest = server.getLatestMessage();
            System.out.println("Latest message: " + latest);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Key Takeaway:

  • Synchronization (synchronized + wait()/notify()) ensures thread-safe message handling.
  • Useful for: Real-time systems like WhatsApp status updates or Pathao driver tracking.

14. Summary Table: RMI vs. Other Distributed Models

Feature RMI CORBA SOAP/REST
Language Java-only Language-agnostic (IDL) Language-agnostic (XML/JSON)
Data Format Java serialization CORBA IDL XML/JSON
Protocol Custom RMI protocol IIOP (Internet Inter-ORB) HTTP/HTTPS
Performance Fast (binary) Moderate Slower (text parsing)
Use Case Java enterprise apps Legacy enterprise systems Web APIs (modern)

15. Final Exam Tip

  • Always include a diagram of the RMI flow (client → stub → network → skeleton → remote object).
  • For coding questions, show:
    1. The remote interface.
    2. The remote object implementation.
    3. Serialization (if applicable).
    4. Registry binding/lookup.
  • Security is key: Mention java.policy, SSL, and firewall rules if asked.
  • Real-world link: Compare RMI to eSewa’s transaction processing or Daraz’s inventory checks.

Good luck! RMI is a high-scoring unit if you master the architecture, code structure, and real-world mapping. 🚀

Based on the TU BCA syllabus for Network Programming (CACS355), unit 4.

Discussion

Loading…