Ejemplo oficial de RMI en Java

18.11.08. Por ooscarr (ooscarr)

Se me pidió implementar un ejemplo de comunicación RMI en Java para un curso de Sistemas distribuidos. Y como estaba en inglés, traduzco el ejemplo que encontré en tutorial de introducción oficial de Java™ RMI. El famoso Hello, world

Los códigos

Lamentablemente, por la licencia, debo poner todos los comentarios iniciales correspondientes a los disclaimer, así que por eso se ven largos los códigos.

Hola.java

/*
 * Copyright 2004 Sun Microsystems, Inc. All  Rights Reserved.
 *  
 * Redistribution and use in source and binary forms, with or 
 * without modification, are permitted provided that the following 
 * conditions are met:
 * 
 * -Redistributions of source code must retain the above copyright  
 *  notice, this list of conditions and the following disclaimer.
 * 
 * -Redistribution in binary form must reproduce the above copyright 
 *  notice, this list of conditions and the following disclaimer in 
 *  the documentation and/or other materials provided with the 
 *  distribution.
 *  
 * Neither the name of Sun Microsystems, Inc. or the names of 
 * contributors may be used to endorse or promote products derived 
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
 * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
 * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *  
 * You acknowledge that Software is not designed, licensed or 
 * intended for use in the design, construction, operation or 
 * maintenance of any nuclear facility.
 */
package ejemplo.hola;

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

public interface Hola extends Remote {
    String diHola() throws RemoteException;
}

Servidor.java

/*
 * Copyright 2004 Sun Microsystems, Inc. All  Rights Reserved.
 *  
 * Redistribution and use in source and binary forms, with or 
 * without modification, are permitted provided that the following 
 * conditions are met:
 * 
 * -Redistributions of source code must retain the above copyright  
 *  notice, this list of conditions and the following disclaimer.
 * 
 * -Redistribution in binary form must reproduce the above copyright 
 *  notice, this list of conditions and the following disclaimer in 
 *  the documentation and/or other materials provided with the 
 *  distribution.
 *  
 * Neither the name of Sun Microsystems, Inc. or the names of 
 * contributors may be used to endorse or promote products derived 
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
 * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
 * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *  
 * You acknowledge that Software is not designed, licensed or 
 * intended for use in the design, construction, operation or 
 * maintenance of any nuclear facility.
 */
package ejemplo.hola;

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class Servidor implements Hola{

 public Servidor() {}

 public String diHola(){
  return "Hola, mundo";
 }

 public static void main(String args[]){

  try {
   Servidor obj = new Servidor();
   Hola stub = (Hola) UnicastRemoteObject.exportObject(obj, 0);

   // Liga los datos (stub) del objeto remoto en el registro
   Registry registro = LocateRegistry.getRegistry();
   registro.bind("Hola",stub);

   System.err.println("Servidor listo");
  } catch (Exception e) {
   System.err.println("Excepción del servidor: " + e.toString());
   e.printStackTrace();
  }
 }
}

Cliente.java

/*
 * Copyright 2004 Sun Microsystems, Inc. All  Rights Reserved.
 *  
 * Redistribution and use in source and binary forms, with or 
 * without modification, are permitted provided that the following 
 * conditions are met:
 * 
 * -Redistributions of source code must retain the above copyright  
 *  notice, this list of conditions and the following disclaimer.
 * 
 * -Redistribution in binary form must reproduce the above copyright 
 *  notice, this list of conditions and the following disclaimer in 
 *  the documentation and/or other materials provided with the 
 *  distribution.
 *  
 * Neither the name of Sun Microsystems, Inc. or the names of 
 * contributors may be used to endorse or promote products derived 
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
 * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
 * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *  
 * You acknowledge that Software is not designed, licensed or 
 * intended for use in the design, construction, operation or 
 * maintenance of any nuclear facility.
 */
package ejemplo.hola;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Cliente {
 
 private Cliente() {}
 
 public static void main(String[] args){
  
  String host = (args.length < 1) ? null : args[0];
  try {
   Registry registro = LocateRegistry.getRegistry(host);
   Hola stub = (Hola) registro.lookup("Hola");
   String respuesta = stub.diHola();
   System.out.println("respuesta: " + respuesta);
  } catch (Exception e) {
   System.err.println("Exception del cliente: " + e.toString());
   e.printStackTrace();
  }
    }
}

