CACS354 Advance Java Programming

Advance Java ProgrammingUnit 611 min read

RMI: Remote Method Invocation in Java

Unit 6 of Advance Java Programming introduces Remote Method Invocation (RMI), a Java technology for distributed object communication, covering its architecture, components (stubs, skeletons, registry), data marshalling/unmarshalling, security, and real-world applications like banking systems and e-commerce platforms.

TAKEAWAYS:

  • RMI enables Java objects to call methods on remote objects as if they were local, using stubs, skeletons, and the RMI registry.
  • Marshalling converts Java objects to byte streams for network transmission; unmarshalling reconstructs them on the remote side.
  • The RMI architecture consists of client, server, stub, skeleton, and registry, with security managers enforcing access control.
  • RMI differs from CORBA in language neutrality (CORBA) vs. Java-only (RMI) and in its use of dynamic proxies vs. IDL interfaces.
  • Real-world use: eSewa’s transaction validation, Daraz’s inventory checks, and NEPSE’s stock price updates rely on distributed method calls.
  • Exam focus: Write client-server RMI programs, explain stub/skeleton roles, and compare RMI with CORBA or servlets.

1. Introduction to RMI

RMI allows a Java object (client) to invoke methods on a remote Java object (server) transparently. Unlike traditional socket-based communication, RMI abstracts network details using stubs (client-side proxies) and skeletons (server-side adapters).

Key Idea: RMI turns distributed objects into local method calls, hiding network latency and serialization complexities.


2. RMI Architecture

The RMI system consists of five core components:

flowchart TD
    A["Client"] -->|"Calls remote method"| B["Stub"]
    B -->|"Marshalls args"| C["Network"]
    C -->|"Unmarshalls args"| D["Skeleton"]
    D -->|"Invokes method"| E["Remote Object"]
    E -->|"Returns result"| D
    D -->|"Marshalls result"| C
    C -->|"Unmarshalls result"| B
    B -->|"Returns to client"| A
    F["RMI Registry"] -->|"Binds/lookups"| B & D

Components Explained:

  • Client: The application invoking remote methods.
  • Stub: A local proxy that marshals arguments and sends them over the network.
  • Skeleton: A server-side adapter that unmarshals arguments and invokes the actual remote object.
  • Remote Object: The actual object implementing remote methods (extends java.rmi.Remote).
  • RMI Registry: A naming service (port 1099 by default) that maps remote objects to network addresses.

3. How RMI Works: Step-by-Step

When a client calls a remote method:

  1. Stub serializes (marshalls) arguments into a byte stream.
  2. Network transmits the byte stream to the server.
  3. Skeleton deserializes (unmarshalls) the byte stream and calls the remote object.
  4. Remote object executes the method and returns a result.
  5. Skeleton marshalls the result back to the client.
  6. Stub unmarshalls the result and returns it to the caller.
Marshalling (args)SendReceiveInvokeReturnMarshalling (result)SendUnmarshallingClientStubNetworkSkeletonRemote Object
Step-by-step RMI communication flow for `stub.multiply(5, 3)`

Example: Calculating the product of two numbers remotely.


4. Data Marshalling and Unmarshalling

RMI uses Java’s serialization to convert objects into byte streams for network transmission.

multiplyintint53TOP
Serialized byte stream (simplified) for `multiply(5, 3)` arguments

Marshalling:

// Stub converts args to bytes
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(args); // Serializes arguments

Unmarshalling:

// Skeleton converts bytes back to objects
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
int result = (int) ois.readObject(); // Deserializes result

Limitations:

  • Only serializable objects can be transmitted.
  • Primitive types (int, double) and String are automatically supported.
  • Custom objects must implement java.io.Serializable.

5. RMI Registry

The RMI Registry acts as a white pages service for remote objects:

  • Binds: Registers a remote object under a name (e.g., "Calculator").
  • Unbinds: Removes a remote object.
  • Lookups: Clients query the registry to find the remote object’s URL.
bind(name, remoteObj)lookup(name)registerRMI RegistryStubRemote Object
RMI Registry: Binding and lookup process

Example Registry Command:

rmiregistry 1099  # Starts registry on port 1099

6. Writing an RMI Application

Worked Example: Remote Calculator (Product of Two Numbers)

Step 1: Define the Remote Interface

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

public interface Calculator extends Remote {
    int multiply(int a, int b) throws RemoteException;
}

Step 2: Implement the Remote Object

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

public class CalculatorImpl extends UnicastRemoteObject implements Calculator {
    public CalculatorImpl() throws RemoteException {
        super();
    }

    @Override
    public int multiply(int a, int b) throws RemoteException {
        return a * b;
    }
}

