"¡Hola! Y un tema más feliz: RMI. RMI significa Invocación de método remoto . En otras palabras, RMI es un mecanismo que permite que un objeto de una máquina Java llame a métodos en objetos de otra máquina Java , incluso si están en diferentes computadoras, en diferentes países, o en diferentes partes del mundo".

RMI - 1

"¡Vaya! Eso suena increíble".

"Sí. Pero solo intentaré darte una descripción general. Con esto, si profundizas demasiado, puedes confundirte con los matices de cómo funciona".

"Pero si no se va a los extremos, entonces RMI no solo es muy simple, sino que también simplifica enormemente la vida de un programador. Por lo cual, le presentamos nuestros más profundos respetos".

"Entonces, queremos que un objeto en un programa Java llame a un método en un objeto que está en otro programa Java. Independientemente de dónde se ejecuten estos programas".

"Consideremos el ejemplo más simple: cuando ambos programas se ejecutan en la misma computadora.  Para permitir que los programas interactúen a través de Internet, debe configurar los permisos de JVM , pero no lo cubriremos hoy".

"En Java, puede llamar de forma remota solo a los métodos de las interfaces, no a las clases".

"Entonces, tenemos dos programas. ¿Cómo pueden llamarse los métodos del otro?"

"Consideremos la situación en la que un programa contiene un objeto y un segundo programa quiere llamar a métodos en ese objeto. Llamemos al primer programa el servidor y al segundo, el cliente" .

"Primero, proporcionaré un código de muestra y luego lo analizaremos".

"Entonces, ¿qué hará nuestro programa?"

"Hmm. Bueno, para simplificar, el programa tendrá un método que invierte una cadena que se le pasa".

"Suficientemente simple."

"Bien, entonces comencemos:"

"Primero, necesitamos una interfaz que satisfaga nuestros requisitos:"

Interfaz para la comunicación entre programas
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

"Creé una interfaz inversa y le agregué una interfaz de marcador remoto, así como una excepción remota. Pueden ocurrir errores inesperados cuando se llama al método. Si lo hace, se lanzará esta excepción".

"Ahora necesitamos escribir una clase de servidor que implemente esta interfaz:"

Clase para el servidor
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

"Ya veo. Invertimos la cuerda en este método".

"Sí."

"Ahora necesitamos hacer que este objeto se pueda llamar desde otro programa. Así es como lo haces:"

compartir objetos
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create an object to be accessible remotely.
 final ReverseImpl service = new ReverseImpl();

 // Create a registry of shared objects.
 final Registry registry = LocateRegistry.createRegistry(2099);
 // Create a stub for receiving remote calls.
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 // Register the stub in the registry.
 registry.bind(UNIC_BINDING_NAME, stub);

 // Put the main thread to sleep, or else the program will exit.
 Thread.sleep(Integer.MAX_VALUE);
}

"Explicaré esto línea por línea".

" En la línea 1 , almacenamos un nombre único (que inventamos) para nuestro objeto remoto (objeto que es accesible de forma remota) en la variable  UNIC_BINDING_NAME . Si el programa hace accesibles varios objetos, cada uno debe tener su propio nombre único. El nuestro el nombre único del objeto es 'server.reverse'".

" En la línea 6 creamos un objeto ReverseImpl al que se podrá acceder de forma remota. Se invocarán sus métodos".

" En la línea 9 creamos un objeto especial llamado registro. Necesitamos usarlo para registrar los objetos que compartimos. La JVM interactuará con ellos más adelante. 2099 es un puerto (un número único que otro programa puede usar para acceder a nuestro registro de objetos)".

"En otras palabras, para acceder a un objeto, debe conocer el número único (puerto) del registro del objeto y el nombre único del objeto, y tener la misma interfaz que la implementada por el objeto remoto".

"Ya veo. Algo como: llamar por teléfono (necesito un número) y preguntar por Bill (el nombre de un objeto)?"

"Sí. Ahora, sigamos".

" En la línea 11  , creamos un stub. Un stub es un objeto especial que recibe información sobre la llamada remota, la desempaqueta, deserializa los argumentos del método y llama al método requerido. Luego, serializa el resultado o la excepción, si la hubo. y lo devuelve todo a la persona que llama".

"Ya veo. Casi. Dijiste que 'deserializa los argumentos del método'. Entonces, ¿eso significa que los argumentos de los métodos remotos deben ser serializables?"

"Sí. ¿De qué otra forma los enviaría a través de la red? Es cierto que hay excepciones, es decir, objetos que se pasan por referencia, pero no hablaremos de ellos hoy".

"Lo pondremos así: no puedes pasar objetos no serializables, pero si realmente quieres, entonces puedes. Pero es un dolor, ya sabes".

"DE ACUERDO."

"Entonces sigamos".

" En la línea 13 , registramos el stub de nuestro objeto con un nombre único en el registro".

" En la línea 16 , ponemos el subproceso principal en suspensión. Todas las llamadas remotas se procesan en subprocesos separados. Lo importante es que el programa se está ejecutando. Así que simplemente ponemos el subproceso principal en suspensión aquí. Eso es todo".

"DE ACUERDO."

"Genial, entonces aquí hay un ejemplo de un cliente:"

Trabajando con un objeto remoto
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create a registry of shared objects
 final Registry registry = LocateRegistry.createRegistry(2099);

 // Get the object (actually, this is a proxy object)
 Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);

 // Call the remote method
 String result = service.reverse("Home sweet home.");
}

"Explicaré este código línea por línea:"

" La línea 1 es el nombre exclusivo  del objeto remoto . Debe ser el mismo tanto en el cliente como en el servidor".

" En la línea 6  , creamos un « registro de objetos remotos ». Su puerto (2099) debe ser el mismo que el puerto del registro para la aplicación del servidor."

" En la línea 9 , obtenemos el objeto del registro. El objeto devuelto es un objeto proxy y se convierte en una interfaz. La interfaz debe heredar la interfaz del marcador remoto".

" En la línea 12 , llamamos a los métodos de la interfaz como si el objeto se hubiera creado dentro del mismo programa. No hay diferencia".

"¡Genial! Ahora puedo escribir aplicaciones distribuidas. O juegos como Battleship para Android".

"¡No te atrevas, Amigo! El sistema operativo Android fue prohibido en el siglo 27 después de su tercer intento de apoderarse del mundo. Los robots no tienen acceso a él en absoluto. No habría forma de alejarte de él". Empezarías a correr gritando: «¡Matad a todos los humanos!»”

"Hmm. Está bien. Pero aún tendré que preguntarle a Diego. Nunca se sabe, tal vez tenga algo interesante que decir al respecto".

"Entonces ve a preguntarle. Está bien, bueno, hasta mañana".

"Adiós, Rishi. Gracias por la interesante lección".