Está en la página 1de 15

Arquitecturas Distribuidas en Redes Heterogneas

Prcticas con CORBA


Curso 2008-2009
14 Noviembre 2008 - v0.1.1
1. Introduccin
1.1. Qu es CORBA?
CORBA (Common Object Request Broker Architecture) es un estndar que dene una plataforma
para el desarrollo de sistemas distribuidos basados en el paradigma de orientacin a objetos. La
norma est denida por el OMG (Object Management Group, autores tambin del estndar UML)
mediante un conjunto de APIs, protocolos de comunicacin y mecanismos que garantizan la inter-
operabilidad entre aplicaciones independientemente de la plataforma y del lenguaje de implemen-
tacin.
Conceptualmente, CORBA se asemeja bastante a Java RMI. Sin embargo, posee ciertas carac-
tersticas que lo hacen diferente. La principal de ellas es que CORBA es agnstico respecto del
lenguaje de programacin. Tal y como veremos ms adelante, las interfaces de los objetos se de-
nen mediante un lenguaje denominado IDL (Interface Description Language). A partir de dicho
lenguaje, se generarn los stubs y skeletons correspondientes en el lenguaje de implementacin. La
infraestructura CORBA proporciona protocolos interoperables que garantizan el correcto paso de
mensajes independientemente del lenguaje empleado (cliente y servidor pueden estar escritos en
distintos lenguajes).
Es importante destacar que CORBA es una especicacin pblica, no un producto. Los distin-
tos estndares que denen la norma pueden ser seguidos para crear diversas implementaciones, lo
cual garantiza tambin la interoperabilidad entre distintos fabricantes.
Figura 1: Funcionamiento bsico de RMI
1
1.2. Cmo funciona CORBA?
El funcionamiento bsico de CORBA pasa por la denicin de las interfaces de los componentes
mediante el lenguaje IDL. Este lenguaje descriptivo nos proporciona mecanismos para denir tipos,
mdulos, interfaces, operaciones, excepciones, etc. De esta forma, el programador puede denir la
forma que tendrn los componentes de su sistema. Tras esto, el cdigo IDL ser compilado al len-
guaje de implementacin (siguiendo unas reglas de mapping estandarizadas), generando los stubs
del cliente y los skeletons del servidor, tal y como se muestra en el diagrama UML de la gura 2.
Figura 2: Compilacin de una calculadora IDL
En dicha compilacin se generan los siguientes elementos bsicos con los que vamos a trabajar:
La interfaz de operaciones, en este caso CalculatorOperations. Esta interfaz incluye
todas las operaciones denidas en el chero IDL para nuestra calculadora.
La clase base del servant, en este caso CalculatorPOA. En CORBA se denomina servant al
objeto que encarna el comportamiento del objeto remoto. Tener claro este concepto es muy
importante, ya que resulta clave a la hora de comprender cmo se comporta un servidor
CORBA. Pensemos en los objetos remotos como si fueran personas en una pelcula u obra
de teatro y, en los servants como actores que interpretan esos personajes o papeles. A la hora
de dar comportamiento a nuestra calculadora (es decir, implementar sus operaciones) debe-
remos crear una nueva clase que extienda de esta, generalmente aadiendo el sujo Impl al
nal para evitar confusiones (en nuestro caso, CalculatorImpl). Por supuesto, esta nueva
clase deber implementar las operaciones de nuestra calculadora.
La interfaz del objeto remoto, en nuestro caso Calculator. Esta interfaz, que extiende tan-
to CalculatorOperations como CORBA.Object representa al objeto calculadora remoto
para ser empleado desde los clientes.
La clase stub, en este caso _CalculatorStub. Esta clase acta de stub o proxy del objeto
remoto, implementando las mismas operaciones que la calculadora. Esta clase nunca es ins-
tanciada directamente desde el cdigo del cliente, sino que se obtiene un objeto de la misma
en forma de la interfaz Calculator.
2
Adicionalmente, se generarn otras clases que complementan a las anteriores.
La clase helper, en nuestro caso CalculatorHelper. Esta clase ofrece un conjunto de ope-
raciones auxiliares para la conversin de objetos del tipo Calculator, serializaciones, etc.
La clase holder, en nuestro caso CalculatorHolder. En Remoting vimos que los parme-
tros de una invocacin a mtodo remoto se pasaban por valor, es decir, en modo in (excepto
los objetos que tambin son remotos). CORBA permite especicar tres tipos diferentes de mo-
do de pas de parmetros con una semntica similar a la de Ada95: in, inout y out. En este
ltimo caso, la clase holder permite encapsular el objeto pasado como parmetro para que
pueda ser manipulado por el servant.
La clase tie, en nuestro caso CalculatorPOATie. Esta clase, que extiende CalculatorPOA,
proporciona un servant listo para ser empleado cuya misin es la de recubrir a un objeto que
implemente CalculatorOperations, remitiendo las llamadas a los mtodos de la calcula-
dora a las mismas operaciones del objeto recubierto.
Como vemos, gran parte de la magia de CORBAse obtiene a partir de la compilacin de che-
ros IDL. Pero necesitamos algo ms. Necesitamos un mecanismo para desplegar objetos remotos y
instanciarlos. Esto, se consigue mediante los siguientes dos mecanismos:
ORB (Object Request Broker). Este artefacto, ofrecido en forma de clase singleton, ofrece un
conjunto de funcionalidades que permite establecer una serie de propiedades del middleware,
instanciar objetos remotos, resolver y registrar servicios, etc.
Portable Server. El despliegue de objetos remotos no es trivial. A menudo, en sistemas com-
plejos resulta necesario contar con mecanismos que proporcionen un gran control sobre los
componentes a desplegar. Para evitar que dichos mecanismos sean implementados por los
fabricantes sin interoperabilidad alguna, CORBA dene en su estndar un conjunto de arte-
factos que satisfacen estas necesidades:
POA o Portable Object Adapter. Esta abstraccin proporciona mecanismos para desplegar
objetos remotos bajo un conjunto de polticas que condicionan su comportamiento en lo
que al despliegue se reere. Los POA se disponen en una estructura jerrquica, a partir
de un POA raz desde el cual podemos crear nuevos POA hijos, formando un rbol.
POA Manager. Cada POA tiene asociado un POA Manager, pudiendo varios de ellos
compartir el mismo. Esta abstraccin controla el comportamiento en ejecucin de los ob-
jetos, deniendo polticas de tratamiento de peticiones, modelo de multiprocesamiento,
etc.
CORBA es bien conocido por su complejidad. Sus diseadores pensaron en una solucin que
cubriera mediante un estndar todas las necesidades de la industria en cuanto a lo que debe pro-
porcionar un middleware. Esto, casi de manera inevitable, supone un sistema complejo.
El objetivo de esta prctica es proporcionar una vista general de CORBA a travs de algunos
ejemplos prcticos. No te preocupes si todos estos conceptos quedan algo confusos, ya que los
comprenders mejor con los casos prcticos.
1.3. Preguntas
Hemos visto que existe una diferencia clara entre un objeto remoto y el servant que lo encar-
na. Entiendes correctamente esta diferencia? Crees que sera posible que un mismo objeto
remoto fuese encarnado por varios servants? Recuerdas el modo de vida SingleCall de Remo-
ting? Crees que tiene relacin? Sera posible lo contrario, que varios objetos remotos fuesen
encarnados por el mismo servant? Se te ocurre un escenario en el que esto tuviera sentido?
Hemos visto que el cdigo IDL generar un stub que implementa las operaciones de la cal-
culadora. Pero... qu hacen esas operaciones? Qu contiene su implementacin? Cul es el
comportamiento que tienen asociado? Suman y multiplican o hacen otra cosa diferente?
3
Hemos visto que la clase CalculatorHolder se usa para contener objetos en el caso de que
una calculadora se pase como parmetro out. Entiendes claramente el motivo? Entiendes
que en Java no se puede devolver un nuevo objeto a travs de un argumento?
Hemos visto que la clase CalculatorPOATie proporcionaba un servant que recubra un
objeto CalculatorOperations. En qu escenario esto puede ser til? Se te ocurre alguno?
2. Primera parte: una calculadora local
Vamos a comenzar realizando un ejercicio de implementacin de una calculadora no distribui-
da. Para ello, crearemos una clase CalculatorImpl como la siguiente
1
:
1 /
*
2
*
File : CalculatorImpl.java
3
*
Description : A simple non-distributed calculator class.
4
*
5
*
/
6
7 public class CalculatorImpl
8 {
9
10 public float add(float lhs, float rhs)
11 {
12 return lhs + rhs;
13 }
14
15 public float multiply(float lhs, float rhs)
16 {
17 return lhs
*
rhs;
18 }
19
20 }
Ahora crearemos un programa cliente que haga uso de esa calculadora:
1 /
*
2
*
File : Client.java
3
*
Description : A simple client which uses a non-distributed calculator.
4
*
5
*
/
6
7 public class Client
8 {
9
10 public static void main(String args[])
11 {
12 // Create the calculator.
13 CalculatorImpl cal = new CalculatorImpl();
14
15 // Use the calculator.
16 try
17 {
18 System.out.println("Adding: 5 + 3 = " + cal.add(5,3));
19 System.out.println("Multiplying: 10
*
2 = " + cal.multiply(10,2));
1
Un consejo!! Nos guste o no, la mayor parte de los profesionales tcnicos de este planeta se comunican en ingls. Suele
ser una buena idea escoger identicadores en ese idioma (Calculator en lugar de Calculadora), escribir comentarios, etc, para
que cualquiera pueda entender tu programa. Nunca se sabe en qu manos puede caer tu cdigo!
4
20 } catch (Exception ex)
21 {
22 System.out.println("Unexpected error was ocurred.");
23 ex.printStackTrace();
24 }
25 }
26 }
Con esto, podemos compilar nuestros cheros y ejecutar la prueba.
3. Segunda parte: una calculadora distribuida
Ahora vamos a construir nuestra calculadora, esta vez para que pueda ser distribuida a travs
de CORBA.
3.1. Preparacin del entorno
Antes de nada, vamos a preparar el entorno para poder crear y ejecutar aplicaciones CORBA.
Como discutimos anteriormente, CORBA es una especicacin que cualquier fabricante puede
desarrollar, quedando garantizada la interoperabilidad entre distintas implementaciones. En nues-
tro caso, vamos a emplear TIDorbJ, la implementacin para Java desarrollada por Telefnica I+D y
publicada bajo licencia libre GNU/GPL. Necesitars los siguientes elementos:
TIDIdlC, el compilador de IDL a Java y C++. Esta herramienta genera cdigo Java o C++ a
partir de cheros IDL. Puedes descargarlo de:
http://gsyc.es/moodle/le.php/8/Practicas/CORBA/TIDorbJ/tididlc_1.3.6-bin.tar.gz
TIDorbJ, el ncleo de la implementacin en forma de librera, disponible en:
http://gsyc.es/moodle/le.php/8/Practicas/CORBA/TIDorbJ/tidorbj_6.3.2-bin.tar.gz
Descomprime ambos cheros en tu directorio personal o home. Te sugerimos que establezcas un
par de variables de entorno que te resultarn tiles:
Aade a PATH el directorio tididlc/bin.
Exporta la variable TIDORB_JAR para que almacene la ruta del chero tidorbj/lib/tidorbj.jar.
Con estos pasos, ya todo est listo para comenzar a codicar.
3.2. Denicin de las interfaces IDL
Anteriormente denimos una calculadora en Java para ser usada localmente. Llegado a este
punto, vamos a denir la interfaz de la misma calculadora empleando el lenguaje IDL:
1 /
*
2
*
File : mymath.idl
3
*
Description : A math module which contains a calculator.
4
*
/
5
6 module mymath
7 {
8
9 interface Calculator
5
10 {
11 float add(in float lhs, in float rhs);
12 float multiply(in float lhs, in float rhs);
13 };
14
15 };
Para compilar este chero y generar el cdigo Java correspondiente, invocaremos el script idl2java.
1 idl2java mymath.idl
Observars que este comando ha creado un nuevo directorio mymath/. Echa un vistazo al con-
tenido y trata de identicar las clases e interfaces descritas en la seccin primera.
Ahora vamos a llevar a cabo un pequeo cambio en la implementacin de nuestra calculadora.
Deniremos de nuevo el chero CalculatorImpl.java con el siguiente contenido:
1 /
*
2
*
File : CalculatorImpl.java
3
*
Description : A simple CORBA-distributed (servant) calculator class
4
*
5
*
/
6
7 import mymath.CalculatorPOA;
8
9 public class CalculatorImpl extends CalculatorPOA
10 {
11
12 public float add(float lhs, float rhs)
13 {
14 return lhs + rhs;
15 }
16
17 public float multiply(float lhs, float rhs)
18 {
19 return lhs
*
rhs;
20 }
21
22 }
Como se puede observar, tan solo hemos hecho que nuestra clase herede de CalculatorPOA,
importando la misma desde el paquete mymath.
Ahora vamos a hacer algo un poco ms complejo: implementar el servidor. Para ello, empleare-
mos el siguiente cdigo:
1 /
*
2
*
File : Server.java
3
*
Description : A calculator server.
4
*
5
*
/
6
7 import java.util.Properties;
8 import java.io.
*
;
6
9
10 import org.omg.CosNaming.
*
;
11 import org.omg.CosNaming.NamingContextPackage.
*
;
12 import org.omg.CORBA.
*
;
13 import org.omg.PortableServer.
*
;
14
15 public class Server
16 {
17 public static void main(String args[])
18 {
19 try
20 {
21 // Create ORB properties for using TID implementation.
22 Properties orb_props = new Properties();
23 orb_props.setProperty(
24 "org.omg.CORBA.ORBClass",
25 "es.tid.TIDorbj.core.TIDORB");
26 orb_props.setProperty(
27 "org.omg.CORBA.ORBSingletonClass",
28 "es.tid.TIDorbj.core.SingletonORB");
29
30 // Initialize the ORB.
31 ORB orb = ORB.init(args, orb_props);
32
33 // Obtain the root POA instance
34 POA rootpoa = POAHelper.narrow(
35 orb.resolve_initial_references("RootPOA"));
36
37 // Activate the root POA to accept incoming requests
38 rootpoa.the_POAManager().activate();
39
40 // Create the servant object
41 CalculatorImpl cal = new CalculatorImpl();
42
43 // Register the object in the root POA and obtain a
44 // reference for the object
45 org.omg.CORBA.Object ref=rootpoa.servant_to_reference(cal);
46
47 // Write the object reference into a file
48 try
49 {
50 String reference = orb.object_to_string(ref);
51 FileOutputStream file = new FileOutputStream("calculator.ior");
52 PrintStream pfile = new PrintStream(file);
53 pfile.println(reference);
54 file.close();
55 } catch (IOException ex)
56 {
57 System.out.println( "File error" );
58 }
59
60 System.out.println("Server ready and waiting for requests ...");
61 orb.run();
62 } catch (Exception e)
63 {
64 System.err.println("ERROR: " + e);
65 e.printStackTrace(System.out);
66 }
67 System.out.println("Server is shutdown ...");
68 }
69 }
7
Este cdigo es sustancialmente ms complejo e ilustra la forma en que un servidor CORBA se
despliega. Las primeras lneas del programa principal (15-22) crea un conjunto de propiedades que
le indicarn a la API Java cual es la implementacin de ORB que debe utilizar (en nuestro caso,
TIDorbJ). Posteriormente, se emplean dichas propiedades para inicializar el ORB (lnea 25). Tras
ello, emplearemos la interfaz que nos ofrece este ltimo para obtener una referencia al POA raz
(lnea 28), lo activaremos para que pueda recibir peticiones (lnea 32), crearemos nuestro servant
(lnea 35) y lo registraremos en el POA como un nuevo objeto remoto (lnea 39). A partir de este
momento, nuestro servidor puede comenzar a atender llamadas al objeto calculadora. No obstante,
para facilitar la localizacin, el servidor rescata la referencia del objeto en formato texto y la escribe
en el chero calculator.ior (42-52). Finalmente, el programa principal entra en un bucle de espera de
peticiones (lnea 55).
Ahora, para acabar con nuestro primer ejemplo de calculadora distribuida, vamos a por el clien-
te:
1 /
*
2
*
File : Client.java
3
*
Description : A calculator client
4
*
5
*
/
6
7 import java.util.Properties;
8 import java.io.
*
;
9 import org.omg.CORBA.
*
;
10
11 import mymath.
*
;
12
13 public class Client
14 {
15
16 public static void main(String args[])
17 {
18 // Create ORB properties for using TID implementation.
19 Properties orb_props = new Properties();
20 orb_props.setProperty(
21 "org.omg.CORBA.ORBClass",
22 "es.tid.TIDorbj.core.TIDORB");
23 orb_props.setProperty(
24 "org.omg.CORBA.ORBSingletonClass",
25 "es.tid.TIDorbj.core.SingletonORB");
26
27 // Initialize the ORB.
28 ORB orb = ORB.init(args, orb_props);
29
30 Calculator cal = null;
31 org.omg.CORBA.Object obj = null;
32 String calc_ior = null;
33
34 // Read the calculator IOR from a text-file
35 // previously generated by server.
36 try
37 {
38 FileInputStream file = new FileInputStream("calculator.ior");
39 BufferedReader myInput = new BufferedReader(
40 new InputStreamReader(file));
41 calc_ior = myInput.readLine();
42 } catch (IOException ex)
43 {
44 System.out.println("File error");
45 System.exit(0);
8
46 }
47
48 // Create a CORBA object from calculator IOR.
49 obj = orb.string_to_object(calc_ior);
50
51 // Cast the CORBA object to Calculator type.
52 cal = CalculatorHelper.narrow(obj);
53
54 // Use the calculator.
55 try
56 {
57 System.out.println("Adding: 5 + 3 = " + cal.add(5,3));
58 System.out.println("Multiplying: 10
*
2 = " + cal.multiply(10,2));
59 } catch (SystemException ex)
60 {
61 System.out.println("Unexpected error was ocurred.");
62 ex.printStackTrace();
63 }
64
65 // Destroy the ORB.
66 orb.destroy();
67 }
68 }
Este cdigo comienza de manera similar al del servidor, estableciendo las propiedades del ORB
a emplear e inicializndolo. Tras ello, recuperamos la cadena de texto correspondiente a la referen-
cia del objeto calculadora desde el chero calculator.ior (36-46). Apartir de esta, creamos la referencia
del tipo CORBA.Object (lnea 49), a partir de la cual haremos un casting al tipo calculadora (lnea
52). Tras eso, podemos usar la calculadora para hacer unas cuantas operaciones (55-63) y acabar
destruyendo el ORB (lnea 66).
Ahora vamos a compilar el cdigo del cliente y del servidor.
1 javac -classpath ".:$TIDORB_JAR" Client.java
2 javac -classpath ".:$TIDORB_JAR" Server.java
Tras esto, si todo ha ido bien, ejecutamos el servidor...
1 java -classpath ".:$TIDORB_JAR" Server
... y luego el cliente ...
1 java -classpath ".:$TIDORB_JAR" Client
3.3. Preguntas
Tanto en el cliente como en el servidor, hemos tenido que proporcionar una serie de propie-
dades a la clase CORBA.ORB para indicar cual es la implementacin que deseamos utilizar.
Cul crees que es el motivo? Consulta la API de Java respecto a esta clase.
Analiza la parte del cdigo del servidor en que se registra el objeto calculadora. Qu es real-
9
mente lo que estamos registrando? El objeto remoto? El servant? Ambos? Navega un poco
en la red y averigua ms mtodos para activar objetos. Si te atreves, consulta la especicacin
de CORBA, seccin 11.2.4.
Hemos visto que el cliente hace una conversin desde CORBA.Object a Calculator apo-
yndose en CalculatorHelper.narrow(). Crees que este casting podra hacerse sin em-
plear esta clase? Podramos hacer una conversin empleando los operadores bsicos de Java?
chale un ojo al cdigo de CalculatorHelper.narrow(). Crees que una operacin como
esta debera tenerse en cuenta cuando hablamos de rendimiento?
Tanto en la implementacin del cliente como en la del servidor, hemos empleado el sujo ior
para referirnos a la referencia del objeto remoto en formato texto. Sabras decir qu es el IOR?
Qu tipo de informacin contiene? Abre el chero calculator.ior generado por el servidor y
mira qu aspecto tiene. Vuelve a ejecutar el servidor y abre de nuevo el chero. Ves algn
cambio? Sabras decir qu est ocurriendo?
4. Tercera parte: referencias amigables
En el anterior ejemplo, una de las cosas que ms nos ha podido llamar la atencin es que habl-
semos de una calculadora distribuida cuando el servidor le pasa a travs de un chero el IOR de la
calculadora al cliente. Esto no es muy distribuible. Vamos a ver cmo podemos separar de una
manera sencilla ambos componentes.
Vamos a efectuar unos pocos cambios en el cdigo del servidor. En primer lugar, aadiremos
una propiedad ms a la inicializacin del ORB:
22 Properties orb_props = new Properties();
23 orb_props.setProperty(
24 "org.omg.CORBA.ORBClass",
25 "es.tid.TIDorbj.core.TIDORB");
26 orb_props.setProperty(
27 "org.omg.CORBA.ORBSingletonClass",
28 "es.tid.TIDorbj.core.SingletonORB");
29 orb_props.setProperty(
30 "es.tid.TIDorbj.iiop.orb_port",
31 "1234");
De esta manera le estaremos indicando al ORB que debe escuchar en el puerto 1234 en lugar de
escoger uno aleatoriamente.
Ahora haremos un pequeo cambio en la inicializacin del ORB, convirtiendo el objeto a la clase
org.omg.CORBA_2_5.ORB. De esta forma, accederemos a nuevas funcionalidades propias de la
versin 2.5 del estndar CORBA.
34 org.omg.CORBA_2_5.ORB orb =
35 (org.omg.CORBA_2_5.ORB) ORB.init(args, orb_props);
Finalmente, en lugar de obtener el IOR y escribirlo en un chero, vamos a registrar el objeto
como un servicio bien conocido.
51 // Register the calculator object as a initial reference
52 orb.register_initial_reference("Calculator", ref);
10
Eso es todo con el servidor. Ahora vamos con el cliente. En esta ocasin, deberemos realiza tan
solo un pequeo cambio. En lugar de leer el IOR de un chero, usaremos la siguiente referencia en
forma de string:
34 // Create a CORBA object from calculator IOR.
35 obj = orb.string_to_object(
36 "corbaloc:iiop:1.2@localhost:1234/Calculator");
Vuelve a compilar de nuevo, y ejecuta servidor y cliente. Si todo funciona, vers que el com-
portamiento de la calculadora vuelve a ser el esperado, pero... esta vez no necesitamos el chero
IOR!
4.1. Preguntas
Hemos visto que por defecto el ORB selecciona un puerto aleatorio. Crees que esto tiene algo
que ver con que los IORs cambiasen cada vez que iniciramos el servidor?
Hemos visto una nueva forma de referenciar objetos, ms comprensible para los humanos,
denominada corbaloc. Para usarla, es necesario usar una API ms moderna del ORB. Sin em-
bargo, parece que poder referenciar objetos de una manera fcil y sencilla es una cualidad
fundamental de un middleware. Por qu crees que los ingenieros de OMG decidieron que
esta funcionalidad era prescindible? Cual crees que fue la motivacin para dejarla de lado?
Crees realmente que es una buena idea que un servidor anuncie todos los objetos remotos
que exporta de esta manera?
5. Cuarta parte: usando un servidor de nombres
Hemos visto que el uso de corbalocs simplica el tratamiento de referencias a objetos remotos.
Sin embargo, este mecanismo no fue ideado para este n, sino para registrar servicios bsicos del
middleware para que estos puedan ser identicados fcilmente. Para localizar los componentes que
conforman nuestros sistemas, necesitamos otros mecanismos.
El OMG, una vez ms para garantizar la interoperabilidad entre fabricantes, estandariz un
servicio de nombrado que nos permite registrar y consultar referencias a objetos remotos. El fun-
cionamiento bsico es muy similar al del registry de Java RMI. Vamos a ver un ejemplo de cmo
trabajar con l.
En primer lugar, vamos a incluir una nueva propiedad en nuestro ORB que le permita localizar
el servidor de nombres:
29 orb_props.setProperty(
30 "es.tid.TIDorbj.naming_service",
31 "corbaloc:iiop:1.2@localhost:1234/NameService");
A continuacin, vamos a hacer una pequea modicacin a nuestro servidor. En lugar de regis-
trar nuestro objeto calculadora cun un corbaloc, vamos a codicar lo siguiente:
50 // Obtain a reference to the Naming
51 // Service (in form of naming context).
52 org.omg.CORBA.Object nc_ref =
53 orb.resolve_initial_references("NameService");
54
55 // Cast into naming context extension class.
11
56 NamingContextExt nc = NamingContextExtHelper.narrow(nc_ref);
57
58 // Register the calculator in the naming service.
59 nc.rebind(nc.to_name("Calculator.tool"), ref);
Ahora vamos con el cliente. En lugar de instanciar el objeto directamente desde un corbaloc,
vamos a ponernos en contacto con el servidor de nombres para resolver la localizacin de la calcu-
ladora.
40 // Obtain a reference to the name server.
41 NamingContextExt nc = NamingContextExtHelper.narrow(
42 orb.resolve_initial_references("NameService"));
43
44 // Locate the calculator in the name service
45 obj = nc.resolve(nc.to_name("Calculator.tool"));
Vamos a probar este escenario. Lo primero de todo, es ejecutar el servidor de nombres. Esta vez
escogeremos la implementacin de Sun Microsystems incluida en el JRE. Ejecutamos el demonio
de la siguiente manera:
1 /usr/lib/jvm/java-6-sun/bin/orbd -ORBInitialPort 1234
Ahora vamos a ejecutar el servidor. Esta vez, procuraremos emplear la mquina virtual de Sun,
empleando un ag especial.
1 /usr/lib/jvm/java-6-sun/bin/java -Xbootclasspath/p:$TIDORB_JAR Server
...haciendo lo mismo con el cliente...
1 /usr/lib/jvm/java-6-sun/bin/java -Xbootclasspath/p:$TIDORB_JAR Client
Tras esto, si todo ha ido bien, podremos observar cmo nuestro sistema funciona correctamente.
5.1. Preguntas
Como vemos, para localizar el servidor de nombres hemos tenido que proporcionar la URL
del mismo. Crees que habra alguna manera de localizar el servidor de nombres sin saberlo
de antemano? Qu soluciones se te ocurren?
En esta prctica hemos empleado un componente que se ejecuta con otra implementacin
CORBA distinta de la nuestra. Como ves, todo parece funcionar. Prueba a ejecutar el servi-
dor empleando el parmetro -classpath en lugar de -Xbootclasspath. Qu ocurre?
Sabras decir qu es lo que est pasando? Qu hace -Xbootclasspath para que todo fun-
cione? Una pista: la clase Delegate qued marcada como deprecated desde la versin 2.3 de
CORBA.
12
6. Quinta parte: sumando fracciones
En esta quinta parte, vamos a desplegar una calculadora un poco ms completa. Vamos a aadir
la funcionalidad que ya vimos en la parte de Remoting para sumar fracciones.
Lo primero, es modicar nuestro cdigo IDL para reejar estos nuevos cambios:
1 /
*
2
*
File : mymath.idl
3
*
Description : A math module which contains a calculator.
4
*
/
5
6 module mymath
7 {
8
9 struct Fraction
10 {
11 float numerator;
12 float denominator;
13 };
14
15 interface Calculator
16 {
17 float add(in float lhs, in float rhs);
18 float multiply(in float lhs, in float rhs);
19 float add_fraction(in Fraction lhs, in Fraction rhs);
20 };
21
22 };
chale un ojo al cdigo generado correspondiente a la estructura Fraction.
Ahora, cmo es lgico, deberemos implementar la nueva operacin add_fraction() en nues-
tra clase CalculatorImpl. Esta vez no te proporcionaremos el cdigo, ya que deberas saber qu
debe incluirse y dnde.
Ahora, en el cliente aadiremos un par de lneas para comprobar esta nueva funcionalidad:
56 Fraction frac1 = new Fraction(1, 3);
57 Fraction frac2 = new Fraction(4, 5);
58
59 System.out.println(
60 "Adding: 1/3 + 4/5 = " + cal.add_fraction(frac1, frac2));
Si compilas todo de nuevo y ejecutas, vers cmo es posible sumar fracciones. Ahora vamos a
hacer un pequeo cambio en nuestro cdigo. Aunque no tenga ningn sentido, vamos a tratar de
intercambiar el denominador de ambas fracciones en el cdigo del servant, de una forma parecida
a esta:
22 public float add_fraction(Fraction frac1, Fraction frac2)
23 {
24 float tmp = frac2.denominator;
25 frac2.denominator = frac1.denominator;
26 frac1.denominator = tmp;
27
13
28 return frac1.numerator / frac1.denominator +
29 frac2.numerator / frac2.denominator;
30 }
Ahora, incluiremos un pequeo trozo de cdigo para imprimir los valores de los denominado-
res despus de invocar a add_fraction().
62 System.out.println("frac1.denominator: " + frac1.denominator);
63 System.out.println("frac2.denominator: " + frac2.denominator);
Compilamos y ejecutamos de nuevo y... qu ocurre aqu? Por qu mis denominadores no pare-
cen haberse intercambiado? Cambia el chero IDL para que tome los argumentos de add_fraction()
en modo inout. Debers hacer algn cambio en el servant para que el conjunto funcione. Tras eso,
prueba de nuevo.
6.1. Preguntas
Hemos denidos una nueva entidad Fraction de tipo estructura. Como vers, no hemos
incluido ninguna operacin que nos proporcione el valor en un nmero real que representa
la fraccin. Cul crees que es el motivo? Podamos haber hecho lo mismo empleando una
interfaz? Por qu no lo hemos hecho?
Hemos tratado de modicar el estado interno de las fracciones desde el cdigo de add_fraction()
en el servant. En un principio, ese cambio no se ha propagado. Por qu? Qu est haciendo
el ORB por debajo a la hora de transmitir los parmetros? Por qu al aadir el modo inout a la
interfaz IDL se soluciona? Por qu al hacer esto hemos necesitado cambiar el tipo Fraction
por FractionHolder en el servant?
Echa un vistazo de nuevo al cdigo Java generado a partir de mymath.idl. Sabras decir dnde
se est efectuando el aplanamiento de las fracciones?
7. Comentarios nales
En esta prctica hemos visto cmo construir algunas aplicaciones sencillas que nos permiten
entender a grandes rasgos cmo funciona CORBA. Como ya hemos mencionado, CORBA es pro-
bablemente uno de los middleware ms complejos que existen. Esto despierta distintos sentimientos
en los desarrolladores. Ms complejidad signica ms dicultad en el aprendizaje y el desarrollo,
pero supone mayor exibilidad y versatilidad. Tal y como hemos podido ver, muchas funcionalida-
des que en Remoting se encuentran ocultas mediante implementaciones transparentes, CORBA
nos las proporciona de manera explcita, siendo responsabilidad del programador denir esos com-
portamientos mediante lneas de cdigo. Esto tiene sus pros y sus contras. Cul es tu opinin?
Como ejercicio nal, te proponemos que experimentes algo ms con CORBA haciendo alguno
de los siguientes ejercicios:
Hemos comentado que el POAManager regula el comportamiento en ejecucin de los objetos
desplegados en el servidor. Trata de implementar el servidor de tal forma que, en lugar de
esperar en un bucle innito, a cada golpe de teclado cambie el estado del Manager del POA
raz, pasando de activo a discarding y holding. Observa el comportamiento en el cliente cuando
esto sucede.
En Remoting hemos visto el modo de vida SingleCall. En CORBA se puede imitar una fun-
cionalidad similar deniendo un ServantManager con la poltica del POA adecuada. Trata de
desplegar un servidor que implemente este comportamiento.
14
En la pgina web de OMG puedes encontrar la especicacin del servicio de nombrado. Es
bastante simple, cuenta con un par de interfaces y apenas unas diez operaciones. Te atreve-
ras a implementarlo? Y qu me dices del servicio de eventos?
15

También podría gustarte