Unit 2
REMOTE METHOD INVOCATION
Remote Method Invocation (RMI) is an API that allows an object to invoke a method on
an object that exists in another address space, which could be on the same machine or on a remote
machine. Through RMI, an object running in a JVM present on a computer (Client-side) can
invoke methods on an object present in another JVM (Server-side). RMI creates a public remote
server object that enables client and server-side communications through simple method calls on
the server object.
Key Components of RMI
● Stub
● Skeleton
1. Stub (Client-side):
The stub is a proxy for the remote object on the client side. It acts as a gateway for outgoing
requests, initiating a connection with the remote JVM, marshaling parameters, waiting for the
result, and unmarshaling the return value or exception.
Working of Stub:
● It initiates a connection with remote Virtual Machin (JVM)
● It writes and transmits the parameters to JVM
● It waits for the result
● It reads the return value or exception
● It finally, returns the value to the caller
Skeleton (Server-side):
The skeleton is a proxy on the server side. It receives incoming requests, unmarshals the
parameters, invokes the method on the actual remote object, and marshals the result back to the
client. Note that in Java 2 SDK, the skeleton was replaced by a protocol that eliminates the need
for skeletons.
Working of Skeleton:
● It reads the parameters for the remote method.
● It invokes method on the actual remote object.
● It writes and transmits the result to the caller.
How they work together:
1. Client invokes method: The client application calls a method on the stub (which appears as a local
object).
2. Stub sends request: The stub serializes the method arguments and sends them over the network to
the server.
3. Skeleton receives request: The skeleton on the server receives the request, deserializes the
arguments, and invokes the corresponding method on the actual remote object.
4. Result returned: The result from the remote object is sent back to the stub through the skeleton.
5. Stub returns result: The stub deserializes the result and returns it to the client application.
Important considerations:
● RMI compiler (rmic): In Java, the "rmic" compiler is used to generate the stub and skeleton classes
from a remote interface definition.
● Transparency: The goal of using stubs and skeletons is to provide a transparent remote method
invocation experience for the developer, hiding the complexities of network communication.
RMI Registry
● The RMI registry is a namespace where server objects are registered. When a server creates
an object, it registers it with the RMI registry using a unique name. Clients can then look
up the remote object using this name to obtain a reference to the stub.
Steps to Create an RMI Application /
CREATING STUBS AND SKELETON
1. Define the Remote Interface: Create an interface that extends Remote and declare methods
that throw RemoteException.
import java.rmi.*;
public interface Adder extends Remote {
public int add(int x, int y) throws RemoteException;
}
2. Implement the Remote Interface: Provide the implementation of the remote interface by
extending UnicastRemoteObject.
import java.rmi.*;
import java.rmi.server.*;
public class AdderRemote extends UnicastRemoteObject implements
Adder {
AdderRemote() throws RemoteException {
super();
}
public int add(int x, int y) {
return x + y;
}
}
3. Generate Stub and Skeleton: Use the rmic tool to generate the stub and skeleton objects.
rmic AdderRemote
4. Start the RMI Registry: Start the registry service using the rmiregistry tool.
rmiregistry 5000
5. Create and Run the Server Application: Bind the remote object to the RMI registry.
import java.rmi.*;
import java.rmi.registry.*;
public class MyServer {
public static void main(String args[]) {
try {
Adder stub = new AdderRemote();
Naming.rebind("rmi://localhost:5000/sonoo", stub);
} catch (Exception e) {
System.out.println(e);
}
}
}
6. Create and Run the Client Application: Look up the remote object and invoke methods on it.
import java.rmi.*;
public class MyClient {
public static void main(String args[]) {
try {
Adder stub = (Adder) Naming.lookup("rmi://localhost:5000/sonoo");
System.out.println(stub.add(34, 4));
} catch (Exception e) {
System.out.println(e);
}
}
}
DISTRIBUTED APPLICATION ARCHITECTURE IN JAVA
Distributed application architecture refers to a design paradigm in which software
components are deployed across multiple computing nodes instead of a single machine. These
components interact over a network to function as a cohesive system.
Java provides several technologies to facilitate distributed computing, ensuring efficient
communication, load balancing, fault tolerance, and scalability.
Key Concepts in Distributed Application Architecture
1. Java RMI (Remote Method Invocation)
Java RMI enables distributed computing by allowing objects running in different JVMs (Java
Virtual Machines) to invoke methods remotely. It abstracts network communication so that
remote method calls appear as local method calls to the developer.
Key Characteristics:
• Facilitates object-oriented distributed computing.
• Uses serialization to transfer complex objects over the network.
• Provides built-in security mechanisms to prevent unauthorized access.
Example Use Case:
A distributed banking system where multiple clients interact with a central bank server to
check balances and perform transactions remotely.
2. CORBA (Common Object Request Broker Architecture)
CORBA is a middleware technology that enables applications written in different languages to
communicate over a network. It achieves interoperability using the Object Request Broker
(ORB) and interfaces defined with the Interface Definition Language (IDL).
Key Characteristics:
• Platform-independent – Enables interaction between Java, C++, Python, etc.
• Uses stub and skeleton for remote calls.
• Provides high-performance distributed computing for enterprise applications.
Example Use Case:
A multinational banking system where Java-based applications interact with C++ legacy
systems to process transactions securely.
3. Java Message Service (JMS)
JMS is a messaging standard in Java that enables asynchronous communication between
distributed components. It allows decoupling of applications by using message queues and
topics.
Key Characteristics:
• Supports Point-to-Point (Queue model) and Publish-Subscribe (Topic model)
messaging.
• Works with message brokers such as ActiveMQ, RabbitMQ, and Apache Kafka.
• Helps achieve scalability by ensuring high-volume message processing.
Example Use Case:
An e-commerce platform using JMS for order processing, where messages notify inventory,
payment, and shipping services asynchronously.
4. Microservices Architecture
Microservices architecture is a design approach where an application is divided into small,
independent services that communicate via APIs. Each microservice handles a specific business
functionality and can be deployed separately.
Key Characteristics:
• Uses REST APIs, Docker containers, and Spring Boot.
• Enables fault isolation – a failure in one service doesn’t impact others.
• Supports horizontal scalability, allowing services to expand independently.
Example Use Case:
A ride-sharing application with separate microservices for authentication, ride matching,
billing, and notifications.
5. Distributed Data Management
Distributed data management refers to storing and managing data across multiple nodes in a
network instead of a centralized database. It ensures fault tolerance, data availability, and
scalability.
Key Characteristics:
• Uses NoSQL databases (MongoDB, Cassandra) and distributed file systems
(Hadoop).
• Supports replication and partitioning to improve resilience.
• Follows eventual consistency models to synchronize distributed data.
Example Use Case:
A social media platform where user-generated content is stored across multiple data centers to
ensure availability and real-time access.
DEFINING REMOTE OBJECTS IN JAVA RMI
Java Remote Method Invocation (RMI) allows distributed applications to invoke methods on
remote objects residing in different Java Virtual Machines (JVMs). To define a remote object,
we need to:
1. Specify a remote interface.
2. Provide an implementation class.
3. Generate client stubs and server skeletons to facilitate communication.
Relationships Among Remote Object, Stub, and Skeleton
Illustration of how clients interact with remote objects via generated stubs and skeletons.
How Remote Objects Work
When a client obtains a reference to a remote object and invokes methods on it, the
method request must be transmitted to the actual object residing on the remote server. Likewise,
the results of the method call must be sent back to the client.
This process relies on:
• Client Stub: Sends method requests to the server.
• Server Skeleton: Receives requests and invokes methods on the actual object.
• RMI Compiler (rmic): Generates these stub and skeleton classes automatically.
Steps in RMI Communication
• Client invokes a method on the remote object.
• Stub marshals the method arguments and sends them over the network.
• Skeleton receives the request, unmarshals data, and invokes the actual method.
• Results are sent back to the client via the stub.
Defining a Remote Interface
A remote interface defines methods that can be invoked remotely. It must:
• Extend the java.rmi.Remote interface.
• Declare methods that throw java.rmi.RemoteException (or its parent classes).
Example: Remote Interface
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ThisOrThatServer extends Remote {
public String doThis(String task) throws RemoteException;
public String doThat(String task) throws RemoteException;
}
Implementing a Remote Object
The implementation class provides actual functionality for the remote methods.
Key Points:
✔ Must extend UnicastRemoteObject.
✔ Implement the remote interface.
✔ Declare a constructor that throws RemoteException.
Example: Implementation Class
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
public class ThisOrThatServerImpl extends UnicastRemoteObject
implements ThisOrThatServer {
public ThisOrThatServerImpl() throws RemoteException {}
public String doThis(String task) throws RemoteException {
return processTask("this", task);
}
public String doThat(String task) throws RemoteException {
return processTask("that", task);
}
private String processTask(String type, String task) {
return "Performed " + type + " on " + task;
}
}
Key RMI Classes for Remote Object Implementations
Java RMI provides several core classes to define remote object behavior:
1. RemoteObject
• Base class for all RMI remote objects.
• Implements equals(), hashCode(), and toString() for remote references.
2. RemoteServer
• An abstract class extending RemoteObject.
• Provides server-side support for managing remote connections.
3. UnicastRemoteObject
• Implements point-to-point remote references.
• Requires that remote objects exist only while the JVM is running.
• Non-persistent: Remote references become invalid when the server object is destroyed.
4. Activatable (Java 1.2+)
• Implements persistent remote references using the RMI activation daemon.
• Allows server objects to start automatically upon a client request.
OBJECT SERIALIZATION
Serialization and Deserialization in Java
Serialization in Java is the process of converting an object’s state into a byte-stream,
enabling it to be stored in a file or transmitted over a network. The reverse operation, called
Deserialization, reconstructs the object from the byte-stream.
Key Features:
• Used in Hibernate, RMI, JPA, EJB, JMS.
• Platform-independent (Serialize on one system, Deserialize on another).
• Uses java.io.Serializable interface to mark objects for serialization.
1. Java Serialization Process
Serialization is achieved using the writeObject() method of the ObjectOutputStream class,
while deserialization uses readObject() from the ObjectInputStream class.
(i) Implementing Java Serialization
To serialize an object, the class must implement the java.io.Serializable interface.
Example: Serializable Class
import java.io.Serializable;
public class Student implements Serializable {
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
Advantages of Java Serialization
✔ Data Persistence – Allows saving object state for future use.
✔ Network Communication – Used in RMI to send objects over a network.
✔ Interoperability – Supports cross-platform serialization and deserialization.
2. Java.io.Serializable Interface
The Serializable interface is a marker interface (i.e., contains no methods or fields)
used to flag classes for serialization.
Other Marker Interfaces in Java
• Cloneable – Allows object duplication.
• Remote – Enables remote object invocation in RMI.
By default, Java’s String class and wrapper classes implement Serializable.
3. Java ObjectOutputStream Class
The ObjectOutputStream class is used to write primitive data types and Java objects
to an output stream.
Constructor
public ObjectOutputStream(OutputStream out) throws IOException;
Creates an ObjectOutputStream that writes to the specified OutputStream.
Key Methods
Method Description
writeObject(Object obj) Serializes and writes the object.
flush() Clears the output stream.
close() Closes the output stream.
4. Java ObjectInputStream Class
The ObjectInputStream class deserializes objects previously written using
ObjectOutputStream.
Constructor
public ObjectInputStream(InputStream in) throws IOException;
Creates an ObjectInputStream that reads from the specified InputStream.
Key Methods
Method Description
readObject() Reads an object from the stream.
close() Closes the input stream.
5. Example: Java Serialization
Persist.java
import java.io.*;
class Persist {
public static void main(String args[]) {
try {
// Creating the object
Student s1 = new Student(211, "Ravi");
// Creating stream and writing the object
FileOutputStream fout = new FileOutputStream("f.txt");
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(s1);
out.flush();
// Closing the stream
out.close();
System.out.println("Serialization successful!");
} catch (Exception e) {
System.out.println(e);
}
}
}
Output:
Serialization successful!
JAVASPACES TECHNOLOGY
JavaSpaces technology is a high-level tool for building distributed applications, acting as
both a coordination mechanism and persistent object repository. Unlike traditional message
passing models such as RMI, JavaSpaces views applications as collections of processes that
exchange objects within one or more shared spaces.
Design Goals:
● Simplifies design and implementation of distributed computing.
● Minimal client-side classes for faster downloads and simple architecture.
● Lightweight memory footprint for resource-constrained environments.
● Supports replicated spaces for fault tolerance and scalability.
1. JavaSpaces vs. Databases
Although JavaSpaces enables persistent storage, it is not a database system and differs
significantly from relational and object-oriented databases.
Key Differences:
Feature JavaSpaces Relational Database Object Database
Data Manipulates
Stores object
Understan Stores objects by type structured data via
representations
ding SQL
Supports template- Uses SQL queries for Provides transparent
Querying
based exact matches flexible retrieval object persistence
Modificatio Objects must be Direct data In-memory object
n removed and rewritten manipulation modification
2. JavaSpaces Services & Operations
Processes interact with JavaSpaces services to store and coordinate objects rather than
communicating directly.
Primary Operations:
Operation Description
write() Adds a new object to a space.
take() Retrieves and removes an object from the space.
read() Creates a copy of an object from the space.
notify() Alerts a process when a matching entry is written.
Variants such as readIfExists() and takeIfExists() allow conditional access to objects.
Modification Approach:
JavaSpaces does not allow direct object modifications. To update an object:
1. Take the existing entry.
2. Modify it locally.
3. Rewrite it to the space.
3. JavaSpaces Application Model
JavaSpaces services store entries, which are structured objects implementing the
net.jini.core.entry.Entry interface.
Lookup Process:
1. Matching objects are found using templates.
2. Unspecified fields in templates act as wildcards.
3. read() retrieves objects; take() removes them permanently.
Distributed Events:
Processes can use the notify() method to receive alerts when matching entries are added.
4. JavaSpaces Technology Programming Model
Operations are executed on objects implementing net.jini.space.JavaSpace. Each entry is
a structured set of typed objects.
Example: Defining an Entry
import net.jini.core.entry.*;
public class MessageEntry implements Entry {
public String content;
public MessageEntry() {} // Default constructor
public MessageEntry(String content) {
this.content = content;
}
public String toString() {
return "MessageContent: " + content;
}
}
5. Writing & Reading from JavaSpaces
Writing to JavaSpaces
JavaSpace space = getSpace();
MessageEntry msg = new MessageEntry("Hello there");
space.write(msg, null, Lease.FOREVER); // Adds entry with an infinite
lease
✔ Entries are immutable once written.
✔ Each write() operation creates a new copy of an entry.
✔ Supports lease-based expiration (e.g., Lease.FOREVER or 60 * 60 * 1000 for
1-hour lease).
Reading from JavaSpaces
MessageEntry template = new MessageEntry(); // Wildcard template
MessageEntry output = (MessageEntry) space.read(template, null,
Long.MAX_VALUE);
✔ Reads matching entries using templates.
✔ Fields set to null act as wildcards.
6. Real-World Application Example: Multiuser Chat System
Using JavaSpaces technology, a multiuser chat system can be implemented as follows:
• Messages are written into a shared space.
• Participants read messages from the space.
• Users list stored entries to view previous conversations.
Unlike RMI, which requires explicit remote interfaces, JavaSpaces needs only one interface to
coordinate interactions.
Transactions in JavaSpaces Technology
The JavaSpaces API uses the package net.jini.core.transaction to provide atomic
transactions that group multiple operations across JavaSpaces services. This ensures that either
all modifications within a transaction are applied or none are, maintaining consistency and
reliability.
Key Features of Transactions in JavaSpaces:
✔ Supports atomic operations across multiple JavaSpaces services.
✔ Ensures all or nothing execution for transaction integrity.
✔ Transactions can span multiple spaces and participants.
✔ Uses null transactions as implicit single-operation transactions.
2. Transaction Behavior
When a read(), write(), or take() operation has a null transaction, it behaves as if it were
in a committed transaction containing just that operation.
Example: Implicit Single-Operation Transaction
✔ A take() operation with a null transaction acts as if:
• A transaction was created.
• The take() was performed under that transaction.
• The transaction was committed automatically.
Jini Outrigger JavaSpaces Service
The Jini Technology Starter Kit includes the package com.sun.jini.outrigger, which
provides JavaSpaces-enabled services for distributed computing.
Implementation Options:
✔ Transient Space – Loses its state between executions (TransientOutriggerImpl).
✔ Persistent Space – Maintains state across executions (PersistentOutriggerImpl).
Compiling and Running the SpaceClient Application
1. Compilation Steps
To compile and run the sample application, follow these steps:
Step 1: Compile MessageEntry.java
javac -classpath <pathToJiniInstallation\lib\jini-ext.jar>
MessageEntry.java
✔ Ensure jini-ext.jar is in your classpath (found in the starter kit's lib directory).
Step 2: Compile SpaceClient.java
✔ The SpaceClient.java file uses a utility class (Lookup.java) to discover a JavaSpaces
service. ✔ Compile both SpaceClient.java and Lookup.java together.
javac -classpath <pathToJiniInstallation\lib\jini-ext.jar>
SpaceClient.java Lookup.java
✔ Include MessageEntry.class in your classpath before compiling SpaceClient.java.
2. Running the Application
Step 1: Start Jini Services
✔ Run Launch-All (from the installverify directory) to start the Jini
Service Browser
✔ This starts six Jini network services, including JavaSpaces.
Step 2: Execute SpaceClient
java -classpath .\;
..\lib\jini-ext.jar;
..\lib\reggie.jar;
..\lib\outrigger.jar SpaceClient