Transparencias 07-08 - Departamento de Ingeniería Telemática

Anuncio
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.
Descargar