CORBA y RMI Mario Muñoz Organero Departamento p de Ingeniería g Telemática http://www.it.uc3m.es/mario Panorámica CORBA, RMI RED Comunicaciones Servidores información Intercambio de datos Clientes Mario Muñoz Organero. Servidores de información 2 Arquitecturas distribuidas basadas en componentes p Alternativas: Sockets. Implementación costosa. Remote Procedure Calls (RPC). No soporta objetos explícitamente. Microsoft Distributed Component Object Model (DCOM) Menos maduro, menos portable y además propietario. Java Remote Method Invocation (RMI) Solo para JAVA. Common Object Request Broker Architecture (CORBA) Multiplataforma, multilenguaje, ... Servicios Web .NET J2EE Servidores de información Mario Muñoz Organero. CORBA Common Object Request Broker Architecture • Open-source ORBs (e.g., TAO, JacORB, omniORB, MICO) • BEA Tuxedo • IONA Orbix • Borland VisiBroker • OIS ORB Express 3 OMA (Object Management Architecture) OMG: Object Management Group, Inc. http://www.omg.org Fundado F d d en 1989 (Sun, (S HP DEC, HP, DEC IBM,...) IBM ) Objetivo: Desarrollo de estándares para la reutilización, portabilidad e interoperabilidad de software orientado a objetos en entornos heterogéneos y distribuidos. Solución: Definen OMA (Object Management Architecture) de la cual CORBA es una parte. Historia: 1991: CORBA 1.1 1995: CORBA 2.0 2 0 (Modelo de Referencia) 2000: CORBA 2.4 2002: CORBA 3.0 (Modelo de componentes) Servidores de información Mario Muñoz Organero. 5 OMA: Objetivos técnicos Transparencia distribución Rendimiento local y remoto Comportamiento dinámico Sistema de nombrado Consultas: nombre, atributos, relaciones Control de la concurrencia Transacciones Robustez, disponibilidad Mario Muñoz Organero. Mantenimiento de versiones Notificación de eventos Semántica de Relaciones entre objetos API en C para todas t d l las operaciones Administración y g gestión Internacionalización Estandarización Servidores de información 6 Arquitectura del modelo de referencia OMA Application objects CORBA facilities CORBA 2.0 Object Request Broker (ORB) j services Object (CORBAservices) Mario Muñoz Organero. Servidores de información 7 Object services (CORBAservices) (I) D fi Definen 16 servicios i i comunes ofrecidos f id a los l objetos: bj Naming service : Identificación de objetos Object security service : Servicio de seguridad Object trader service : Mercader de objetos. Los ofrece a los clientes. Object j transaction service : Permite transacciones con commit-rollback Change management service : Gestor de versiones de implementación. Concurrency service : Gestión de bloqueos para permitir concurrencia Event notification service : Objetos que son mensajes de eventos Externalization service : Permite copiar objetos por valor Licensing service : Permite obtener licencias de uso de un objeto Lifecycle service : Crea, copia, mueve y borra objetos y grupos de objetos relacionados Mario Muñoz Organero. Servidores de información 8 Object services (CORBAservices) (II) Object collections service : Crea colecciones de objetos (basado en SMALLTALK) (árboles, listas, colas, conjuntos,...) Object query service Obj i : Permite P i localizar l li l objetos los bj por ell valor l de d sus atributos (parecido al Trader, pero en lugar de servicios ofrece atributos)) Persistent object service : Permite al objeto sobrevivir a la terminación del programa que lo creó Properties service : Asocia propiedades al objeto (modificable, borrable o sólo lectura) Relationship service : Permite relaciones entre objetos Time service : Soluciona el problema del reloj asíncrono en los SID. Usa time-stamping. Mario Muñoz Organero. Servidores de información 9 CORBAfacilities Definen servicios comunes ofrecidos a las aplicaciones: Horizontales: define colecciones de objetos prefabricados Interfaz de usuario Gestión de la información Gestión de sistemas Gestión de tareas Verticales: define servicios comunes para un dominio completo (framework tier) Objetos de negocio Comercio electrónico Finanzas Man fact ración Manufacturación Medicina Telecomunicaciones Mario Muñoz Organero. Servidores de información 10 Application objects Definen servicios específicos de un determinado negocio i o aplicación. li ió Suponen el nivel más alto de los servicios soportados p por la arquitectura p q OMA Mario Muñoz Organero. Servidores de información 11 CORBA (Common Object Request Broker Architecture) CORBA es un middleware orientado a objetos / componentes. Los objetos cliente solicitan servicios a los objetos servidor mediante invocación de método Separa interfaz e implementación Es independiente del lenguaje: los objetos clientes y servidores se implementan en cualquier lenguaje (de los soportados) Crea transparencia de localización a través del ORB : de objetos: la invocación siempre se hace en local de red: el ORB la gestiona de activación: los servidores se activan automáticamente de estado persistente: permite que el servidor guarde persistencia y es transparente al cliente Mario Muñoz Organero. Servidores de información 12 CORBA Ejemplo 1 Paso 1: Interfaz en IDL // Descripcion de una excepcion exception DivisionPorCero{ float op1; float op2; }; interface Calculator{ // operacion de Suma float add ( in float nb1, in float nb2 ); // operacion de Division float div ( in float nb1, , in float nb2 ) raises ( DivisionPorCero ); }; Mario Muñoz Organero. (*) Ejemplo tomado de http://www.programacion.com/tutorial/acscorba 13 CORBA Ejemplo 1 Paso 2: Implementación de calculator public class CalculatorPOAImpl extends CalculatorPOA{ public float add(float nb1, float nb2){ System out println("Suma = "+nb1+" + "+nb2); System.out.println("Suma return nb1 + nb2; } public float div(float nb1, nb1 float nb2) throws DivisionByZero { System.out.println("Division = "+nb1+" / "+nb2); if ( nb2 == 0 ){ throw new DivisionPorCero(nb1,nb2); DivisionPorCero(nb1 nb2); } return nb1 / nb2; } } Mario Muñoz Organero. Servidores de información 14 CORBA Ejemplo 1 Paso 3: Desarrollo del cliente Inicializar ORB Contactar con el objeto remoto Contactar con serv de nombres y obtener ref a él Construir el nombre del objeto en el servidor de nombres Obtener ref a objeto remoto en el servidor de nombres Narrow a o de obje objeto o ge genérico é co CO CORBA a al tipo po espec específico co de del objeto remoto Utilizar el objeto j remoto como si fuese local Servidores de información Mario Muñoz Organero. 15 CORBA Ejemplo 1 Paso 3: Desarrollo del cliente public class Client{ public static void main( String args[] ) { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); org.omg.CORBA.Object bj obj bj = null; ll org.omg.CosNaming.NamingContext naming = null; try{ obj = orb.resolve_initial_references("NamingService"); naming = org.omg.CosNaming.NamingContextHelper.narrow(obj); }catch ( org.omg.CORBA.ORBPackage.InvalidName name ){ 1) Inicializar el ORB System.out.println("No se ha podido obtener el NamingService"); org.omg.CORBA.ORB orb = System.exit(0); } orgorg.omg.CosNaming.NameComponent org.omg.CORBA.ORB.init(args,null); omg CORBA ORB init(args null); [] name = new org.omg.CosNaming.NameComponent[1]; name[0] = new org.omg.CosNaming.NameComponent(); name[0].id = "Calculator"; name[0].kind = "Example"; (...) } // fin del main } // fin de la clase Mario Muñoz Organero. Servidores de información 16 CORBA Ejemplo 1 Paso 3: Desarrollo del cliente public class Client{ public static void main( String args[] ) { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); org.omg.CORBA.Object bj obj bj = null; ll org.omg.CosNaming.NamingContext naming = null; try{ obj = orb.resolve_initial_references("NamingService"); naming = org.omg.CosNaming.NamingContextHelper.narrow(obj); }catch ( org.omg.CORBA.ORBPackage.InvalidName name ){ System.out.println("No se ha podido obtener el NamingService"); System.exit(0); } org.omg.CosNaming.NameComponent [] name = new org.omg.CosNaming.NameComponent[1]; name[0] = new org.omg.CosNaming.NameComponent(); name[0].id = "Calculator"; name[0].kind = "Example"; (...) } // fin del main 2) Localizar naming Service y obtener ref a él: } // fin de la el clase obj = orb.resolve_initial_references("NamingService"); naming = org.omg.CosNaming.NamingContextHelper.narrow(obj) Mario Muñoz Organero. Servidores de información 17 CORBA Ejemplo 1 Paso 3: Desarrollo del cliente 3) Construir nombre del objeto calculator: { public class Client{ public static void main( String args[] ) org.omg.CosNaming.NameComponent [ ] name = new org.omg.CosNaming.NameComponent[1]; org.omg.CosNaming.NamingContext naming = null; name[0] = new org.omg.CosNaming.NameComponent(); try{ obj = orb.resolve_initial_references("NamingService"); name[0].id = "Calculator"; naming = org.omg.CosNaming.NamingContextHelper.narrow(obj); name[0].kind [0] ki d = "Example"; "E l " }catch ( org.omg.CORBA.ORBPackage.InvalidName name ){ org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); org.omg.CORBA.Object bj obj bj = null; ll System.out.println("No se ha podido obtener el NamingService"); System.exit(0); } org.omg.CosNaming.NameComponent [] name = new org.omg.CosNaming.NameComponent[1]; name[0] = new org.omg.CosNaming.NameComponent(); name[0].id = "Calculator"; name[0].kind = "Example"; (...) } // fin del main } // fin de la clase Mario Muñoz Organero. Servidores de información 18 CORBA Ejemplo 1 Paso 3: Desarrollo del cliente public class Client{ public static void main( String args[] ) { (...) try{ { obj = naming.resolve(name); }catch ( org.omg.CosNaming.NamingContextPackage.NotFound ex ){ System.out.println("Objeto no encontrado en el NamingService"); System.exit(0); }catch ( org.omg.CosNaming.NamingContextPackage.CannotProceed ex ){ System.out.println("No se ha podido continuar"); System.exit(0); }catch ( org.omg.CosNaming.NamingContextPackage.InvalidName ex ){ System.out.println("Nombre invalido"); System.exit(0); } (...) } // fin del main } // fin de la clase 4) Localizar ref del objeto calculator en el naming Service: obj = naming.resolve(name); Servidores de información Mario Muñoz Organero. 19 CORBA Ejemplo 1 Paso 3: Desarrollo del cliente public class Client{ public static void main( String args[] ) { (...) Calculator l l calc l = CalculatorHelper.narrow(obj); l l l ( bj) try{ System.out.println("5 + 3 = " + calc.add(5,3) ); System.out.println("5 / 0 = " + calc.div(5,0) ); } catch ( DivisionPorCero ex ){ System.out.println("Interceptada intento de divisón por cero"); System.out.println("La division era "+ex.op1+" / "+ex.op2); } catch ( org.omg.CORBA.SystemException ex ){ System.out.println("Interceptada una excepcion CORBA System"); 5) Narrow de obj genérico Corba al objeto que buscamos: System.out.println(ex.getMessage()); Calculator calc = CalculatorHelper.narrow(obj); } } // fin del main } // fin de la clase Mario Muñoz Organero. Servidores de información 20 CORBA Ejemplo 1 Paso 3: Desarrollo del cliente public class Client{ public static void main( String args[] ) { (...) Calculator l l calc l = CalculatorHelper.narrow(obj); l l l ( bj) try{ System.out.println("5 + 3 = " + calc.add(5,3) ); System.out.println("5 / 0 = " + calc.div(5,0) ); } catch ( DivisionPorCero ex ){ System.out.println("Interceptada intento de divisón por cero"); System.out.println("La division era "+ex.op1+" / "+ex.op2); } catch ( org.omg.CORBA.SystemException ex ){ System.out.println("Interceptada una excepcion CORBA System"); System.out.println(ex.getMessage()); } } // fin del main } // fin de la clase 6) Uso de la ref objeto remoto como si fuera local: System.out.println("5+3 = " + calc.add(5,3)); System.out.println("5/0 = " + calc.div(5,0)); 21 Servidores de información Mario Muñoz Organero. CORBA Ejemplo 1 Paso 4: Desarrollo del servidor Inicializar ORB (1) Contactar con el serv de nombre Contactar con serv de nombr y obtener ref a POA (2) Pasar la referencia CORBA genérica a una específica POA (3) Poner objeto remoto disponible en el POA Instanciar objeto remoto (4) Activar el objeto remoto en el orb y obtener id (5) Obtener referencia a objeto remoto a partir del id (6) Registrar el nombre del objeto en el servidor de nombres (7) Enlazar en el servidor de nombres la ref a objeto remoto con su nombre (8) Activar gestor de invocaciones del POA (9) Pasar el control al ORB para que acepte peticiones (10) Mario Muñoz Organero. Servidores de información 22 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); org.omg.CORBA.Object bj objPoa bj = null; ll org.omg.PortableServer.POA rootPOA = null; try{ objPoa = orb.resolve_initial_references("RootPOA"); }catch ( org.omg.CORBA.ORBPackage.InvalidName ex ){} rootPOA = org.omg.PortableServer.POAHelper.narrow(objPoa); CalculatorPOAImpl calc = new CalculatorPOAImpl(); (...) } // fin del main } // fin de la clase 1) Inicializar el ORB org.omg.CORBA.ORB orb = org omg CORBA ORB init(args null); org.omg.CORBA.ORB.init(args,null); Mario Muñoz Organero. Servidores de información 23 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); org.omg.CORBA.Object bj objPoa bj = null; ll org.omg.PortableServer.POA rootPOA = null; try{ objPoa = orb.resolve_initial_references("RootPOA"); }catch ( org.omg.CORBA.ORBPackage.InvalidName ex ){} rootPOA = org.omg.PortableServer.POAHelper.narrow(objPoa); CalculatorPOAImpl calc = new CalculatorPOAImpl(); (...) } // fin del main } // fin de la clase 2) Resolver referencia al adaptador de objetos raíz RootPOA objPoa bjP = orb.resolve_initial_references("RootPOA"); b l i iti l f ("R tPOA") Mario Muñoz Organero. Servidores de información 24 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); org.omg.CORBA.Object bj objPoa bj = null; ll org.omg.PortableServer.POA rootPOA = null; try{ objPoa = orb.resolve_initial_references("RootPOA"); }catch ( org.omg.CORBA.ORBPackage.InvalidName ex ){} rootPOA = org.omg.PortableServer.POAHelper.narrow(objPoa); CalculatorPOAImpl calc = new CalculatorPOAImpl(); (...) } // fin del main } // fin de la clase 3) Narrow de ref genérica a ref de adaptador (POA) org.omg.PortableServer.POA rootPOA = null; rootPOA = org.omg.PortableServer.POAHelper.narrow(objPoa); Mario Muñoz Organero. Servidores de información 25 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); org.omg.CORBA.Object bj objPoa bj = null; ll org.omg.PortableServer.POA rootPOA = null; try{ objPoa = orb.resolve_initial_references("RootPOA"); }catch ( org.omg.CORBA.ORBPackage.InvalidName ex ){} rootPOA = org.omg.PortableServer.POAHelper.narrow(objPoa); CalculatorPOAImpl calc = new CalculatorPOAImpl(); (...) } // fin del main } // fin de la clase 4) Crear el objeto Calculator CalculatorPOAImpl calc = new CalculatorPOAImpl(); Mario Muñoz Organero. Servidores de información 26 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { (...) try y { byte[] servantId = rootPOA.activate_object(calc); org.omg.CORBA.Object ref = rootPOA.id_to_reference(servantId); org.omg.CORBA.Object obj = null; org.omg.CosNaming.NamingContext naming = null; try { obj = orb.resolve_initial_references("NamingService"); System.out.println("Locallizado el NamingService"); naming = org.omg.CosNaming.NamingContextHelper.narrow(obj); System out println("Narrow del NamingService"); System.out.println("Narrow } catch ( org.omg.CORBA.ORBPackage.InvalidName name ){ System.out.println("No se ha podido obtener el NamingService"); System.exit(0); } (...) 5) Activar elmain servidor dentro del ORB } // fin del } // fin de la clase byte[] servantId = rootPOA.activate_object(calc); Mario Muñoz Organero. Servidores de información 27 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { (...) try y { byte[] servantId = rootPOA.activate_object(calc); org.omg.CORBA.Object ref = rootPOA.id_to_reference(servantId); org.omg.CORBA.Object obj = null; org.omg.CosNaming.NamingContext naming = null; try { obj = orb.resolve_initial_references("NamingService"); System.out.println("Locallizado el NamingService"); naming = org.omg.CosNaming.NamingContextHelper.narrow(obj); System out println("Narrow del NamingService"); System.out.println("Narrow } catch ( org.omg.CORBA.ORBPackage.InvalidName name ){ System.out.println("No se ha podido obtener el NamingService"); System.exit(0); } (...) 6)Obtener la referencia al servidor } // fin del main } // fin de la clase org.omg.CORBA.Object ref = rootPOA id to reference(servantId); rootPOA.id_to_reference(servantId); Mario Muñoz Organero. Servidores de información 28 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ 7) Acceder al Naming Service public static void main( String args[] ) { obj =(...) orb.resolve_initial_references("NamingService"); try y { naming = org.omg.CosNaming.NamingContextHelper.narrow(obj); byte[] servantId = rootPOA.activate_object(calc); org.omg.CORBA.Object ref = rootPOA.id_to_reference(servantId); org.omg.CORBA.Object obj = null; org.omg.CosNaming.NamingContext naming = null; try { obj = orb.resolve_initial_references("NamingService"); System.out.println("Locallizado el NamingService"); naming = org.omg.CosNaming.NamingContextHelper.narrow(obj); System out println("Narrow del NamingService"); System.out.println("Narrow } catch ( org.omg.CORBA.ORBPackage.InvalidName name ){ System.out.println("No se ha podido obtener el NamingService"); System.exit(0); } (...) } // fin del main } // fin de la clase Mario Muñoz Organero. Servidores de información 29 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { (...) if ( naming g == null ) { System.out.println("No se ha encontrado el NamingService"); System.exit(0); } org.omg.CosNaming.NameComponent [] name = new org.omg.CosNaming.NameComponent[1]; name[0] = new org.omg.CosNaming.NameComponent(); name[0].id = "Calculator"; name[0].kind = "Example"; (...) } // fin del main } // fin de la clase 7) Construir nombre del objeto calculator: (=que 2 de cliente) org.omg.CosNaming.NameComponent [ ] name = new org.omg.CosNaming.NameComponent[1]; name[0] = new org org.omg.CosNaming.NameComponent(); omg CosNaming NameComponent(); name[0].id = "Calculator"; = "Example"; Servidores de información Mario name[0].kind Muñoz Organero. 30 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { (...) try{ naming.bind(name,ref); } catch ( org.omg.CosNaming.NamingContextPackage.NotFound ex ){ System.out.println("Objeto no encontrado"); System.exit(0); }catch ( org.omg.CosNaming.NamingContextPackage.AlreadyBound ex ){ System out println("Ya System.out.println( Ya hay un objeto con ese nombre nombre"); ); naming.unbind(name); System.exit(0); }catch ( org.omg.CosNaming.NamingContextPackage.InvalidName ex ){ System.out.println("Nombre inválido"); System.exit(0); }catch ( org.omg.CosNaming.NamingContextPackage.CannotProceed ex ){ System.out.println("No se ha podido continuar"); System.exit(0); } (...) } // fin del main } // fin de la clase 8) Enlazar ref del objeto calculator con su nombre naming.bind(name,ref); Servidores de información Mario Muñoz Organero. 31 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { (...) rootPOA.the_POAManager().activate(); g System.out.println("El servidor está preparado..."); orb.run(); } // fin del try catch ( java.lang.Exception ex ) { System.out.println("Se ha capturado una excepción"); ex.printStackTrace(); } } // fin del main } // fin de la clase 9)) Activar gestor g de invocaciones del POA rootPOA.the_POAManager().activate(); Mario Muñoz Organero. Servidores de información 32 CORBA Ejemplo 1 Paso 4: Desarrollo del servidor public class ServerPOA{ public static void main( String args[] ) { (...) rootPOA.the_POAManager().activate(); g System.out.println("El servidor está preparado..."); orb.run(); } // fin del try catch ( java.lang.Exception ex ) { System.out.println("Se ha capturado una excepción"); ex.printStackTrace(); } } // fin del main } // fin de la clase 10) Ceder control a ORB para que escuche peticiones orb.run(); b () Mario Muñoz Organero. Servidores de información 33 Servidores de información 34 CORBA Ejemplo 1 Paso 5: Compilar la aplicación Compilar interfaces Compilar el servidor Generar stubs y skeletons Compilar la clase cliente Mario Muñoz Organero. CORBA Ejemplo 1 Paso 6: Ejecutar la aplicación Arrancar ORB Arrancar Servidor de Nombres Arrancar el Servidor Ejecutar el cliente Servidores de información Mario Muñoz Organero. 35 IDL (Interface Definition Language) CORBA incorpora un lenguaje de definición de interfaces (IDL) Independiente del lenguaje de implementación. implementación Mapea hacia los lenguajes de programación habituales. Los ORBs llevan incorporados su traductor de IDL a los lenguajes de implementación soportados C C++ Java Delphi Ada SmallTalk IDL Object Request Broker (ORB) Mario Muñoz Organero. Servidores de información 36 IDL (Interface Definition Language) Lenguaje declarativo para definir las interfaces d los de l objetos bj t CORBA. CORBA Similar a C++ en el léxico y la sintaxis Macros de preprocesamiento, comentarios, ... Además de las interfaces, permite definir tipos necesarios i para declarar d l l interfaces: las i t f Enumerados, structs, arrays, secuencias, ... Organiza las definiciones en ámbitos (módulos). (módulos) Mario Muñoz Organero. Servidores de información 37 IDL – enum y struct enum: P Permite it la l declaración d l ió de d un tipo ti enumerado d enum color {rojo, verde, azul}; struct: Para definir estructuras al estilo C++ struct descripcion_ventana descripcion ventana { float altura; float anchura; color color_ventana; color ventana; }; Mario Muñoz Organero. Servidores de información 38 IDL – Secuencias, Arrays y Alias Secuencias: typedef sequence <short> valores; typedef sequence <string, 10> nombres; typedef sequence <valores> pedidos_proveedor; Arrays: typedef ventana matriz_ventanas[10][30]; typedef: permite definir alias a tipos typedef color_ventana color; Mario Muñoz Organero. Servidores de información 39 IDL - Constantes Pueden estar definidas de forma global, dentro de un módulo o dentro de un interface. interface Los valores permitidos son: booleanos, numéricos, caracteres y strings Los valores numéricos pueden ser declarados como expresiones. Ejemplos: const float numero_ventanas = ((max_p pantalla - 100)) / 2.5;; const string mensaje_error = “cantidad incorrecta”; Mario Muñoz Organero. Servidores de información 40 IDL - Excepciones Se definen como un struct, sustituyendo la palabra clave struct por exception Permite definir excepciones de usuario CORBA tiene definidas un conjunto j de excepciones p estándar (excepciones de sistema) Ejemplo: exception ColorIncorrecto { sequence <color> otros_colores; color color_solicitado; color solicitado; }; Mario Muñoz Organero. Servidores de información 41 Excepciones de Sistema OBJECT_NOT_EXIST La referencia no apunta a ningún objeto. objeto TRANSIENT No se ha podido alcanzar el servidor o el objeto. BAD_PARAM Algún parámetro de un método es ilegal. N se puede No d pasar un null ll por ell ORB. ORB COMM_FAILURE UNKNOWN La operación ha lanzado una excepción desconocida. Mario Muñoz Organero. Servidores de información 42 Interface Object Todas las interfaces IDL heredan implícitamente de la interface Object. Para averiguar si existe el objeto: boolean non_existent() () Un valor false no quiere decir que el objeto aún exista. Para indicar cuándo creamos y destruimos referencias: Object duplicate() void release() Para consultar si es de un determinado tipo: boolean is_a(in string logical_type_id) El argumento es un RepositoryId. Para averiguar si dos referencias apuntan al mismo objeto: boolean is_equivalent(in Object other_object) Un valor false no implica que las dos referencias no sean iguales. iguales Mario Muñoz Organero. Servidores de información 43 Tipo any Contenedor de valores de cualquier tipo IDL. C Creación ió de d un any: Operación create_any del ORB. Nos permite conocer el tipo de valor que contiene: CORBA::TypeCode type() Para los tipos básicos existen operaciones de inserción y extracción de valores: void insert_short _ ((in short value)) short extract_short () Mario Muñoz Organero. Servidores de información 44 Ejemplo IDL (I) interface Cuenta { boolean ingresar(in long cantidad); b l boolean retirar(in ti (i long l cantidad); tid d) long balance(); }; Mario Muñoz Organero. Servidores de información 45 Servidores de información 46 Ejemplo IDL (II) struct HoraDelDia { short hora; short minutos; short segundos; }; Interface Hora { HoraDelDia obtener_hora(); }; Mario Muñoz Organero. Ejemplo IDL (III) interface Tipo: TipoBase, OtroTipoBase { attribute tt ib t string t i un_atributo; t ib t readonly attribute long otro_atributo; // Comentario char h operacion i (in (i OtroTipo Ot Ti ot, t inout i t long l valor, l outt boolean ok) raises (MiExcepcion, OtraExcepcion); oneway void otra_operacion(in string datos); }; Servidores de información Mario Muñoz Organero. 47 Proyección (mapping) de lenguajes g j Especifican cómo se traduce el IDL a los distintos lenguajes de programación. programación IDL short long float char string g boolean Mario Muñoz Organero. C++ CORBA::Short CORBA::Long CORBA::Float CORBA::Char char * CORBA::Boolean Servidores de información 48 Correspondencia IDL en Java Objetivo: Definir la correspondencia de todas las definiciones de IDL en Java. Limitaciones Java: Los tipos sólo se pueden definir con clases e interfaces. Paso de parámetros sólo por valor. No permite alias de tipos. El narrow Java no es válido para CORBA. Todas T d las l cuestiones ti relativas l ti a la l correspondencia d i las l resuelve un compilador IDL. Mario Muñoz Organero. Servidores de información 49 IDL-Java – Tipos Básicos Mario Muñoz Organero. Servidores de información 50 IDL-Java – Clase Holder Resuelven el problema del paso de parámetros de salida ((out)) y entrada/salida ((inout). ) Idea: Para cada tipo, definir una clase que contenga un atributo de ese tipo. tipo En Java no se puede modificar una referencia pasada como parámetro, pero sí el estado del objeto. El compilador crea un clase holder para cada tipo: Ejemplo Tipo TipoHolder Accedemos al valor a través del campo “value”. Dentro del módulo CORBA están definidas para los tipos básicos: CharHolder, ULongLongHolder, ... Mario Muñoz Organero. Servidores de información 51 IDL-Java – Clase Helper Cualquier tipo IDL tiene las siguientes propiedades: Se puede introducir y sacar de un any. En el caso de una interface, necesitamos un “narrow”. Consultar el tipo (TypeCode). Conocer su identificador de repositorio (RepositoryId) Esta funcionalidad se introduce en una clase helper como métodos de clase: void insert (org.omg.CORBA.Any any, Tipo t) Ti extract Tipo t t (org.omg.CORBA.Any ( CORBA A any)) Tipo narrow (omg.org.CORBA.Object obj) TypeCode type() String id() Generada por el compilador: TipoHelper. Mario Muñoz Organero. Servidores de información 52 IDL-Java – Interfaces El compilador genera una interface Java equivalente al IDL TipoOperations Y otra que hereda de ésta y de Object Tipo También crea las clases: Stub: _TipoStub Skeleton: TipoPOA Atributos: attribute short edad; public short edad(); public void edad(short value); En caso de ser readonly sólo crea el método de acceso. Operaciones: oneway desaparece, se introducen los holder para out e inout, y se declaran las excepciones con throws. Mario Muñoz Organero. Servidores de información 53 IDL-Java IDL Java – Registros y Excepciones p Por ejemplo, para un struct con nombre Posicion el compilador genera 3 clases: Clase Posicion. Clases PosicionHelper y PosicionHolder. La clase Posicion estará formada por: Un atributo público por cada campo del struct. Un constructor por defecto. defecto Un constructor para la inicialización. En el caso de las excepciones, p la clase hereda de org.omg.CORBA.UserException. Mario Muñoz Organero. Servidores de información 54 IDL-Java IDL Java – Secuencias, Secuencias Arrays y Alias Java no permite definir alias. En el código Java aparecerá el tipo base en lugar del alias. alias Existe una excepción para las secuencias y arrays: Crea las clases Helper y Holder. Holder Pero no crea el tipo, hay que especificarlo en cada declaración: typedef long[10] long_array; // IDL long_array valores; // IDL En Java: int [ ] valores = new int [10]; Mario Muñoz Organero. Servidores de información 55 IDL-Java – Constantes y Módulos Las constantes se mapean al estilo Java: atributo static final. final const short MaxSlots = 8; // IDL public final static short MaxSlots = (short) 8; // Java L módulos Los ód l corresponden d con paquetes t Java. J module externo { module interno { interface I { ... Crea los paquetes: externo, externo.interno I t d Introduce l interface la i t f I stub, I, t b skeleton, k l t h l helper y holder h ld dentro d t del d l paquete externo.interno Mario Muñoz Organero. Servidores de información 56 Comunicación C/S en CORBA Cliente Invocation Interface Servidor Object Adapter Object Request Broker (ORB) Mario Muñoz Organero. Servidores de información 57 Flujo general de peticiones El cliente realiza una petición usando stubs estáticos (previamente compilados) (p p ) o la Interfaz de invocación dinámica (DII) y la dirige a su ORB. El ORB cliente transmite las peticiones al ORB enlazado con el servidor. servidor El ORB del servidor redirige la petición al adaptador de objetos que ha creado el objeto destino. El adaptador de objetos dirige la petición al servidor que implementa el objeto destino. Puede utilizar esqueletos estáticos o la interfaz de esqueleto q dinámico. El servidor devuelve su respuesta. Mario Muñoz Organero. Servidores de información 58 Flujo general de peticiones Servidores de información Mario Muñoz Organero. 59 Arquitectura de CORBA Interface Repository IDL COMPILER Implementation Repository operación(args) Client Dynamic Invocation Interface OBJ REF IDL Stubs S b Object resultado(args) ORB IInterface t f (Servant) IDL Dynamic Static Skeleton Skeletons Interface Object Adapter Object j Request q Broker (ORB) ( ) Mario Muñoz Organero. Servidores de información 60 Componentes primarios en CORBA (I) () Object : Entidad de programación CORBA. Tiene una identidad, una interfaz, y una implementación (conocida como Servant). Servant (sirviente) : Implementación de una entidad en un lenguaje de programación (en cualquiera de los soportados). soportados) Define las operaciones que soporta un determinado interfaz CORBA IDL. Client : Entidad de programa que invoca una operación a una implementación de objeto. objeto Idealmente será tan simple como una invocación a un método. Object Request Broker (ORB) (corredor de peticiones a objetos) : Núcleo de la arquitectura CORBA. Proporciona transparencia entre los clientes y las implementaciones de los objetos. Cuando un cliente invoca una operación, ORB busca la implementación del objeto, lo activa si es necesario, transmite la petición y devuelve la respuesta. Permite conexión con otros ORBs. Mario Muñoz Organero. Servidores de información 61 Componentes primarios en CORBA (II) ( ) ORB Interface : Interfaz de comunicación con el ORB para solicitarle servicios al propio ORB: conversión ió de d referencias f i de d objetos bj a cadenas, d ... IDL stubs (cabos) : El stub es la interfaz que ve el cliente R Representante t t del d l servidor id en ell lado l d cliente li t (proxy) ( ) Realiza invocación remota Define rutinas específicas para operaciones particulares en objetos particulares Definido en IDL y se transforma al lenguaje de programación del Cliente La transformación entre CORBA IDL y el lenguaje de programación se realiza automáticamente por el IDL compiler IDL s skeletons e eto s (esque (esqueletos) etos) : Ofrece una interfaz estática a cada servicio del objeto Definido en IDL y se transforma al lenguaje de programación del Servant Mario Muñoz Organero. Servidores de información 62 Componentes primarios en CORBA (III) ( ) Dynamic Invocation Interface : Permite la construcción dinámica de invocaciones a objetos. j No llama a una rutina específica para una operación particular en un objeto particular. El cliente especifica el objeto a ser invocado, la operación y el conjunto de parámetros (esto lo obtiene del Interface Repository) Dynamic Skeleton Interface : Permite el manejo dinámico de las invocaciones a objetos. No es accedido por un esqueleto específico para una operación determinada. Se proporciona acceso a través de un nombre de operación y parámetros. Mario Muñoz Organero. Servidores de información 63 Componentes primarios en CORBA (IV) ( ) Object Adapter : Conecta al ORB con la implementación p del objeto j para realizar p los servicios que el ORB proporciona (a otros objetos y clientes): generación e interpretación de referencias a objetos invocación de métodos seguridad de las interacciones activación y desactivación del objeto y su implementación mapeo de las referencias de los objetos a sus implementaciones registro de implementaciones. Crean referencias de objetos Aseguran que cada objeto destino esté encarnado en un sirviente R ib Reciben l las peticiones ti i emitidas itid por ell ORB del d l servidor id y las l redirigen a los sirvientes que encarnan a los objetos destino. Mario Muñoz Organero. Servidores de información 64 Componentes primarios en CORBA (V) ( ) Interface Repository : Almacena información relativa a las interfaces IDL definidas en el Sistema Di ib id Distribuido. El ORB solicita los servicios al IR para: comunicarse con otros ORB de distinta implementación. verificar los parámetros de la petición verificar la existencia de ciclos en los grafos de herencia Los clientes solicitan los servicios al IR para: navegar por la lista de interfaces facilitar la instalación y distribución de objetos Un ORB puede tener varios IR según la necesidad (prueba, release, externos, ... Implementation Repository : Al Almacena i f información ió de d administración d i i t ió de d cada d uno de d los l objetos: bj t cuáles ál están instanciados, como activarlos, permisos, etc. Mario Muñoz Organero. Servidores de información 65 Invocación de peticiones Para que un cliente envíe un mensaje a un objeto necesita tener una referencia de dicho objeto. j Las operaciones se realizan a través de la referencia al objeto. Cuando un cliente llama a una operación, operación el ORB: Localiza al objeto destino. Activa a la aplicación servidor, si no está activa. Transmite los argumentos. Activa un sirviente para el objeto si es necesario. Espera p hasta q que se complete p la operación. p Devuelve cualquier parámetro out e inout al cliente. Devuelve una excepción cuando falla la llamada. Mario Muñoz Organero. Servidores de información 66 Características de las invocaciones Transparencia de la localización. T Transparencia i del d l servidor. id Independencia del lenguaje. Independencia de la implementación. Independencia de la arquitectura. Independencia del sistema operativo. Independencia del protocolo. Independencia del nivel transporte. Mario Muñoz Organero. Servidores de información 67 Referencias y proxys Cuando un cliente recibe una referencia, el ORB d l cliente del li t instancia i t i un objeto bj t proxy, que proporciona al cliente una interfaz del objeto d ti destino. Cuando un cliente llama a una operación en el proxy, éste envía el mensaje adecuado al servidor remoto. Mario Muñoz Organero. Servidores de información 68 ORB en Java Cualquier aplicación que mantenga o utilice objetos CORBA debe instanciar un ORB. Clase ORB: public static ORB init(String[] args, Properties props) Propiedades estándares en Java: org.omg.CORBA.ORBClass org.omg.CORBA.ORBSingletonClass Indican la implementación del ORB a utilizar. utilizar Por defecto, Sun define el suyo. Otro ORB: ORBacus Mario Muñoz Organero. Servidores de información 69 ORB en Java Problema: Incluir las propiedades dentro del código hace que la aplicación no sea portable entre ORBs Solución 1: Establecer las propiedades desde la línea de comandos (-D) Solución 2: Definir el fichero “orb orb.properties properties” e incluirlo dentro del directorio “lib” del JRE de Java. org.omg.CORBA.ORBClass=com.ooc.CORBA.ORB org.omg.CORBA.ORBSingletonClass=com.ooc.CORBA.ORBSingle CORBA ORBSi l t Cl CORBA ORBSi l ton Mario Muñoz Organero. Servidores de información 70 Adaptador de Objetos Intermediario entre la red y los objetos servidores. id Implementa políticas de instanciación de sirvientes, concurrencia, seguridad… Algunos g ejemplos: j p BOA POA Mario Muñoz Organero. Servidores de información 71 Adaptador de Objetos: POA Portable Object Adapter (POA). Encargado de registrar y controlar los objetos CORBA. C fi Configurable bl mediante di t políticas. líti El ORB proporciona un POA raíz como referencia inicial: “RootPOA” Los POAs se organizan jerárquicamente El POA se encarga de crear las referencias. Mario Muñoz Organero. Servidores de información 72 Adaptador de Objetos: POA Mario Muñoz Organero. Servidores de información 73 RootPOA Un ORB mantiene un registro de objetos CORBA que son accedidos por nombre: Referencia Inicial Se puede especificar declarativamente (en ficheros de configuración) los objetos que son necesarios Registro del Sistema, canales de eventos, ... En particular, E ti l ell POA raíz í es un objeto bj t inicial i i i l siempre i presente: Mario Muñoz Organero. Servidores de información 74 Activación de Objetos Para que un objeto sea accesible remotamente es necesaria i su activación ti ió en un POA Una vez registrados todos los objetos, hay que activar el POA: poa.the_POAManager().activate(); Mario Muñoz Organero. Servidores de información 75 Referencias a objetos Los objetos una aplicación CORBA se encuentran identificados por medio de una referencia única. Esta referencia es generada al activar un objeto en el Adaptador de Objetos. Por medio de esta referencia el ORB es capaz de localizar el computador remoto y el adaptador de objetos donde se encuentra. Éste último es capaz de identificar el objeto concreto dentro del adaptado adaptador. IOR:010000000f00000049444c3a4375656e74613a312e300000020000 00000000003000000001010000160000007175696e6f2e64617473692 e66692e75706d2e65730041040c000000424f418a640965000009f4030 100000024000000010000000100000001000000140000000100000001 00010000000000090101000000000 Mario Muñoz Organero. Servidores de información 76 Referencias a Objetos Remotos Es necesario crearlas explícitamente utilizando el POA. Object create_reference create reference (in CORBA::RepositoryId intf) Object create_reference_with_id ( in ObjectId CORBA::RepositoryId intf ) ObjectId servant_to_id servant to id (in Servant servant) Object servant_to_reference (in Servant servant) Servant reference_to_servant (in Object reference) ObjectId reference_to_id (in Object reference) Servant id_to_servant (in ObjectId oid) Object id_to_reference id to reference (in ObjectId oid) Mario Muñoz Organero. oid, Servidores de información in 77 Obtener una Referencia Una referencia remota puede ser obtenida: Utilizando un registro: Servicio de Nombres. Nombres Como parámetro o valor de retorno de una operación distribuida. Utilizando una representación stringfield almacenada en un fichero. Cualquier C l i referencia f i puede d representarse t como una cadena: IOR (InterOperable Reference) String refStr = orb.object_to_string(contador); orb object to string(contador); Object obj = orb.string_to_object(refStr); Mario Muñoz Organero. Servidores de información 78 Referencias y Estructura del POA Mario Muñoz Organero. Servidores de información 79 Políticas para el POA Permite configurar: Thread policy: ORB CTRL MODEL ORB_CTRL_MODEL, SINGLE_THREAD_MODEL Lifespan policy: TRANSIENT, PERSISTENT Obj t ID uniqueness: Object i UNIQUE ID MULTIPLE_ID UNIQUE_ID, MULTIPLE ID ID assignment policy: SYSTEM_ID, USER_ID Servant retention p policy: y RETAIN, NON_RETAIN _ Request processing policy: USE_ACTIVE_OBJECT_MAP_ONLY, USE_DEFAULT_SERVANT,, USE_SERVANT_MANAGER. Implicit activation policy: IMPLICIT_ACTIVATION, NO_IMPLICIT_ACTIVATION Mario Muñoz Organero. Servidores de información 80 Políticas para el POA Lifespan: indica si las referencias de objeto creados por el POA son transitorios o persistentes. Por defecto: TRANSIENT Servant Retention: indica si el POA mantiene los sirvientes en memoria y almacena la correspondencia entre IDs de objetos y sirvientes en el “mapa mapa de objetos activos activos” o no Por defecto: RETAIN ID Assignment: indica si es el POA o la implementación del objeto quien asigna los IDs de objeto Por defecto: SYSTEM_ID ID Uniqueness: indica si los sirvientes activados por el POA tienen ID de objeto único o no Por defecto UNIQUE_ID Thread: indica si toda petición es tratada por el mismo hilo (SINGLE_THREAD_MODEL) o no necesariamente Por defecto: ORB_CTRL_MODEL Activation: indica si un sirviente se activa implícitamente a la hora de crear una referencia de objeto o si debe ser activado explícitamente Por defecto: IMPLICIT_ACTIVATION Request processing: indica si en caso de no encontrar un objeto en el mapa de objetos activos, se devuelve una excepción (RETAIN obligatorio), o se envía la petición a un gestor de sirvientes (que activará un sirviente) o a un sirviente por defecto; en el caso NO_RETAIN: no hace falta mirar el mapa Por defecto: USE_ACTIVE_OBJECT_MAP_ONLY Mario Muñoz Organero. Servidores de información 81 Ej: Referencias Persistentes Necesitamos crear un POA con estas propiedades. D fi i las Definir l políticas: líti Lifespan con valor PERSISTENT Id Assigment con valor USER_ID USER ID Instanciar un POA con esas políticas: Mario Muñoz Organero. Servidores de información 82 Manos a la obra El compilador de IDL genera: iinterface t f C t d { Contador void inc(); void dec(); void set(in long valor); long get(); }; Mario Muñoz Organero. Compilación: Contador.java ContadorOperations.java ContadorPOA.java _ContadorStub.java C t d St b j ContadorHelper.java ContadorHolder.java Servidores de información 83 Servidores de información 84 Add.idl prompt> idlj -fall Add.idl Mario Muñoz Organero. AddImpl.java Mario Muñoz Organero. Servidores de información 85 Servidores de información 86 AddServer.java Mario Muñoz Organero. AddServer.java Mario Muñoz Organero. Servidores de información 87 Servidores de información 88 AddClient.java Mario Muñoz Organero. AddClient.java Mario Muñoz Organero. Servidores de información 89 Arrancando el servidor y cliente prompt> javac *.java ArithApp/*.java prompt> orbd -ORBInitialPort 2500 prompt> p p jjava AddServer -ORBInitialPort 2500 prompt> java AddClient -ORBInitialPort 2500 Mario Muñoz Organero. Servidores de información 90 RMI Invocación de Métodos Remota RMI (Remote t Method th d Invocation) ti ) Concepto ¿Qué es? RMI (Remote Method Invocation). Procedimiento de invocación a métodos remotos Permite a un objeto que se está ejecutando en una MV invocar métodos de otro que esté en una MV distinta Dos partes: Middleware: soporte a la ejecución de aplicaciones distribuidas API de java: soporte a la creación de aplicaciones distribuidas. Proporciona: Mecanismos de localización, Facilidades de comunicación Una semántica p para p permitir la invocación de métodos remotos Mario Muñoz Organero. Servidores de información 92 RMI (Remote t Method th d Invocation) ti ) Objetivos ¿Para qué sirve? Permitir invocación de métodos de un objeto por objetos que residen en diferentes máquinas virtuales (en particular, a través de la red) P.e. p permitir invocación de métodos remotos p por Applets pp Integrar el modelo de objetos distribuidos al lenguaje Java de modo natural, preservando en lo posible la semántica de objetos en Java distinción entre objetos locales y remotos diferentes semánticas en las referencias a objetos remotos: no persistentes (vivas), persistentes, de activación lenta Preservar la seguridad de tipos (type safety) dada por el ambiente de ejecución Java Mantener la seguridad del ambiente dada por los Security Managers, en particular, en presencia de carga dinámica de clases Facilitar el desarrollo de aplicaciones distribuidas Mario Muñoz Organero. Servidores de información 93 RMI (Remote t Method th d Invocation) ti ) Hitos Especificaciones RMI en JDK-1.1 Introducción de las bibliotecas java.rmi.* Comunicación por Java Remote Method Protocol (JRMP) RMI en J2SE SDK 1.2 Referencias de objeto persistentes y objetos activables No hace falta generar skeletons (reflection + skeletons genéricos) RMI en J2SE SDK 1.3 Opción de comunicación por IIOP (Internet Inter-ORB Protocol de CORBA) Uso de un fichero de política de seguridad obligatorio con la activación RMI en J2SE SDK 1.4 Mejoras en la serialization (secuenciación) RMI en J2SE SDK 1.5 = J2SE SDK 5.0 Introducción de un tipo de invocación dinámica hace uso de reflection + stubs genéricos este mecanismo obvia la compilación con rmic Mario Muñoz Organero. Servidores de información 94 RMI (Remote Method Invocation) ¿Cómo funciona? ¿ El servidor Crea objetos j remotos Hace accesibles refs a objetos remotos Espera p a q que los clientes invoquen q a estos objetos j remotos o a sus métodos El cliente Obtiene una referencia de uno o más objetos remotos en el servidor Invoca a sus métodos Mario Muñoz Organero. Servidores de información 95 RMI (Remote Method Invocation) ¿Cómo funciona? ¿ RMI proporciona al cliente y servidor Mecanismos de localización ((obtención de refs)) Registrar objetos remotos con rmiregistry Pasar y devolver referencias a objetos remotos Mecanismos de comunicación Transparentes para el programador S á ti similar Semántica i il a una llamada ll d estándar tá d a método ét d Mecanismos de carga dinámica de clases Para objetos que se pasan entre C y S bien por parámetro o como tipo de retorno Mario Muñoz Organero. Servidores de información 96 RMI (Remote Method Invocation) ¿Cómo funciona? CountRMIClient RMI Stub CountRMIServer RMI sobre TCP/IP Cliente RMI Skeleton Servidor Servidores de información Mario Muñoz Organero. 97 RMI ¿Cómo RMI: Cómo ffunciona? nciona? Stubs y Skeletons Objeto Cliente Objeto Remoto Interfaz remota Interfaz remota Skeleton Stub Red Mario Muñoz Organero. Servidores de información 98 RMI ¿Cómo RMI: Cómo ffunciona? nciona? Interfaces remotas y objetos remotos Una interfaz remota declara un conjunto de operaciones que podrán invocarse desde otras JVM. debe extender java.rmi.Remote sus métodos deben declarar que lanzan java.rmi.RemoteException Para que los métodos de una interfaz remota estén disponibles para ser invocadas desde otras JVM ha de implementar la interfaz Un objeto remoto es un objeto que implementa una interfaz remota Un cliente en otra JVM interactúa con un objeto remoto vía una de sus interfaces remotas, nunca directamente Habitualmente, la clase de un objeto remoto extiende java.rmi.server.UnicastRemoteObject j i i bj pero puede llamar a su método exportObject() directamente Mario Muñoz Organero. Servidores de información 99 RMI ¿Cómo RMI: Cómo ffunciona? nciona? Los stubs Un stub de RMI es un proxy es decir, un representante local de un objeto remoto Contiene la referencia al objeto remoto Permite la invocación de sus métodos como si fuera un objeto local. En concreto: recibe las peticiones del llamante realiza el marshalling (empaquetado de los parámetros), envía la petición al objeto llamado en el caso de que haya respuesta: realiza el unmarshalling g devuelve el valor al llamante Mario Muñoz Organero. Servidores de información 100 RMI: ¿Cómo se usa? 1 2 Proceso de Desarrollo definir una interfaz remota 1. 2. implementar la interfaz java.rmi.UnicastRemoteObject (o llamando a exportObject()) (.java) 3 3. javac 4. clase servidora (.class) 4 8 implementar el cliente rmic clase esqueleto clase stub usa 5 arrancar el registro RMI 5. 6. 7. 8. (.java) 9 javac 10 arrancar el cliente 6 clase cliente arrancar los objetos servidores 7 Extender java.rmi.Remote Implementar interfaz, extendiendo 9. 10. Compilar impl. (.java) con javac Compilar impl. (.class) con rmic Arrancar el rmiregistry A Arrancar l objetos los bj t del d l servidor id Registrar los objetos remotos (llamando a métodos del paquete java.rmi.Naming para asociar un nombre con el objeto remoto) Escribir el código cliente (llamando a métodos del paquete java.rmi.Naming para localizar el objeto remoto) Compilar el código cliente Arrancar el cliente registrar los objetos remotos Mario Muñoz Organero. Cliente 101 Servidor RMI Ejemplo 1 Paso 1: Definir interfaz remota Importar paquetes adecuados import java.rmi.Remote; import java.rmi.RemoteException; Extender la clase Remote public interface NombreInt extends Remote{} p {} Lanzar remoteException en todos los métodos public Tipo NombreMet() throws RemoteException; Ejemplo tomado de: http://www.programacion.com/java/tutorial/rmi/ Mario Muñoz Organero. Servidores de información 102 RMI Ejemplo 1 Paso 1: Definir un interfaz remoto package compute; comp te import java.rmi.Remote; import java.rmi.RemoteException; java rmi RemoteException; public interface Compute extends Remote { Object executeTask(Task t) throws RemoteException; } Mario Muñoz Organero. Servidores de información 103 RMI Ejemplo 1 Paso 1: Definir otros interfaces Detectar objetos que puedan viajar por tratarse de: Parámetros de métodos remotos Tipos de retorno de métodos remotos Deben extender el interfaz serializable Mario Muñoz Organero. Servidores de información 104 RMI Ejemplo 1 Paso 1: Definir otros interfaces package compute; import java.io.Serializable; public interface Task extends Serializable { Object execute(); } Mario Muñoz Organero. Servidores de información 105 RMI Ejemplo 1 Paso 2: Implementar interfaz remota Extender la clase UnicastRemoteObject I l Implementar t ell interfaz i t f remoto t definido d fi id en ell paso 1 C Crear main i que realice li las l siguientes i i t tareas t Crear controlador de seguridad C Crear objeto bj t de d la l clase l remota t Registrar objeto de la case remota Mario Muñoz Organero. Servidores de información 106 RMI Ejemplo 1 Paso 2: Implementar interfaz remoto package engine; import java.rmi.*; import java.rmi.server.*; import compute.*; public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException { super();} public bli Object bj executeTask(Task k( k t) ) { return t.execute(); () } public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } String name = "//localhost/Compute"; try { Compute engine = new ComputeEngine(); Naming rebind(name engine); Naming.rebind(name, System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); } } } Servidores de información Mario Muñoz Organero. 107 RMI Ejemplo 1 Paso 2: Implementar interfaz remoto package engine; import java.rmi.*; import java.rmi.server.*; import compute.*; public class ComputeEngine extends UnicastRemoteObject implements Compute{ public ComputeEngine() throws RemoteException { super();} public bli Object bj executeTask(Task k( k t) ) { return t.execute(); () } public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); public ComputeEngine } class String name = "//localhost/Compute";extends UnicastRemoteObject try { implements Compute{ Compute engine = new ComputeEngine(); Naming rebind(name engine); Naming.rebind(name, System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); } } } Mario Muñoz Organero. Servidores de información 108 RMI Ejemplo 1 Paso 2: Implementar interfaz remoto package engine; import java.rmi.*; import java.rmi.server.*; import compute.*; public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException { super();} public bli Object bj executeTask(Task k( k t) ) { return t.execute(); () } public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } String name = "//localhost/Compute"; try { Compute engine = new ComputeEngine(); Naming rebind(name engine); Naming.rebind(name, System.out.println("ComputeEngine bound"); if (System.getSecurityManager() == null) { } catch (Exception e) { RMISecurityManager ()); System.setSecurityManager(new System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); } } } } Servidores de información Mario Muñoz Organero. 109 RMI Ejemplo 1 Paso 2: Implementar interfaz remoto package engine; import java.rmi.*; import java.rmi.server.*; import compute.*; public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException { super();} C Compute t engine i = new ComputeEngine(); C t E i () public bli Object bj executeTask(Task k( k t) ) { return t.execute(); () } public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } String name = "//localhost/Compute"; try { Compute engine = new ComputeEngine(); Naming rebind(name engine); Naming.rebind(name, System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); } } } Mario Muñoz Organero. Servidores de información 110 RMI Ejemplo 1 Paso 2: Implementar interfaz remoto package engine; String name = "//localhost/Compute"; Naming.rebind(name, engine); public ComputeEngine() throws RemoteException { super();} import java.rmi.*; import java.rmi.server.*; import compute.*; public class ComputeEngine extends UnicastRemoteObject implements Compute { public bli Object bj executeTask(Task k( k t) ) { return t.execute(); () } public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } String name = "//localhost/Compute"; try { Compute engine = new ComputeEngine(); Naming rebind(name engine); Naming.rebind(name, System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); } } } Mario Muñoz Organero. Servidores de información 111 RMI Ejemplo 1 Paso 3: Crear programa cliente Crear clases que invocan métodos remotos Crear controlador de seguridad g Asignar nombre al objeto remoto Invocar métodos del objeto remoto Crear resto de las clases Mario Muñoz Organero. Servidores de información 112 RMI Ejemplo 1 Paso 3: Crear programa cliente package k client; li t import java.rmi.*; import java.math.*; import compute.*; public class ComputePi { public static void main(String args[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { String name = "//" + args[0] + "/Compute"; Compute comp = (Compute) Naming.lookup(name); Pi task = new Pi(Integer.parseInt(args[1])); BigDecimal if (S (System.getSecurityManager() t tS itpiM= (BigDecimal) () ==(comp.executeTask(task)); null) ll) { System.out.println(pi); System.setSecurityManager(new RMISecurityManager()); } catch (Exception e) { } y p p exception: p " + e.getMessage()); g g System.err.println("ComputePi e.printStackTrace(); } } } Mario Muñoz Organero. Servidores de información 113 RMI Ejemplo 1 Paso 3: Crear programa cliente package k client; li t import java.rmi.*; import java.math.*; import compute.*; String name = "//" + args[0] + "/Compute"; public class ComputePi { public static void main(String args[]) { Compute comp = (Compute) Naming.lookup(name); Naming lookup(name); if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { String name = "//" + args[0] + "/Compute"; Compute comp = (Compute) Naming.lookup(name); Pi task = new Pi(Integer.parseInt(args[1])); BigDecimal pi = (BigDecimal) (comp.executeTask(task)); System.out.println(pi); } catch (Exception e) { y p p exception: p " + e.getMessage()); g g System.err.println("ComputePi e.printStackTrace(); } } } Mario Muñoz Organero. Servidores de información 114 RMI Ejemplo 1 Paso 3: Crear programa cliente try{ ( ) comp.executeTask(task); (…) t T k(t k) (…) ( ) import java.rmi.*; import java.math.*; import compute.*; }catch (RemoteException e) { public class ComputePi { public(…) static void main(String args[]) { } if (System.getSecurityManager() == null) { package k client; li t System.setSecurityManager(new RMISecurityManager()); } try { String name = "//" + args[0] + "/Compute"; Compute comp = (Compute) Naming.lookup(name); Pi task = new Pi(Integer.parseInt(args[1])); BigDecimal pi = (BigDecimal) (comp.executeTask(task)); System.out.println(pi); } catch (Exception e) { y p p exception: p " + e.getMessage()); g g System.err.println("ComputePi e.printStackTrace(); } } } Servidores de información Mario Muñoz Organero. 115 RMI Ejemplo 1 Paso 3: Crear programa cliente (resto de clases) package client; import Compute.*; import java.math.*; public class Pi implements Task { private i t static t ti final fi l BigDecimal Bi D i l ZERO = BigDecimal.valueOf(0); Bi D i l l Of(0) private static final BigDecimal ONE = BigDecimal.valueOf(1); private static final BigDecimal FOUR = BigDecimal.valueOf(4); private static final int roundingMode = BigDecimal.ROUND_HALF_EVEN; private int digits; public Pi(int digits){ this.digits = digits;} public Object execute(){return computePi(digits);} public static BigDecimal computePi(int digits) { // calcula usando fórmula de Hachin } public static BigDecimal arctan(int inverseX, // Calcula en radianes el int scale) { arctan(x) = x - (x^3)/3 + (x^5)/5 - // - (x^7)/7 + (x^9)/9 ... } } Mario Muñoz Organero. Servidores de información 116 RMI Ejemplo 1 Paso 4: Compilar la aplicación Compilar interfaces jjavac NombreInterfaz.java j Compilar la clase servidora javac NombreClase.java Generar stubs y skeletons rmic NombreClase Compilar la clase cliente Hacer accesibles vía web las clases necesarias Interfaces, clases del cliente y del servidor (no todas) Mario Muñoz Organero. Servidores de información 117 Servidores de información 118 RMI Ejemplo 1 Paso 4: Compilar interfaces Windows. cd c:\home\profs\mario\src j javac compute\Compute.java t \C t j javac compute\Task.java jar cvf compute.jar j p j compute\*.class p \ UNIX. cd /home/profs/mario/src javac compute/Compute.java javac compute/Task.java jar cvf compute.jar compute/*.class Mario Muñoz Organero. RMI Ejemplo 1 Paso 4: Compilar servidor Windows. cd c:\home\profs\mario\src javac engine\ComputeEngine.java rmic -d . engine.ComputeEngine mkdir c:\home\profs\mario\public_html\classes\engine cp engine\ComputeEngine_*.class \ c:\home\profs\mario\public_html\classes\engine \ \ \ \ \ \ Unix. cd /home/profs/mario/src javac engine/ComputeEngine.java engine/ComputeEngine java rmic -d . engine.ComputeEngine mkdir /home/profs/mario/public_html/classes/engine cp engine/ComputeEngine_ engine/ComputeEngine *.class .class /home/profs/mario/public html/classes/engine /home/profs/mario/public_html/classes/engine Mario Muñoz Organero. Servidores de información 119 RMI Ejemplo 1 Paso 4: Compilar cliente Windows: set CLASSPATH= c:\home\profs\jones\src;c:\home\profs\jones\public_html\classes\compute.jar cd c:\home\profs\jones\src javac client\ComputePi.java javac -d c:\home\profs\jones\public j p j p _html\classes client\Pi.java j UNIX. setenv CLASSPATH /home/profs/jones/src:/home/profs/jones/public_html/classes/c p j ompute.jar cd /home/profs/jones/src javac client/ComputePi.java javac -d d /home/profs/jones/public_html/classes /home/profs/jones/public html/classes client/Pi.java client/Pi java Mario Muñoz Organero. Servidores de información 120 RMI Ejemplo 1 Paso 5: Ejecutar la aplicación Arrancar el registro Arrancar el servidor Ejecutar el cliente Servidores de información Mario Muñoz Organero. 121 RMI Ejemplo 1 Paso 5: Arrancar el registro Puerto por defecto Windows (utilizar javaw si no está disponible start). unset CLASSPATH start rmiregistry UNIX. unsetenv CLASSPATH rmiregistry & Deshabilitar el classpath Puerto 2001 Windows. start rmiregistry 2001 UNIX. rmiregistry 2001 & Mario Muñoz Organero. Servidores de información 122 RMI Ejemplo 1 Paso 5: Arrancar el servidor Windows. Windows set CLASSPATH=c:\home\profs\mario\src;c:\home\profs\mario\public_html\classes\compute.jar Unix. setenv CLASSPATH /home/profs/mario/src:/home/profs/mario/public_html/classes/compute.jar Windows. j java -Djava.rmi.server.codebase=file:/c:\home\profs\mario\public_html\classes/ Dj i d b fil / \h \ f \ i \ bli ht l\ l / -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine ComputeEngine engine.ComputeEngine UNIX. java -Djava.rmi.server.codebase=http://zaphod/~mario/classes/ -Djava rmi server hostname=zaphod east sun com -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine.ComputeEngine Mario Muñoz Organero. Servidores de información 123 RMI Ejemplo 1 •Dirección desde donde el servidor distribuye sus clases •Información de localización que se Paso 5: Arrancar el servidor añadirá cuando se envien clases a otras Wi d Windows. máquinas virtuales set CLASSPATH=c:\home\...\src;c:\home\...\public_html\classes\compute.jar •Permitirá que el receptor pueda Unix. descargar dichas clases setenv CLASSPATH /home/…/src:/home/…/public_html/classes/compute.jar Windows. j java -Djava.rmi.server.codebase=file:/c:\home\...\public_html\classes/ Dj i d b fil / \h \ \ bli ht l\ l / -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine ComputeEngine engine.ComputeEngine UNIX. java -Djava.rmi.server.codebase=http://zaphod/~mario/classes/ -Djava rmi server hostname=zaphod east sun com -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine.ComputeEngine Mario Muñoz Organero. Servidores de información 124 RMI Ejemplo 1 Paso 5: Arrancar el servidor Nombre del servidor Wi d Windows. set CLASSPATH=c:\home\...\src;c:\home\...\public_html\classes\compute.jar Unix. setenv CLASSPATH /home/…/src:/home/…/public_html/classes/compute.jar Windows. j java -Djava.rmi.server.codebase=file:/c:\home\...\public_html\classes/ Dj i d b fil / \h \ \ bli ht l\ l / -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine ComputeEngine engine.ComputeEngine UNIX. java -Djava.rmi.server.codebase=http://zaphod/~mario/classes/ -Djava rmi server hostname=zaphod east sun com -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine.ComputeEngine Mario Muñoz Organero. Servidores de información 125 RMI Ejemplo 1 Paso 5: Arrancar el servidor Wi d Windows. Fichero con política de seguridad Indica permisos concedidos a las clases del codebase /home/…/src:/home/…/public_html/classes/compute.jar set CLASSPATH=c:\home\...\src;c:\home\...\public_html\classes\compute.jar Unix. setenv CLASSPATH Windows. j java -Djava.rmi.server.codebase=file:/c:\home\...\public_html\classes/ Dj i d b fil / \h \ \ bli ht l\ l / -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine ComputeEngine engine.ComputeEngine UNIX. java -Djava.rmi.server.codebase=http://zaphod/~mario/classes/ -Djava rmi server hostname=zaphod east sun com -Djava.rmi.server.hostname=zaphod.east.sun.com -Djava.security.policy=java.policy engine.ComputeEngine Mario Muñoz Organero. Servidores de información 126 RMI Ejemplo 1 Paso 5: Arrancar el cliente Windows. set CLASSPATH c:\home\profs\jones\src;c:\home\profs\jones\public_html\classes\compute.jar java -Djava.rmi.server.codebase=file:/c:\home\profs\jones\public_html\classes/ -Djava.security.policy=java.policy client.ComputePi localhost 20 UNIX. setenv CLASSAPTH /home/profs/jones/src:/home/profs/jones/public_html/classes/compute.jar /home/profs/jones/src:/home/profs/jones/public html/classes/compute.jar java -Djava.rmi.server.codebase=http://ford/~jones/classes/ -Djava.security.policy=java.policy client.ComputePi zaphod.east.sun.com 20 Servidores de información Mario Muñoz Organero. 127 RMI Ejemplo 1 •Dirección Paso 5: Arrancar el cliente desde donde el cliente distribuye sus clases Windows. set CLASSPATH c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar java -Djava.rmi.server.codebase=file:/c:\home\jones\public Djava.rmi.server.codebase file:/c:\home\jones\public_html\classes/ html\classes/ -Djava.security.policy=java.policy client.ComputePi localhost 20 UNIX. setenv CLASSAPTH /home/jones/src:/home/jones/public_html/classes/compute.jar java -Djava.rmi.server.codebase=http://ford/~jones/classes/ -Djava.security.policy=java.policy client.ComputePi zaphod.east.sun.com 20 Mario Muñoz Organero. Servidores de información 128 RMI Ejemplo 1 Paso 5: Arrancar el cliente Fi h Fichero que contiene ti la l política líti d de seguridad id d Windows. set CLASSPATH c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar java -Djava.rmi.server.codebase=file:/c:\home\jones\public Djava.rmi.server.codebase file:/c:\home\jones\public_html\classes/ html\classes/ -Djava.security.policy=java.policy client.ComputePi localhost 20 UNIX. setenv CLASSAPTH /home/jones/src:/home/jones/public_html/classes/compute.jar java -Djava.rmi.server.codebase=http://ford/~jones/classes/ -Djava.security.policy=java.policy client.ComputePi zaphod.east.sun.com 20 Mario Muñoz Organero. Servidores de información 129 RMI Ejemplo 1 Paso 5: Arrancar el cliente Windows. set CLASSPATH Parámetro 1: Nombre del servidor que realizará el cálculo c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar java -Djava.rmi.server.codebase=file:/c:\home\jones\public Djava.rmi.server.codebase file:/c:\home\jones\public_html\classes/ html\classes/ -Djava.security.policy=java.policy client.ComputePi localhost 20 UNIX. setenv CLASSAPTH /home/jones/src:/home/jones/public_html/classes/compute.jar java -Djava.rmi.server.codebase=http://ford/~jones/classes/ -Djava.security.policy=java.policy client.ComputePi zaphod.east.sun.com 20 Mario Muñoz Organero. Servidores de información 130 RMI Ejemplo 1 Paso 5: Arrancar el cliente Windows. Parámetro 2: Número de decimales set CLASSPATH c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar con el que queremos que realice el java -Djava.rmi.server.codebase=file:/c:\home\jones\public Djava.rmi.server.codebase file:/c:\home\jones\public_html\classes/ html\classes/ cálculo -Djava.security.policy=java.policy client.ComputePi localhost 20 UNIX. setenv CLASSAPTH /home/jones/src:/home/jones/public_html/classes/compute.jar java -Djava.rmi.server.codebase=http://ford/~jones/classes/ -Djava.security.policy=java.policy client.ComputePi zaphod.east.sun.com 20 Mario Muñoz Organero. Servidores de información 131 Servidores de información 132 RMI. Arquitectura Mario Muñoz Organero. RMI: ¿Cómo funciona? Servicios utilizados Secuenciación de objetos (serialization) Servicio de nombrado (naming service) En p particular, RMI registry g y Descarga de clases por la red: (Class Loader) Servicios de seguridad (Security Manager) Recolección de basura distribuida (distributed garbage collection) Mario Muñoz Organero. Servidores de información 133 RMI: ¿Cómo funciona? Secuenciación de objetos (serialization) El paso de parámetros por valor introduce un problema: Si se pasa un objeto por la red y éste contiene referencias a otros objetos, ¿cómo se resuelven las referencias en la máquina de destino? Secuenciar un objeto consiste en convertirlo en una secuencia de bits que representa a ese objeto. objeto Para hacer que un objeto sea secuenciable, éste debe implementar el interfaz java.io.Serializable Es una interfaz de marcado (no contiene métodos): indica que un objeto puede ser secuenciable (serializable) y reconstruible (deserializable). Es posible implementar una secuenciación a medida (custom serialization) con writeObject() y readObject(). Normalmente. los mecanismos existentes por defecto son suficientemente buenos. Mario Muñoz Organero. Servidores de información 134 RMI: ¿Cómo funciona? Reglas para secuenciar objetos Cualquier tipo primitivo (int, char, etc.) es secuenciado automáticamente y está disponible en la reconstrucción del objeto al que pertenece. Los objetos contenidos en el objeto a secuenciar pueden o no ser secuenciados: Si se marcan con la palabra transient, éstos no son secuenciados con el objeto y no están disponibles en la reconstrucción. Los objetos no marcados con transient deberán implementar el interfaz java io Serializable java.io.Serializable. Si no están marcados con transient ni implementan java.io.Serializable, se lanza una excepción NotSerializable. Objetos j transient típicos: p objetos muy grandes recursos no reconstruibles en la máquina de destino (sockets o conexiones a bases de datos) i f información ió confidencial. fid i l Servidores de información Mario Muñoz Organero. 135 RMI: ¿Cómo funciona? Secuenciación recursiva Cuando se secuencia un objeto, todos sus objetos no transient, también serán secuenciados. Esto se realiza de forma recursiva para todos los subobjetos. java.io.Serializable java.io.Serializable java.io.Serializable Clase2 Clase3 c Clase3 MiClase int a transient long b String s Clase2 c java io Serializable java.io.Serializable Java.lang.String Mario Muñoz Organero. Servidores de información 136 RMI: ¿Cómo funciona? Paso de parámetros / valores de retorno Dos maneras de pasar parámetros a métodos remotos por valor: se inserta una copia “secuenciada” del objeto en el flujo de salida que corresponde al envío de la invocación o el retorno es el objeto remoto el que viaja por referencia: se inserta una copia “secuenciada” del stub del objeto en el flujo de salida que corresponde al envío de la invocación o el retorno es el stub del objeto remoto (instancia de la clase stub) el que viaja. Tres casos: tipos primitivos : se pasan por valor; todos son serializables objetos locales: se pasan por valor (si no son serializables, exception), se crea un nuevo objeto bj t en la l máquina á i virtual i t l que recibe ib la l copia. i objetos remotos: se pasan por referencia, se crea un nuevo stub en la máquina virtual que recibe la copia Mario Muñoz Organero. Servidores de información 137 RMI: ¿Cómo funciona? Paso de parámetros / valores de retorno Observaciones: Los objetos remotos no viajan, viajan en cambio se envían referencias Un stub se debe convertir (cast) al tipo de la interfaz remota que implemente la clase del objeto remoto al que corresponde ⌧ si un objeto remoto implementa varias interfaces remotas un cliente solo puede convertir el stub a una de ellas Dos stubs que se refieren al mismo objeto remoto en el mismo servidor se consideran iguales bajo la operación equals() Mario Muñoz Organero. Servidores de información 138 RMI: ¿Cómo funciona? Declaración de parámetros Los parámetros / valores de retorno que son objetos remotos se pasan por referencia Por tanto, P t t la l clase l d un parámetro de á t de d un método ét d de d una interfaz i t f remota t no puede ser la de un objeto remoto su clase es la de un objeto no remoto o la de una interfaz remota Por ejemplo, si MyRemote es una interfaz remota y MyRemoteImpl es una clase que la implementa y metodo es un método de otra interfaz remota, con respecto a la declaración de metodo: public void metodo(MyRemote remoto) ¡Bien! throws RemoteException public bli void id metodo(MyRemoteImpl t d (M R t I l remoto) t ) throws RemoteException ¡Mal! Servidores de información Mario Muñoz Organero. 139 RMI Objeto remoto vs objeto local Objeto local Objeto remoto Instancia de una clase Java Instancia de una clase Java que implementa una o varias interfaces que extienden java.rmi.Remote j Se crea una nueva instancia con new() Acceso directo Eliminado por el garbage collector cuando no hay referencias locales que apuntan a el Sus métodos no pueden java.rmi.RemoteException Mario Muñoz Organero. lanzar En la misma JVM se crea una nueva instancia con new(); desde otra JVM sólo se puede crear una nueva instancia por activación remota Acceso por un stub Eliminado por el garbage collector cuando no hay ni referencias locales ni referencias remotas t activas ti que apuntan t a el; l una referencia remota se considera activa si no ha sido soltado y se ha realizado un acceso hace poco (con un tiempo configurable) Sus métodos pueden lanzar java.rmi.RemoteException 140 RMI Registry Registr Servidor de nombres ¿Cómo el cliente encuentra un servicio remoto de RMI? Por medio de un servicio de nombres o de directorios relaciona nombres (cadenas de caracteres) con objetos remotos El servicio de nombres/directorios tiene que estar escuchando en un puerto conocido de una máquina conocida RMI puede utilizar distintas servicios de nombres, p.e.: JNDI (Java (Ja a Naming and Directory Director Interface) RMI Registry: servicio sencillo incluido con RMI RMI registry Implementación actual ejecuta en la misma máquina que el objeto remoto Por defecto, escucha en el puerto 1099 Mario Muñoz Organero. Servidores de información 141 RMI Registry Registr Clases e interfaces Interfaz remota Registry lookup(), bind(), unbind(), rebind(), list() Trabaja con nombres que son simples cadenas de caracteres Clase LocateRegistry createRegistry(): crea un nuevo objeto que implementa la interfaz Registry y d devuelve l una referencia f i a este t objeto bj t getRegistry(): devuelve una referencia a un objeto que implementa la interfaz Registry en una máquina dada en una máquina dada y un puerto dado Clase Naming IInvoca métodos ét d de d un objeto bj t remoto t que implementa i l t Registry Trabaja con nombres en forma de URL: rmi://maquina:puerto/ruta Mario Muñoz Organero. Servidores de información 142 RMI Registry Registr Clase principal: Naming Método lookup(URL) devuelve el objeto remoto (eso es, su referencia) que corresponde al URL Método bind(URL, objeto remoto) asocia el URL al objeto remoto (eso es, a su referencia) Método unbind(URL) desasocia el URL del objeto remoto (eso es, de su referencia) Método rebind(URL, objeto remoto) asocia el URL al objeto remoto (eso es, a su referencia) borrando la previa el uso de rebind evita la posibilidad de una AlreadyBoundException Método list() Devuelve un array que contiene los URLs actualmente asociados a un objeto remoto en el registry Mario Muñoz Organero. Servidores de información 143 RMI Retrollamadas (callbacks) Un servidor puede necesitar hacer una llamada al cliente Para lograrlo, el cliente debe comportarse como servidor Muchas veces es más práctico llamar a java.rmi.server.UnicastRemoteObject.exportObject() en vez de extender UnicastRemoteObject Mario Muñoz Organero. Servidores de información 144 RMI Ubicación de ficheros Sin descarga automática de clases: Cli t Cliente Servidor Clase Implementación del Servidor Clase Implementación cliente Clase de Interfaz Remota Clase de Interfaz Remota Clase Stub Clase Skeleton Mario Muñoz Organero. Clase Stub Servidores de información 145 RMI Descarga dinámica de clases RMI utiliza serialización para enviar datos entre máquinas distintas En el proceso de marshaling se serializan los objetos y se envian junto con información de localización para permitir que la definición de clases se pueda descargar en la máquina que recibe los objetos. En el proceso de unmarshalling para convertir de nuevo los datos en objetos activos es necesario resolver la localización de las clases que definen esos objetos. Cuando no se pueden resolver las clases de manera local es necesario descargar la definición de las clases de una máquina remota. Cuando un cliente invoca un método de un objeto remoto es posible que tenga que tratar con objetos cuyas y definiciones de clase son desconocidas p para el classLoader local. Para que los objetos remotos estén activos en la MV local es necesario descargar la definición de las clases de todos los objetos remotos con los que tenga que tratar: La definición de clase del stub q que representa p al objeto j cuyo y método se invoca. La definición de clase de los objetos que se pasen como parámetros La definición de clase de los objetos que se devuelvan como tipo de retorno L definición La d fi i ió de d clase l d los de l objetos bj t excepción que se lancen l en ell método ét d Mario Muñoz Organero. Servidores de información 146 RMI Descarga dinámica de clases Durante el marshalling , junto con el nombre de una clase, RMI coloca automáticamente su localización (un codebase) en forma de URL el URL de la clase se transmite en el flujo de salida Si un cliente o un servidor encuentra el nombre de una clase que no reconoce, intenta cargarla como sigue: del CLASSPATH local utilizando el Class Loader local, si es posible d l URL transmitido del t itid junto j t con ell nombre, b utilizando tili d ell RMIClassLoader l d en caso de d un stub t b encontrado por un servidor como parámetro de una llamada a un método remoto o por un cliente como resultado de una tal llamada de un URL especificado en la propiedad java.rmi.server.codebase utilizando el RMIClassLoader en caso de una clase local Especificación del codebase que proporciona las clases para objetos (p.e. Stubs) enviados desde este JVM: j java -Djava.rmi.server.codebase=http://maquina/ruta/classes j i d b h // i / / l ServImpl l Se puede obligar la carga de todas las clases del codebase local poniendo la propiedad java.rmi.server.useCodebaseOnly a true Mario Muñoz Organero. Servidores de información 147 RMI descarga de clases RMI, Seguridad El RMIClassLoader no descarga clases remotas si no hay instalado un SecurityManager System.setSecurityManager(new RMISecurityManager()); El RMISecurityManager impide que los stubs escuchen en puertos, manipulen hilos fuera de su grupo, grupo enlacen con DLLs, DLLs creen procesos, procesos abran descriptores de ficheros, etc. Para aplicaciones p especiales p el p programador g puede sustituir el cargador p g de clases (RMIClassLoader) y el gestor de seguridad (RMISecurityManager) que vienen con RMI por el suyo propio pero para las aplicaciones estándar no es necesario. Mario Muñoz Organero. Servidores de información 148 RMI Activación / desactivación de objetos La clase Activatable y el demonio rmid permiten la creación y ejecución j de objetos j remotos bajo j demanda La clase que implementa la interfaz remota debe extender java.rmi.activation.Activatable Hace falta también una clase setup (montaje) para instalar un SecurityManager pasar la información sobre la clase activable al rmid registrar una referencia y un nombre con el rmiregistry entre otras cosas El rmid requiere un fichero de política de seguridad (security policy) Mario Muñoz Organero. Servidores de información 149 Papeles en la activación Activador (rmid) – Inicia instacias de JVMs en el servidor bajo demanda. demanda Grupo de activación – una instancia separada de una JVM que contiene grupos de objetos activados. activados Monitor de activación – monitoriza el estado de los grupos de activación y de sus objetos activados. Sistema de activación – registro de grupos y objetos activables Mario Muñoz Organero. Servidores de información 150 Creando objetos activables (I) Paso 1 – Crear una interfaz remota import java.rmi.Remote; import java.rmi.RemoteException; public interface HelloInterface extends Remote { public String sayHello() throws RemoteException; } Mario Muñoz Organero. Servidores de información 151 Creando objetos activables (II) Paso 2 – Implementar el objeto remoto public class HelloServer extends Activatable implements HelloInterface { public HelloServer(ActivationID id, MarshalledObject data) throws RemoteException { super(id,0); } public String sayHello() throws RemoteException { return “Hello Hello World World” + new Date(); } Mario Muñoz Organero. Servidores de información 152 Creando objetos activables (III) Paso 3 – Registrar el objeto en el sistema public static void main (String[] argv) { try { ActivationGroupDesc mygroupdes = new ActivationGroupDesc(null, null); ActivationGroupID mygroupid = ActivationGroup.getSystem().registerGroup(mygroupdes); ActivationGroup.createGroup(mygroupid,mygroupdes,0); ActivationDesc objectdesc = new ActivationDesc(“HelloServer”,”file:///c:/wuye/….”,null); ( y ) HelloInterface myobject = (HelloInterface)Activatable.register(objectdesc); Mario Muñoz Organero. Servidores de información 153 Creando objetos activables (IV) Naming.rebind(“helloObject”,myobject); S t System.out.println(“helloObject t i tl (“h ll Obj t bound b d in i registry”); i t ”) } catch(Exception e) { … … } } java -Djava.security.policy=registerit.policy RegisterIt g Mario Muñoz Organero. Servidores de información 154 RMI Paquetes Package java.rmi clientes: para acceder a servicios remotos RMI y para ubicar servicios RMI en máquinas á i remotas. t Package java.rmi.server Servidores: para hacer accesible un servicio RMI a peticiones TCP/IP y HTTP proxy. Package java.rmi.registry Creación y ubicación de registros de nombres. Package java.rmi.dgc Recolección de basura para un entorno distribuido. Package java.rmi.activation (J2SE SDK 1.2+) Permite que los servidores sólo sean activados cuando haya una petición real de servicio. 155 Servidores de información Mario Muñoz Organero. RMI Clases principales Object class IOException class java.lang Remote Interface java.rmi.registry java.rmi java.io Remote Exception class LocateRegistry class R RemoteObject Obj class l Registry Interface RemoteStub class Naming g class Tu clase stub Registry Implementation Extiende Implementa Mario Muñoz Organero. Invoca Tu clase cliente java.rmi.server RemoteServer class Tu interfaz remoto UnicastRemoteObject class Tu claseServidores servidora de información 156 Escenario básico Suma en contador remoto Client System Naming System Server X setSecurityManager Y rebind Z setSecurityManager y g [ lookup Proxy Server repite 1000 veces \ sum(0) ] start timer sum(0) ^ increment _ stop timer Cliente Mario Muñoz Organero. increment Servidor Servidores de información RMI sobre IIOP 157 ¿Qué es RMI sobre IIOP? RMI sobre IIOP (RMI-IIOP), desarrolado por IBM y Sun, es una nueva versión de RMI (Remote Method Invocation) para IIOP (Internet Inter-ORB Protocol) que combina la fácil programación de RMI con la interoporabilidad con CORBA. Mario Muñoz Organero. Servidores de información 159 RMI-IIOP (I) SUN e IBM implementaron RMI-over-IIOP (RMI-IIOP) para reemplazar al protocolo de comunicación de RMI (Java Remote Method Protocol or JRMP). JRMP) Inprise, Netscape, Oracle, Sun e IBM especificaron el mapeo inverso de Java a IDL. Limitaciones del mapeo: Las costantes solo pueden ser de tipos primitivos o java.lang.String IDL normalmente no soporta sobrecarga de métodos. Una clase no puede heredar un método con la misma firma de dos interfaces. Los interfaces deben ser public. No se consideran los nombres Case-sensitive Mario Muñoz Organero. Servidores de información 160 RMI-IIOP (II) Limitaciones en tiempo de ejecución: Enviar (serializar) un árbol de objetos de ORB a ORB puede dar problemas si varios nodos apuntan al mismo objeto. CORBA no define el distributed garbage collection El Casting de stubs no funciona apropiadamente, apropiadamente se usa el método estático narrow de la clase java.rmi.PortableRemoteObject. CORBA no tiene ti d descarga automática t áti de d clases. l Mario Muñoz Organero. Servidores de información 161 RMI-IIOP (III) Pasos para escribir una aplicación RMI-IIOP: usar javax.rmi.PortableRemoteObject javax rmi PortableRemoteObject en vez de usar java.rmi.UnicastRemoteObject Usar JNDI (Java Naming and Directory Interface) en vez del RMI Registry Hacer el casting de objetos remotos con el método narrow de la clase PortableRemoteObject Mario Muñoz Organero. Servidores de información 162 Poniendolo todo junto La implementación del objeto remoto debe extender javax.rmi.PortableRemoteObject class, en vez de java rmi server UnicastRemoteObject java.rmi.server.UnicastRemoteObject. Los stub y skeleton se generan usando el compilador rmic compatible con RMI/IIOP. Este compilador tiene la opción -iiop que produce stubs y ties IIOP (ties son los skeletons en CORBA). Todas las referencias al RMI Naming registry se tienen que cambiar por el uso del JNDI para hablar con el CORBA Naming Service. El casting se hace usando el método javax rmi PortableRemoteObject narrow() javax.rmi.PortableRemoteObject.narrow(). Mario Muñoz Organero. Servidores de información 163 Extendiendo PortableRemoteObject rmic -iiop -d /home/myclasses IIOPAccountImpl Esto genera una clase IIOPAccountImpl_Stub IIOPA IIOPAccountImpl_Tie tI l Ti Mario Muñoz Organero. y Servidores de información una 164 La aplicación servidora Mario Muñoz Organero. Servidores de información 165 Servidores de información 166 El cliente Mario Muñoz Organero.