Tabla de Contenidos

RMI: Remote Method Invocation

Diferencias con la programación local

Arquitectura

Tenemos dos conceptos principales: Definición de comportamiento e implementación de comportamiento

dad:diagram1.png

Tres capas

dad:diagramadecapas.png

Servicio de Nombres

Como Buscar

rmi://<host_name>[:puerto del servicio de directorio]/<nombre del servicio>

Distribución de clases

Implementación Servidor

En este ejemplo implementaremos una calculadora en un servidor que será utilizada por un cliente.

Interfaz Servidor

La interfaz debe heredar de java.rmi.Remote

InterfazSertvidor.jar
public interface InterfazServidor extends java.rmi.Remote{
public long sumar(long a, long b)
  throws java.rm.RemoteException;
 
public long restar (long a, long b)
  throws java.rm.RemoteException;
 
public long multiplicar ()
  throws java.rmi.RemoteException;
 
public long dividir()
  throws java.rmi.RemoteException;
 
}

Implementación Servidor

Aquí implementaremos las funciones de la interfaz del servidor. Se debe heredar de UnicastRemoteObject con un Extends e indicar que se va a implementar la interface anterior con Implements:

ImplementacionInterfaceServidor.jar
public class ImplementacionInterfaceServidor extends UnicastRemoteObject implements InterfazServidor{
  private static final long serialVersionUID = 1L;
 
  public implementacion() throws RemoteException{
    super();
  }
 
  public long sumar(long a, long b) throws RemoteException{
    return a+b;
  }
 
  public long restar(long a, long b) throws RemoteException{
    return a-b;
  }
 
  public long multiplicar (long a, long b) throws RemoteException{
    return a*b;
  }
 
  public long dividir (long a, long b) throws RemoteExcepcion{
    return a/b;
  }
 
}

Implementación servidor

Server.jar
public class Server(){
  public server(){
    try{
 
      //creamos el servicio en el puerto 1099
      LocateRegistry.createRegistry(1099);
      //creamos un nuevo objeto con la funcionalidad
      InterfazServidor is = new ImplementacionInterfaceServidor();
      //Vinculamos el objeto a un nombre de servicio poniendo la URL de este y el objeto
      //Ejemplo de URL("RMI://localhost:1099/Nombre_del_Servicio")
      Naming.rebind("RMI://localhost:1099/CalculatorService", is);//este sería el Stub
 
    }catch (Exception e){
      System.out.println("Error en el servidor: " + e);
    }
  }
 
  public static void main(String args[]){
    new Server();
  }
 
}

Implementación Cliente

Client.jar
public class Client{
  public static void main(String[] args){
    try{
      //Con Naminglookup(URL del RMI) el cliente busca el servicio
      //Formato de la URL: RMI://localhost:puerto/nombre_del_servicio
      InterfazServidor is = (InterfazServidor)Naming.lookup("RMI://localhost:1099/CalculatorService");//esto es un Stub
 
      System.out.println(is.sumar(3,4));
      System.out.println(is.restar(7,2));
      System.out.println(is.multiplicar(8,5));
      System.out.println(is.dividir(4,2));
    }catch(Exception e){
      System.out.println("Error en el cliente");
      e.printStackTrace();
    }
 
  }
}

Soluciones a Errores comunes

Unable to make public abstract boolean

En el archivo module-info.java debemos revisar que se esté exportando el paquete

module-info.java
module nombre_proyecto {
    exports nombre_paquete;
}