Cómo compilarlo y ejecutarlo

Para compilarlo, sólo hay que ejecutar el comando usual:

javac -d clases Hola.java Servidor.java Cliente.java

El directorio donde se guardarán las clases (en este ejemplo llamado clases debe existir previamente.

El árbol con los archivos debería quedar como en la siguiente imagen:

Captura de pantalla del contenido de la carpeta del proyecto: 3 archivos .java más un subdirectorio ejemplo/hola/ con 3 archivos .class en él
Repito. La carpeta clases debe existir previamente.

Para ejecutar este ejemplo, se necesita hacer lo siguiente:

  • Iniciat el registro Java RMI
  • Iniciar el servidor
  • Ejecutar el cliente

Iniciar el registro Java RMI

Para iniciar el registro, ejecuta el comando rmiregistry en el host del servidor. Este comando no produce ningún mensaje de salida (cuando es satisfactorio) y típicamente corre en background. Para más informción, vea la documentación de las herramientas de rmiregistry [paraSolaris, Windows].

Por ejemplo, en Solaris™:

rmiregistry &

En OS X con Java 5 por lo menos es igual que en Solaris pero sin el &

rmiregistry

O, en la plataforma Windows:

start rmiregistry 

Por defecto, el registro corre en el puerto TCP 1099. Para iniciar un registro en un puerto diferente, especifica el número de puerto desde la línea de comandos. Por ejemplo, para iniciar el registro en el puerto 2001 sobre la plataforma Windows:

start rmiregistry 2001

Si el registro estará ejecutándose en un puerto distinto del 1099, necesitarás especificar el número de puerto en las llamadas a LocateRegistry.getRegistry en las clases Server y Client. Por ejemplo, si el registro está ejecutándose sobre el puerto 2001 en este ejemplo, la llamada a getRegistry en el servidor sería:

Registry registry = LocateRegistry.getRegistry(2001);

Iniciar el servidor

Para iniciar el servidor, ejecuta la clase Servidor usando el comando java siguiente:

En Solaris:

java -classpath clases -Djava.rmi.server.codebase=file:clases/ ejemplo.hola.Servidor &

En OS X:

java -classpath clases -Djava.rmi.server.codebase=file:clases/ ejemplo.hola.Servidor

Bajo la plataforma Windows:

start java -classpath clases -Djava.rmi.server.codebase=file:clases/ ejemplo.hola.Servidor

donde clases es el directorio raíz del árbol de archivos de las clases (el mismo clases de cuando fueron compilados los archivos fuentes). Definiendo la propiedad de sistema java.rmi.server.codebase asegura que el registro pueda cargar la definición de interfaz remota (ojo que el slash final es importante).

La salida del servidor debería verse como esto:

Servidor listo

El servidor mantiene ejecutándose hasta que el proceso es terminado por el usuario (típicamente matando al proceso).

Ejecutar el cliente

Una vez que el servidor está listo, el cliente puede ser ejecutado de la siguiente forma:

java -classpath clases ejemplo.hola.Cliente

donde clases es el directorio raíz del árbol de archivos de las clases (el mismo clases de cuando fueron compilados los archivos fuentes).

La salida del cliente es el siguiente mensaje:

respuesta: Hola, mundo

Referencias

Etiquetas: ,

3 comentarios (RSS ATOM) :

  1. A las 4/5/09 09:36  

    Anonymous Anónimo ha dicho...

    mu bien

  2. A las 10/9/09 22:54  

    Anonymous Anónimo ha dicho...

    como se ejecuta en dos maquinas?

  3. A las 10/9/09 23:08  

    Blogger ooscarr ha dicho...

    De acuerdo al código fuente, al momento de ejecutar el cliente se le agrega un argumento con la IP del servidor. No lo he probado. Podría ser así

    java -classpath clases ejemplo.hola.Cliente 110.etc.23.etc

Página principal

Publicidad