# java.rmi

***

**1. Remote Object Invocation (RMI) with Simple Data Types**

```java
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

// Define the remote interface.
interface RemoteInterface {
    int add(int a, int b);
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}

// Create the remote object and register it with the RMI registry.
RemoteInterface remoteObject = new RemoteObject();
Registry registry = LocateRegistry.createRegistry(1099);
registry.bind("RemoteObject", remoteObject);

// Get the remote object from the RMI registry and invoke its method.
RemoteInterface stub = (RemoteInterface) registry.lookup("RemoteObject");
int result = stub.add(5, 7);
System.out.println(result); // Output: 12
```

**2. RMI with Custom Data Types**

```java
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

// Define the remote interface.
interface RemoteInterface {
    Employee getEmployee(int empId);
}

// Define the data type to be passed through RMI.
class Employee implements java.io.Serializable {
    private int empId;
    private String name;

    // Constructor, getters, setters...
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public Employee getEmployee(int empId) {
        // Logic to get the employee by ID.
        return employee;
    }
}

// Create the remote object and register it with the RMI registry.
RemoteInterface remoteObject = new RemoteObject();
Registry registry = LocateRegistry.createRegistry(1099);
registry.bind("RemoteObject", remoteObject);

// Get the remote object from the RMI registry and invoke its method.
RemoteInterface stub = (RemoteInterface) registry.lookup("RemoteObject");
Employee employee = stub.getEmployee(12345);
System.out.println(employee.getName());
```

**3. RMI with Method Overloading**

```java
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

// Define the remote interface.
interface RemoteInterface {
    int add(int a, int b);
    int add(float a, float b);
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int add(float a, float b) {
        return (int) (a + b);
    }
}

// Create the remote object and register it with the RMI registry.
RemoteInterface remoteObject = new RemoteObject();
Registry registry = LocateRegistry.createRegistry(1099);
registry.bind("RemoteObject", remoteObject);

// Get the remote object from the RMI registry and invoke its methods.
RemoteInterface stub = (RemoteInterface) registry.lookup("RemoteObject");
int result1 = stub.add(5, 7); // Integer addition
int result2 = stub.add(3.5f, 4.7f); // Floating-point addition
System.out.println(result1); // Output: 12
System.out.println(result2); // Output: 8
```

**4. RMI with Exception Handling**

```java
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

// Define the remote interface.
interface RemoteInterface {
    int add(int a, int b) throws RemoteException;
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public int add(int a, int b) throws RemoteException {
        if (a < 0 || b < 0) {
            throw new ArithmeticException("Negative numbers not allowed");
        }
        return a + b;
    }
}

// Create the remote object and register it with the RMI registry.
RemoteInterface remoteObject = new RemoteObject();
Registry registry = LocateRegistry.createRegistry(1099);
registry.bind("RemoteObject", remoteObject);

// Get the remote object from the RMI registry and invoke its method.
RemoteInterface stub = (RemoteInterface) registry.lookup("RemoteObject");
try {
    int result = stub.add(5, 7);
    System.out.println(result); // Output: 12
} catch (RemoteException e) {
    System.out.println("Error: " + e.getMessage()); // Output: Error: Negative numbers not allowed
}
```

**5. RMI with Security Manager**

```java
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.security.Policy;
import java.security.ProtectionDomain;

// Define the remote interface.
interface RemoteInterface {
    int add(int a, int b);
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}

// Define a custom security manager.
class MySecurityManager extends SecurityManager {
    @Override
    public void checkPermission(Permission perm, Object context) {
        // Allow specific permissions.
    }
}

// Create the remote object and register it with the RMI registry.
System.setSecurityManager(new MySecurityManager());
RemoteInterface remoteObject = new RemoteObject();
Registry registry = LocateRegistry.createRegistry(1099);
registry.bind("RemoteObject", remoteObject);

// Get the remote object from the RMI registry and invoke its method.
RemoteInterface stub = (RemoteInterface) registry.lookup("RemoteObject");
stub.add(5, 7); // Will be allowed if granted the appropriate permission
```

**6. RMI with Client Callback**

```java
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

// Define the remote interface for the client.
interface ClientInterface {
    void update(String message);
}

// Implement the client callback object.
class ClientObject implements ClientInterface {
    @Override
    public void update(String message) {
        // Handle the received message.
    }
}

// Define the remote interface for the server.
interface ServerInterface {
    void registerClient(ClientInterface client);
    void sendMessage(String message);
}

// Implement the server object.
class ServerObject implements ServerInterface {
    private List<ClientInterface> clients;

    @Override
    public void registerClient(ClientInterface client) {
        clients.add(client);
    }

    @Override
    public void sendMessage(String message) {
        for (ClientInterface client : clients) {
            client.update(message);
        }
    }
}

// Create the server object and register it with the RMI registry.
ServerInterface serverObject = new ServerObject();
Registry registry = LocateRegistry.createRegistry(1099);
registry.bind("ServerObject", serverObject);

// Create the client object and register itself with the server.
ClientInterface clientObject = new ClientObject();
registry.bind("ClientObject", clientObject);
serverObject.registerClient(clientObject);

// Server sends a message to the client, which gets displayed.
serverObject.sendMessage("Hello, client!");
```

**7. RMI with Activation**