Step 3: Server Code (Exports Remote Object)

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class CalculatorServer {
    public static void main(String[] args) {
        try {
            Calculator obj = new CalculatorImpl();
            Registry registry = LocateRegistry.createRegistry(1099);
            registry.rebind("Calculator", obj);
            System.out.println("Server ready");
        } catch (Exception e) {
            System.err.println("Server error: " + e);
        }
    }
}

Step 4: Client Code (Calls Remote Method)

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class CalculatorClient {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost", 1099);
            Calculator stub = (Calculator) registry.lookup("Calculator");
            int result = stub.multiply(5, 3);
            System.out.println("Product: " + result); // Output: 15
        } catch (Exception e) {
            System.err.println("Client error: " + e);
        }
    }
}

7. RMI vs. CORBA

Feature RMI CORBA
Language Java-only Language-neutral (IDL)
Interface Java Remote interface IDL (Interface Definition Language)
Proxy Generation Automatic (stubs/skeletons) Manual (ORB generates stubs/skeletons)
Portability Limited to Java Cross-language (C++, Python, etc.)
Use Case Java-based distributed systems Heterogeneous distributed systems
017.53552.570RMI (Java-only)30CORBA (Language-neutral)70% Usage

8. Security in RMI

RMI includes security managers to control:

  • Network access (e.g., blocking malicious calls).
  • Class loading (preventing code injection).
  • Method invocation (enforcing permissions).

Example Security Policy:

java -Djava.security.policy=policy.all -cp . CalculatorServer

Policy File (policy.all):

grant {
    permission java.net.SocketPermission "localhost:1099", "connect, accept";
};

9. Real-World Applications

In the Real World

  1. eSewa Transaction Validation

    • Idea: RMI enables real-time balance checks across multiple servers.
    • How: When a user requests a transaction, eSewa’s backend uses RMI to call a remote balance service running on a different server, ensuring consistency without direct database access.
  2. Daraz Inventory Management

    • Idea: Distributed product availability checks.
    • How: When a customer adds an item to their cart, Daraz’s frontend calls a remote inventory service (via RMI) to verify stock levels across warehouses, updating the UI instantly.
  3. NEPSE Stock Price Updates

    • Idea: Real-time market data aggregation.
    • How: NEPSE’s trading servers use RMI to publish stock prices to multiple client applications (e.g., trading platforms), ensuring low-latency updates without polling.

10. Worked Example: Discounted Price Calculation

Scenario: A retail app calculates the selling price after a discount. Given:

  • Cost price = Rs. 5000
  • Discount = Rs. 500

Step 1: Remote Interface

public interface PriceCalculator extends Remote {
    double calculateSellingPrice(double cost, double discount) throws RemoteException;
}

Step 2: Server Implementation

public class PriceCalculatorImpl extends UnicastRemoteObject implements PriceCalculator {
    public PriceCalculatorImpl() throws RemoteException {
        super();
    }

    @Override
    public double calculateSellingPrice(double cost, double discount) {
        return cost - discount;
    }
}

Step 3: Client Call

Registry registry = LocateRegistry.getRegistry("localhost", 1099);
PriceCalculator stub = (PriceCalculator) registry.lookup("PriceCalculator");
double sellingPrice = stub.calculateSellingPrice(5000, 500);
System.out.println("Selling Price: Rs. " + sellingPrice); // Output: Rs. 4500.0

11. Common Pitfalls and Debugging

  1. ClassNotFoundException:

    • Cause: The client cannot find the remote object’s class.
    • Fix: Ensure both client and server have the same .class files (or use -classpath in rmic).
  2. NoSuchMethodError:

    • Cause: The remote interface method is not implemented correctly.
    • Fix: Verify the method signature matches exactly.
  3. Connection Refused:

    • Cause: The RMI registry is not running (rmiregistry not started).
    • Fix: Start the registry first:
      rmiregistry 1099
      

12. Exam Tip

  • For definitions: Always include stub, skeleton, and marshalling in your answer.
  • For code questions:
    • Server: Extend UnicastRemoteObject, implement Remote interface, bind to registry.
    • Client: Use LocateRegistry.getRegistry(), call lookup(), cast to remote interface.
  • For comparisons: Highlight language neutrality (CORBA vs. Java-only RMI) and proxy generation (automatic vs. manual).
  • For security: Mention policy files and permission checks in your answer.
  • For real-world links: Tie RMI to e-commerce (Daraz), banking (eSewa), or stock markets (NEPSE) in your explanations.

Visual Summary:

mindmap
  root((RMI))
    Client
      Stub
        Marshalls args
    Network
      Transmits byte stream
    Server
      Skeleton
        Unmarshalls args
      Remote Object
        Executes method
    Registry
      Binds/lookups objects
    Security
      Policy files
      Permission checks
    Real-world
      E-commerce (Daraz)
      Banking (eSewa)
      Stock markets (NEPSE)

Based on the TU BCA syllabus for Advance Java Programming (CACS354), unit 6.

Discussion

Loading…