RMI 1 RMI Los sistema tradicionales de ejecución de código en otros equipos informáticos a través de conexiones de red siempre han sido motivo de confusión y mal interpretación. La mejor manera de pensar en una aplicación distribuida en red es considerar que un objeto vive en una máquina remota y que tú puedes enviarle un mensaje y obtener un resultado como si el objeto viviera en tu mismo equipo. Esta simplificación del problema es precisamente lo que hace RMI. RMI significa REMOTE METHODS INVOCATION. En RMI se utilizan interfaces. Se crean objetos remotos a los que se oculta bajo una interfaz que se pasará a los clientes. El cliente recogerá una referencia al objeto remoto aunque utilice una interfaz. La interfaz será un sistema llamado Stub el cual se encargará de conectar (STUB) con el objeto remoto. 2 Representación gráfica de una comunicación RMI port=1099 port=900 3 La interfaz La interfaz se desarrollará según las siguientes condiciones. 1. Tiene que ser public. 2. Tiene que heredar de java.rmi.Remote. 3. Cada método de la interfaz tiene que declarar: throws java.rmi.RemoteException 4. Tiene que declarar los métodos que se quieren exponer a los clientes. 4 La clase de implementación La clase se desarrollará según las siguientes condiciones. 1. Tiene que implementar todos los métodos declarados en la interfaz (implements). 2. Tiene que heredar de UnicastRemoteObject. 5 Stub y Skeleton Las dos clases se generan automáticamente con el programa rmic. rmic ClaseImplementación La clase Stub tendrá que copiarse en el ordenador del cliente. 6 java.rmi.registry.Registry • Para que los clientes puedan acceder a un objeto remoto se necesita un servicio de directorio (registro). • El servicio de directorio es una tabla de tipo Hash con parejas del tipo “nombre/referencia” • El registro RMI se ejecuta en la máquina que alberga los objetos remotos. 7 Name Service El RMI Registry se puede arrancar desde una ventana dos (rmiregistry) O se puede ejecutar automáticamente desde el mismo servidor: try{ java.rmi.registry.LocateRegistry.createRegistry(1099) ;//1099 es el puerto por defecto. }catch(RemoteException ex){ System.out.println("Problemas con createRegistry()..."); ex.printStackTrace(); }//catch 8 Clase java.rmi.Naming public static void bind(String name, Remote obj) throws AlreadyBoundException, MalformedURLException, RemoteException Asocia una referencia de objeto a un nombre. public static void Elimina la asociación de un unbind(String name) throws objeto dado. RemoteException, NotBoundException, MalformedURLException 9 Clase java.rmi.Naming public static void rebind(String name, Remote obj) throws RemoteException, MalformedURLException public static String[] list(String name) throws RemoteException, MalformedURLException public static Remote lookup(String name) throws NotBoundException, MalformedURLException, RemoteException Vuelve a asociar un nombre ya existente a otra referencia de objeto. Devuelve una lista de todos los nombres presentes en el registro. Devuelve una referencia (Stub) para el objeto remoto asociado con el nombre. 10 Security Manager En la clase servidor y cliente hay que impostar el gestor de seguridad: if(System.getSecurityManager()==null) System.setSecurityManager(new RMISecurityManager()); Cuando se instala un gestor de seguridad, todo código que no se cargue desde el classpath declarado en la propiedad de System sun.boot.class.path no será fiable. Para que el código resulte fiable, hay que configurar convenientemente el fichero java.policy: Ej.: grant { permission java.net.SocketPermission "*:1024-65535", "accept, connect, listen, resolve"; }; Por comodidad puede incluirse el fichero java.policy directamente en la V.M. en el momento de a arrancar la aplicación: java -Djavasecurity.policy=java.policy nombreFicheroAplicación 11 Excepciones Excepción AccessException Significado El cliente no tiene permiso para la acción solicitada. AlreadyBoundException El nombre que se intenta utilizar ya existe en el registro (bind()). ConnectException Error de conexión al host remoto. 12 Excepciones ConnectionIOException MarshallException NoSuchObjectException NotBoundException Error de tipo IOException al intentar conectar al host remoto. Error de tipo IOException en una operación de marshalling El objeto remoto ya no existe. El recurso pedido (obj. remoto) no existe. 13 Excepciones ServerError ServerException StubNotFoundException Lo recupera el cliente si un método remoto lanza una excepción de tipo: java.lang.Error. Lo recupera el cliente si un método remoto lanza una excepción de tipo: java.lang.Exception. No se encuentra la clase stub. 14 Excepciones UnexpectedException UnknownHostException UnmarshallException Lo recupera el cliente si un método remoto lanza una excepción no declarada en su cláusula throws. Host desconocido. Error en la fase de unmarshalling de parámetros o valores de retorno. 15 Pasaje de parámetros/retornos • Si el parámetro/retorno es de tipo primitivo (int, long, float...), el sistema RMI lo pasa por valor (es decir, una copia del parámetro viaja a través de la red). • Si el parámetro/retorno es un objeto e implementa java.io.Serializable o java.io.Externalizable, se serializa a través de la red. • Si el parámetro es un objeto remoto, RMI lo sustituye por el stub, lo serializa y lo envía al cliente. 16 Recolector de objetos distribuidos DGC • El servidor mantiene una gestión de los objetos remotos en uso. • Los objetos son considerados “dirty” (sucios) cuando los utilizan uno o más clientes o “clean” (limpios) cuando ya no los utiliza ningún cliente. • Trascurrido un tiempo controlado por la propiedad de sistema java.rmi.dgc.leaseValue (en milisegundos - por defecto 10 minutos), el recolector de basura destruirá los objetos que estén limpios. • Si un cliente intenta utilizar una referencia de un objeto inexistente (recolectado) se lanzará la excepción: java.rmi.ConnectException. • Para que un objeto esté limpio también tiene que haber sido dado de baja (unbind()) en el registro. 17 Ejemplo HolaMundo JRMP • En este ejemplo se desarrollará un “hola mundo” con protocolo rmi JRMP. (Java Remote Method Protocol). • El alta del objeto remoto será vía rmiregistry. • Se necesita el j2sdk1.4. holamundoRmi.ZIP 18 Ejemplo HolaMundo IIOP • En este ejemplo se desarrollará un “hola mundo” con protocolo rmi IIOP. (Internet Inter ORB Protocol). • El alta del objeto remoto será vía JNDI. • Se necesita el j2sdk1.4. holamundoIIOP.zip 19 Ejemplo HolaMundo JRMP • En este ejemplo se desarrollará un “hola mundo” con protocolo rmi JRMP. • El alta del objeto remoto será vía JNDI. • Se necesita el j2sdk1.4. holamundoJRMPJNDI.zip 20