```java
import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationException;
import java.rmi.activation.ActivationGroupID;
import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationMonitor;
import java.rmi.activation.ActivationSystem;
import java.rmi.activation.UnknownObjectException;
import java.rmi.server.UnicastRemoteObject;

// Define the remote interface.
interface RemoteInterface {
    int add(int a, int b);
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}

// Create the activation descriptor and register it with the Activation System.
ActivationDesc activationDesc = new ActivationDesc(
    "com.example.RemoteObject",
    null, // Constructor arguments (null for no-arg constructor)
    null, // Location of the class (null for default)
    null // Group ID (null for new group)
);
ActivationSystem.registerActivationDesc(activationDesc);

// Create the remote object and export it.
RemoteInterface remoteObject = new RemoteObject();
UnicastRemoteObject.exportObject(remoteObject, 0);

// Get the activation ID and group ID.
ActivationGroupID activationGroupID = activationDesc.getGroupID();
ActivationID activationID = activationDesc.getActivationID();

// Deactivate the object.
ActivationMonitor.deactivationEvent(activationGroupID, activationID);
```

**8. RMI with Live Refreshable Classes**

```java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.rmi.server.UnicastRemoteObject;

// Define the remote interface.
interface RemoteInterface {
    int add(int a, int b);
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}

// Create the remote object and register it with the RMI registry.
RemoteInterface remoteObject = new RemoteObject();
UnicastRemoteObject.exportObject(remoteObject, 0);

// Get the URL of the class to refresh.
URL url = new URL("file:RemoteObject.class");

// Create a new class loader.
URLClassLoader classLoader = new URLClassLoader(new URL[]{url});

// Get the class from the new class loader.
Class<?> refreshedClass = classLoader.loadClass("RemoteObject");

// Get the method from the refreshed class.
Method addMethod = refreshedClass.getMethod("add", int.class, int.class);

// Invoke the method on the refreshed object.
int result = (int) addMethod.invoke(remoteObject, 5, 7);
System.out.println(result); // Output: 12
```

**9. RMI with JNDI Lookup**

```java
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

// Get the remote object from the JNDI registry.
Context context = new InitialContext();
RemoteInterface remoteObject = (RemoteInterface) context.lookup("java:global/RemoteObject");

// Invoke the method on the remote object.
int result = remoteObject.add(5, 7);
System.out.println(result); // Output: 12
```

**10. RMI with Remote Event Handling**

```java
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.EventListener;

// Define the remote interface for the event listener.
interface RemoteEventListener extends EventListener {
    void onEvent(String message);
}

// Implement the remote event listener.
class RemoteEventListenerImpl implements RemoteEventListener {
    @Override
    public void onEvent(String message) {
        // Handle the event.
    }
}

// Define the remote interface for the event generator.
interface RemoteEventGenerator extends Remote {
    void addEventListener(RemoteEventListener listener) throws RemoteException;
    void removeEventListener(RemoteEventListener listener) throws RemoteException;
    void fireEvent(String message) throws RemoteException;
}

// Implement the remote event generator.
class RemoteEventGeneratorImpl extends UnicastRemoteObject implements RemoteEventGenerator {
    private List<RemoteEventListener> listeners;

    public RemoteEventGeneratorImpl() throws RemoteException {
        listeners = new ArrayList<>();
    }

    @Override
    public void addEventListener(RemoteEventListener listener) throws RemoteException {
        listeners.add(listener);
    }

    @Override
    public void removeEventListener(RemoteEventListener listener) throws RemoteException {
        listeners.remove(listener);
    }

    @Override
    public void fireEvent(String message) throws RemoteException {
        for (RemoteEventListener listener : listeners) {
            listener.onEvent(message);
        }
    }
}

// Create the remote event generator and register it with the RMI registry.
RemoteEventGenerator remoteEventGenerator = new RemoteEventGeneratorImpl();
UnicastRemoteObject.exportObject(remoteEventGenerator, 0);

// Create the remote event listener and register it with the remote event generator.
RemoteEventListener remoteEventListener = new RemoteEventListenerImpl();
remoteEventGenerator.addEventListener(remoteEventListener);

// Fire an event on the remote event generator.
remoteEventGenerator.fireEvent("Hello, world!"); // The event listener will receive this message.
```

**11. RMI with Serialization**

```java
import java.io.Serializable;

// Define a serializable class.
class Employee implements Serializable {
    private int empId;
    private String name;

    // Constructor, getters, setters...
}

// Define the remote interface.
interface RemoteInterface {
    Employee getEmployee(int empId);
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public Employee getEmployee(int empId) {
        // Logic to get the employee by ID.
        return employee;
    }
}

// Create the remote object and register it with the RMI registry.
RemoteInterface remoteObject = new RemoteObject();
UnicastRemoteObject.exportObject(remoteObject, 0);
```

**12. RMI with HTTP Tunneling**

```java
import java.rmi.Remote;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;

// Define the remote interface.
interface RemoteInterface {
    int add(int a, int b);
}

// Implement the remote object.
class RemoteObject implements RemoteInterface {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}

// Create the remote object and register it with the RMI registry.
System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
SslRMIClientSocketFactory clientSocketFactory = new SslRMIClientSocketFactory();
SslRMIServerSocketFactory serverSocketFactory = new SslRMIServerSocketFactory();
Registry registry = LocateRegistry.createRegistry(1099, clientSocketFactory, serverSocketFactory);
RemoteInterface remoteObject = new RemoteObject();
UnicastRemoteObject.exportObject(remoteObject, 0, clientSocketFactory, serverSocketFactory);
registry.bind("RemoteObject", remoteObject);
```

**13. RMI with JRMP Protocol**
