Exponiendo y consumiendo servicios remotos RMI de Java

2021-12-19 - Categorías: Java
Java

Esto es un codekata, apunte o resumen sobre esta funcionalidad de Java. Resumiendo, Java RMI es una funcionalidad que viene implementada de casa, mediante la cual podemos conectar servicios distribuidos, de forma que las funciones programadas se pueden ejecutar desde cualquier programa en cualquier servidor.

Es decir, RMI significa Remote Method Invocation, entonces tenemos que mediante estos mecanismos podemos declarar funciones en objetos de Java, y exponerlos a la Red para ser utilizados por procesos remotos. Se consigue de esta forma transparente para el programador, que se lancen acciones en servidores remotos. Así se puede escalar los procesos entre varios servidores, distribuyendo la carga y funcionalidades.

Es más fácil leer el fuente que explicarlo, al grano..

Estructurando proyecto en paquetes

Por probar cómo queda la visibilidad entre los códigos fuentes se podrían establecer tres paquetes:

  • Un servidor: rmiserver
  • Un cliente: rmiclient
  • Contratos de uso: rmicommon

Los contratos de uso son Interfaces en Java en este caso, para especificar lo que hay que implementar. En este caso, el cliente no necesita saber nada más que cuales son los contratos disponibles en ServiceInterface.java para usarlos. El servidor que expone el servicio RMI tiene que saber los contratos, y además lo implementa en ServiceImpl.java.

El código fuente implementado en el servidor, aunque se lance la llamada al servicio desde el cliente, se ejecuta en el servidor. Se puede también devolver resultados al cliente que lanza la invocación de los métodos remotos, y es aquí su mayor utilidad de todo esto.

Una forma de estructura puede ser la siguiente:

La declaración de contratos, las funciones, para el servicio que exponemos para invocación remota

En rmicommon sólo tenemos declarado el contrato del servicio que se expone. Simplemente especifica los métodos que se van a poder invocar de forma remota. Está en rmicommon porque lo usa rmiclient y rmiserver en forma de interfaz de comunicación:

package rmicommon;

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

public interface ServiceInterface extends Remote {
    public void sayHello() throws RemoteException;
}

El código fuente del servidor

package rmiserver;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import rmicommon.*;

public class Server {
    static ServiceImpl service;
    static String localServiceName = "rmi://localhost:8080/TheService";

    public static void main(String[] args) {
        service = new ServiceImpl();

        try {
            Registry registry = LocateRegistry.createRegistry(8080);

            ServiceInterface stubService = (ServiceInterface) UnicastRemoteObject.exportObject(service, 0);
            registry.rebind(localServiceName, stubService);
            for (String string : registry.list()) {
                System.out.println(string);
            }
            
            System.console().readLine("Finish? ");

            UnicastRemoteObject.unexportObject(service, true);
            Naming.unbind(localServiceName);
        } catch (Exception e) {
            System.out.println("ERROR: " + e.toString());
        }
    }
}

El código fuente del cliente

package rmiclient;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import rmicommon.*;

public class Client {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost", 8080);

            ServiceInterface service = (ServiceInterface) Naming.lookup("rmi://localhost:8080/TheService");

            service.sayHello();
            service.sayHello();
            service.sayHello();
        } catch (Exception e) {
            System.out.println("ERROR: " + e.toString());
        }
    }
}

La implementación del servicio

package rmiserver;

import java.rmi.RemoteException;
import rmicommon.*;

public class ServiceImpl implements ServiceInterface {
    public void sayHello() throws RemoteException {
        System.out.println("Hello!");
    }
}

Ejecutando desde el cliente, el método remoto, en el servidor

Lo siguiente es la ejecución del cliente anterior. Importante, primero hay que arrancar el servidor para que se ponga a la escucha usando RMI. Luego se lanza el cliente, que necesitará conectar al servidor. Este código sólo funciona para correr en localhost los dos procesos, lo mismo sería en distintos servidores.

El cliente no escribe nada por pantalla con la invocación del método remoto service.sayHello(), porque el método remoto se ejecuta realmente en el servidor:

Ejecución del cliente RMI..

Lo siguiente es lo que se ve en el servidor. Se invoca desde el cliente, se ejecuta el método sayHello() en el servidor, y es en el servidor en donde se escribe por pantalla:

Java RMI basic usage
Ejecución del servidor RMI, viendo resultado del método invocado desde el cliente..

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

© 2024 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.