Está en la página 1de 138

Tesis de grado de Ingeniera en Informtica



Extensin del estndar


de  para proveer
servicios de estado persistente con acceso remoto: Anlisis, diseo e
implementacin.


      

     

Buenos Aires, Argentina. Diciembre 2007

Tesis de Grado Ingeniera en Informtica

Pablo M. Ilardi

INFORMACIN DE CONTACTO
PABLO MAXIMILIANO ILARDI: PILARDI@FI.UBA.AR O PILARDI@GMAIL.COM
MARA FELDGEN: MFELDGEN@IEEE .ORG O MARIA.FELDGEN@GMAIL.COM

Abstract

Pablo M. Ilardi

RESUMEN
Muchas de las aplicaciones distribuidas tienen requerimientos de persistencia y se encuentran
desarrolladas en lenguajes de programacin orientados a objetos (POO) tales como Java. Una de las

 
arquitecturas, CORBA de OMG, define un estndar de persistencia denominado     



  (PSS), siendo una de sus alternativas con un lenguaje PSDL. En este trabajo se analiz el estado
del arte de la persistencia, en particular en el marco de las aplicaciones CORBA desarrolladas en
lenguaje Java y la especificacin del servicio PSS. Para estas aplicaciones, se dise y construy un
servicio de estado persistente, junto con un compilador de lenguaje PSDL. Este servicio, adems de la
persistencia, permite compartir objetos persistentes entre servants ubicados en distintas mquinas o
procesos, caracterstica que no est prevista en la especificacin PSS de CORBA. El compilador y el
servicio construidos se caracterizan por ser extensibles y configurables, soportando distintas formas de
lograr persistencia. Finalmente, los resultados obtenidos fueron comparados con otros servicios PSS.
Palabras clave: Persistencia, OMG, CORBA, Servicio, POO, Java, PSS, PSDL, Compilador, Servant,
Conector, OODB

ABSTRACT
A large number of distributed applications require persistence. Many of these applications are
developed using object oriented programming languages (OOP) like Java. The OMG CORBA
   

architecture defines the      
 (PSS) as a standard for persistence. One of the options
is using a language PSDL. In this work, the state of art of persistence was analyzed specifically in the
context of CORBA applications developed in Java, altogether with the PSS specification itself. For these
applications, a persistent state service with a PSDL language compiler was designed and built. The
service includes in addition of persistence, the sharing of persistent objects with servants existing in
different machines or processes, a feature which is not provided by the PSS specification. The built
compiler and service are characterized for being extensible and configurable, supporting different ways
for persisting objects. Finally, the works results were compared to other existing PSS services.
Keywords: Persistence, OMG, CORBA, Service, POO, Java, PSS, PSDL, Compiler, Servant, Connector,
OODB

Tesis de Grado Ingeniera en Informtica

Pablo M. Ilardi

CONTENIDO
Introduccin ................................................................................................................... 9
Introduccin a POO - Programacin Orientada a Objetos ............................................ 13
Introduccin a CORBA................................................................................................... 21
Servicio de Estado Persistente CORBA - PSS ................................................................. 31
Implementacin del servicio de estado persistente CORBA - PSS................................. 47
Comparacin con otras implementaciones del servicio de estado persistente de
CORBA ........................................................................................................................ 121
Trabajos adicionales ................................................................................................... 131
ndice de Grficos ....................................................................................................... 133
Glosario ...................................................................................................................... 135

Tesis de Grado Ingeniera en Informtica

Pablo M. Ilardi

INTRODUCCIN

os juegos, sistemas de bases de datos distribuidas, multimedia, aplicaciones grficas y los sistemas
distribuidos en general, almacenan informacin que requiere persistencia. La mayora de los
sistemas de informacin, requieren de algn soporte para mantener su estado en forma
persistente. Persistencia en la programacin orientada a objetos (POO), significa almacenar los objetos y
por consiguiente el valor de sus atributos para uso futuro.
El soporte de persistencia no es trivial, ya que la representacin de un objeto en memoria puede
variar en tamao y estructura de una plataforma a otra. Adems, no est soportado en forma nativa por
todos los lenguajes de programacin (por ejemplo, C++), plataformas de desarrollo y sistemas operativos.
Por consiguiente, es necesario el uso de frameworks, como por ejemplo, CORBA, para su
implementacin.

    
CORBA (Common Object Request Broker Architecture) o 


   

[CR01] es la propuesta del OMG (Object Management Group) para la construccin de
software interoperable, portable y reusable. OMG define una arquitectura de software detallada, que
consta de interfases claramente definidas. Esta arquitectura, llamada OMA (Object Management


Architecture) [OM0], est dividida en dos modelos fundamentales. El primero, llamado 

 
  
 (
   
), permite el desarrollo de aplicaciones distribuidas basadas en un  
 
   
 u ORB (Object Request Broker). El segundo modelo, llamado 

   


(   
 ), define un marco para el desarrollo de las aplicaciones junto a un conjunto de


interfases estandarizadas llamadas 
   
 (  ) que utilizan la ORB.
Uno de los servicios que CORBA provee, tiene el objeto de facilitar y unificar la forma de hacer
persistentes a los objetos utilizados por los servants [CRO1], por medio de una interfase comn para el
manejo de persistencia. Los servants son aquellos objetos que estn bajo el control de la ORB. Todo

servant tiene una interfase definida en lenguaje IDL (Interface Definition Language o    
      
y puede ser accedido en forma remota por medio de los mecanismos que la ORB
provee a tal fin.
El servicio de CORBA que da soporte de persistencia de objetos se denomina: 
 !

  "#$%$&"'& &(&" "#)%*"


(P
S
S
) PSS [PS0]. Este servicio no intenta ser una interfase a una base de
datos orientada a objetos OODBMS (Object Oriented Database Management System), sino que provee
una forma estndar de persistencia de objetos. No incluye los dos conceptos fundamentales de OODBMS
como ser las transacciones y las consultas [BgVaDk]. Su fundamento, es la separacin de intereses
1 45 5
(+,-./.0 23 2 23 ,/3+) que est presente en la arquitectura y las especificaciones de servicios CORBA.
De esta forma, si se tienen requerimientos transaccionales no sern implementados por este servicio,
sino que este servicio se conectar o comunicar con el servicio de transacciones CORBA [TS01].
El modelo de trabajo que propone PSS, es similar al modelo general propuesto por CORBA. Los
67
5
67 5
objetos persistidos por PSS, son denominados 2 ,02+ .89. ,3.:2+ (+02/.;, 2 , 0+). Todo objeto
5<
1
1
persiste en un .89. 3 (+02/.;, =29,). Los almacenes existen en /,-2+ 02/ 2+. PSS provee un lenguaje
EA ABAF
AB B B B
para definir estos objetos y almacenes, llamado PSDL (P>?@ @ >C S D > D> C C LDCGHDG>), que es una
extensin al lenguaje IDL. Los servants que utilicen PSS, pueden hacer persistentes a los objetos de dos
formas: por su definicin en lenguaje PSDL, o por medio de objetos comunes definidos en el lenguaje de
MN M N
N
programacin que se utilice. La segunda forma de persistencia se la denomina IJKL L JOP Q KQOLIQKJO JR
En ambos casos, los objetos persistidos por los servants, son slo conocidos por el servant que los define,
y no son exportados a la ORB, lo que implica que los objetos almacenados no pueden ser accedidos en
forma remota.

Tesis de Grado Ingeniera en Informtica

Pablo M. Ilardi

Para usar el lenguaje PSDL se requiere de un compilador que traduzca las definiciones PSDL en
las definiciones del lenguaje de programacin que se utiliza. En cambio, la persistencia transparente,
permite persistir objetos directamente en el lenguaje nativo, pero a costa de perder muchas
funcionalidades que solo estn disponibles en las definiciones PSDL.
Si bien PSS es un estndar cuya ltima revisin es del ao 2002, no existen muchas
implementaciones del mismo, dado que no se trata de una de las especificaciones ms difundidas.
El problema a resolver es: Cmo hacer uso de objetos que requieran estado persistente en
CORBA? Se deben analizar las soluciones existentes, viendo que alternativas son viables de construir. Las
especificaciones son ambiguas en algunas definiciones, en las cuales se pierde la idea de interfase de
servicio CORBA. En particular, sucede cuando se trata de soportar dos modelos de persistencia, como lo
son el transparente y el de definicin por PSDL, por medio de una misma interfase de servicio.
Sin embargo, la construccin de un servicio siguiendo la especificacin PSS se plantea como una
idea atractiva y desafiante. Es atractiva, porque permite tener una interfase o modelo estndar para
solucionar este problema no trivial, lo cual es algo muy til y valioso. Es desafiante, porque se trata de un
problema complejo con muchos matices a considerar, tales como la construccin de un compilador del
lenguaje PSDL, proveer persistencia transparente sin uso de un lenguaje nuevo, definir dnde y cmo
almacenar el estado que define a los objetos utilizando una base de datos u otro medio, evaluar cmo se
podra extender el servicio para que soporte el acceso remoto de los objetos almacenados, no
contemplado en el estndar actual, etc.

OBJETIVOS
Se realiz un estudio del estado del arte de la persistencia en objetos, focalizado principalmente
en CORBA y el lenguaje de programacin Java.
Se realiz un anlisis de la especificacin del servicio de estado persistente (PSS) CORBA,
evaluando sus posibles usos, ventajas y desventajas. Se analizaron las distintas alternativas que plantea el
  

estndar, considerando los beneficios y las desventajas de la       . Se evaluaron las
diferentes estrategias a seguir frente a ambigedades en las definiciones. Se evaluaron las distintas
herramientas que pueden utilizarse para mantener el estado persistente, y su posible uso en un servicio
de persistencia.
Se dise y construy un servicio de persistencia, que soporta el estndar CORBA, utilizando el
lenguaje de programacin Java y patrones de diseo adecuados para este fin [GA0]. Se provey de un
mecanismo bsico que permite a dos o ms servants acceder en forma remota a un repositorio definido
en otra mquina, pudiendo as acceder a objetos almacenados definidos por otros servants, extendiendo
el servicio que propone el estndar. El servicio de persistencia que se construy, soporta definiciones
PSDL, junto con las funcionalidades que este lenguaje provee. Para ello, fue necesaria la construccin de
un compilador [CooperRice00] PSDL que genera cdigo Java que es compatible con el servicio construido.
Finalmente, se realiz una comparacin entre otras implementaciones del servicio de
persistencia de CORBA y la construida.

ETAPAS DEL TRABAJO


1. R EVISIN DEL MARCO TERICO
Esta etapa del trabajo se focaliz en obtener un conocimiento del marco terico necesario para
la realizacin de este trabajo. Este marco incluye CORBA, Persistencia de Objetos Java y Servicios de
CORBA.

10

Tesis de Grado Ingeniera en Informtica

Pablo M. Ilardi

2. A NLISIS
Se realiz un anlisis completo de la especificacin del servicio de estado persistente de CORBA.
Se evalu el aporte del servicio al desarrollo de aplicaciones CORBA, valorizando sus beneficios y
desventajas. Se analizaron los requerimientos para la construccin de un servicio CORBA que cumple con
este estndar y permite compartir un repositorio por ms de una ORB. Se consideraron las diferentes

herramientas, lenguajes de programacin y    que podran utilizarse en la construccin. Esta
etapa defini los requerimientos del servicio a construir.

3. D ISEO
En esta etapa se dise una solucin que cumple con los requerimientos relevados durante la
etapa de anlisis. Esta solucin incluye el diseo de un compilador de lenguaje PSDL a Java, y varios
conectores para el servicio. El diseo obtenido es lo suficientemente amplio, como para permitir futuras
extensiones al servicio en forma de nuevos conectores para distintos tipos de repositorios, tales como
archivos o bases de datos relacionales. La solucin tambin contempla el soporte para su funcionamiento
en distintas ORBs y no slo para una en particular. El diseo hace uso de distintos patrones de diseo
adecuados para resolver los problemas que se presentaron.

4. C ONSTRUCCIN
En esta etapa se construyeron los artefactos definidos en la etapa de diseo. La construccin se
realiz en forma incremental, y se proveyeron pruebas unitarias que permiten futuras extensiones al
servicio con otros conectores. Esta forma de construccin se realiz en dos iteraciones entre la etapa de
diseo y construccin, focalizando la primera en el compilador y las herramientas. Entre los artefactos
construidos se encuentran el compilador y el conector que permite compartir repositorios entre distintas
ORBs. Tambin se construyeron herramientas para la generacin de cdigo y junto con sus respectivas
pruebas unitarias.

5. E VALUACIN DEL SERVICIO


Esta etapa se evalu el servicio construido en una aplicacin CORBA. Tambin se compararon las
funcionalidades y las formas de uso de otras implementaciones de este mismo servicio. El objetivo de
esta etapa fue poner un marco de referencia de este trabajo en relacin con otros servicios.

6. R EDACCIN DEL I NFORME Y C ONCLUSIONES


Esta epata consisti en la realizacin de este informe final del trabajo. Se adjuntan tambin un
CDROM con el cdigo fuente de todas las construcciones realizadas para este trabajo, referencias en
formato digital, herramientas utilizadas, y este documento en formato digital.

11

Tesis de Grado Ingeniera en Informtica

Pablo M. Ilardi

REFERENCIAS
  

     . Third Edition June 13, 1995. Richard Mark Soley,

 
 
OM0
Ph.D. (ed.) Christopher M. Stone

      


. Meyer, Bertrand. Prentice Hall. (1997) ISBN 0-13-

BM0
629155-4.



              

      
   OMG.
CR01


http://www.omg.org/technology/documents/corba_spec_catalog.htm
PS0 Persistent State Service, V2.0 OMG 2002. http://www.omg.org/cgi-bin/doc?formal/02-09-06
GA0 Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley
Professional Computing Series - by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
January 15, 1995.
BgVaDk Java Programming with CORBA, Advanced Techniques for Building Distributed
Applications, 3rd Edition Gerald Brose, Andreas Vogel, Keith Duddy, Wiley 2001.
TS01 Transaction Service Specification, OMG 2003.
http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
EisenbergMelton01 SQL: 1999, formerly known as SQL3. Andrew Eisenberg, Sybase, Concord,
MA 01742 andrew.eisenberg@sybase.com; Jim Melton Sandy UT 84093 jim.melton@acm.org
Ramakanth01 Object-Relational Database Systems - The Road Ahead; Ramakanth S.
Devarakonda; http://www.acm.org/crossroads/xrds7-3/ordbms.html
CooperRice00 Engineering A Compiler, Keith Cooper - Rice University, Houston, Texas; Linda
Torczon - Rice University, Houston, Texas. http://www.cs.rice.edu/~keith/

12

Introduccin a POO Programacin Orientada a Objetos

Pablo M. Ilardi

INTRODUCCIN A POO - PROGRAMACIN ORIENTADA A OBJETOS


Elementos principales .............................................................................................. 15
Clase ..................................................................................................................... 15
Objeto .................................................................................................................. 15
Atributo ................................................................................................................ 15
Mtodo ................................................................................................................ 16
Mensaje................................................................................................................ 16
Caractersticas:......................................................................................................... 16
Encapsulamiento .................................................................................................. 16
Herencia ............................................................................................................... 16
Abstraccin ........................................................................................................... 16
Polimorfismo ........................................................................................................ 17
Ciclo de Vida ............................................................................................................ 17
Persistencia .............................................................................................................. 17
Java .......................................................................................................................... 18
Patrones de Diseo .................................................................................................. 18
Referencias .............................................................................................................. 20

13

14

Introduccin a POO Programacin Orientada a Objetos

Pablo M. Ilardi

a Programacin Orientada a Objetos (POO) es un paradigma de programacin, as como tambin lo


son el Estructurado y el Funcional que preceden a POO. Un paradigma de programacin es un estilo
de programacin que conlleva una cierta filosofa. Esta filosofa define una serie de premisas que
son las llamadas mejores prcticas (best practices). Existen mltiples lenguajes de programacin para un
paradigma dado. El paradigma define las herramientas que los lenguajes de programacin deben proveer
para permitir el desarrollo de aplicaciones de la forma ms natural posible [HJ0].
Si bien la POO tiene ya muchos aos no fue recin hasta los comienzos de los 90 donde se
populariz y comenz a ser utilizado como paradigma de desarrollo de software.
Muchas de las buenas prcticas en otros paradigmas son igualmente vlidas en POO, como por
ejemplo la Modularizacin.
La Modularizacin tiene como objetivo separar un sistema en mdulos, simplificando su diseo,
implementacin y entendimiento, as como tambin facilitar su evolucin y mantenimiento. El grado de
efectividad de esta tcnica depende del criterio utilizado para descomponer el sistema en mdulos [PD0].
La modularizacin est presente en POO principalmente en las clases. Para algunos autores, las clases
debieran ser los nicos mdulos existentes en un sistema [BM0]. En algunos lenguajes, tales como ADA o
Java, existe un concepto que tambin se podra asociar a los mdulos, que es el de paquete. Estos
paquetes se utilizan para agrupar clases, pero no son estrictamente necesarios en el mundo de POO.
La idea bsica en POO es resolver un problema plantendolo como un modelo del mundo real en
el que existen objetos que interactan, a diferencia del modelo de desarrollo estructurado donde se trata
de resolver el problema descomponindolo en un conjunto de funciones.
Existen mltiples lenguajes de programacin orientados a objetos, entre los que se encuentran:
Smalltalk, Object Pascal, ADA, C++, Java, Eiffel, C#, entre muchos otros.

ELEMENTOS PRINCIPALES
Todo lenguaje que se base en POO debe proveer de algunas herramientas o construcciones
bsicas como son las: clases, objetos, mtodos, mensajes y atributos.

CLASE
Una clase define o modela las caractersticas de una cosa. Las caractersticas incluyen los
atributos o propiedades junto con su comportamiento (mtodos). El tpico ejemplo es el de un Animal, el
cual tiene propiedades tales como: edad, ubicacin, forma de alimentacin, etc. su comportamiento
podra estar definido por: alimentarse, dormir, procrear, etc.

OBJETO
Un objeto es un individuo de una clase. Los individuos en POO se denominan instancias. En el
ejemplo de los animales un objeto seria un Animal concreto, por ejemplo, un animal en el zoolgico, que
tiene un estado determinado, como por ejemplo, 2 aos de vida.

ATRIBUTO
Un atributo de una clase es anlogo a una variable en la programacin estructurada, con la
diferencia del contexto donde se define. Los atributos son accesibles desde una instancia de una clase u
objeto, mientras que las variables son accesibles desde el contexto en el que se definieron. En la
programacin ms estricta todo es un objeto, o sea un entero o un string es un objeto. Los atributos son
tipados. Se puede tener un atributo de tipo Animal y otro de tipo Entero, o un atributo de tipo Objeto,
que podra referenciar tanto una instancia de un Animal como de un Entero. Los valores de los atributos
de una instancia de un objeto determinan su estado.

15

Introduccin a POO Programacin Orientada a Objetos

Pablo M. Ilardi

MTODO
Los mtodos de POO son anlogos a las funciones de programacin estructurada. La diferencia
fundamental es que las funciones o procedimientos se ejecutan en un contexto global, mientras que los
mtodos se ejecutan en el contexto del objeto en el cual se llam al mtodo. Se dice que el conjunto de
mtodos de un objeto determinan su comportamiento.

MENSAJE
Se entiende por mensaje, a la invocacin a un mtodo de un objeto. Esta invocacin se realiza
con los parmetros aceptados por el mtodo. El mensaje es el equivalente a una llamada a una funcin en
el paradigma estructurado.

CARACTERSTICAS:
La POO se basa en cuatro caractersticas: Encapsulamiento, Herencia, Abstraccin y
Polimorfismo.

ENCAPSULAMIENTO
El encapsulamiento es una forma de ocultar y agrupar informacin de forma tal de unificar el
acceso a la misma. El encapsulamiento es generalmente equiparado a ocultamiento de la informacin.
Segn [BM0]:
Debiera ser posible para el autor de una clase especificar los atributos que estarn disponibles
para todos, ninguno o algunos de los clientes de la clase.
Pero ocultar informacin, no se refiere solamente a los aspectos fsicos de la misma. Por
ejemplo, que una clase Lista utilice un array para almacenar sus elementos no debiera ser visible para un
usuario de esta clase. Los usuarios de la clase debieran acceder a los elementos de una Lista por medio
las operaciones de la misma, por ejemplo: obtenerElementoX. Esto garantiza que los clientes de las clases
se comuniquen por medio de su interfase o contrato sin depender de la implementacin de la misma.

HERENCIA
La herencia es una caracterstica que permite agrupar funcionalidades comunes en lugares
comunes, es la forma ms natural de reutilizacin en POO. Al igual que en el mundo real, la herencia
refleja que una clase hereda de otra. En POO las clases pueden heredar de otras clases sus caractersticas
y comportamiento. Por ejemplo, en la familia de los animales, algunos son de tipo carnvoro y otros de
tipo herbvoro. Una forma de herencia se podra definir como que las clases Carnvoro y Herbvoro
heredan de la clase Animal. Esto implica que ambas tiene las mismas caractersticas que cualquier animal
como la edad, peso, etc. pero adems cada una tiene sus caractersticas propias, por ejemplo, un
Carnvoro se alimenta de distinta forma que un Herbvoro.
Existen dos tipos distintos de herencia: la herencia simple y la herencia mltiple. La primera,
implica que una clase solo puede heredar a lo sumo de una nica clase, mientras que la segunda, permite
que una clase pueda heredar de ms de una clase al mismo tiempo. No todos los lenguajes de
programacin soportan el segundo tipo de herencia, por ejemplo, C++ la soporta y Java no lo hace.
La herencia incluye un nuevo concepto llamado redefinicin. Bsicamente significa que una clase
hija puede redefinir una caracterstica de la clase padre, por ejemplo un atributo o un mtodo.

ABSTRACCIN
La abstraccin permite que dos objetos sean tratados de forma uniforme sin que importe cual
clase sea. Por ejemplo, dos animales, uno Carnvoro y otro Herbvoro como un Perro y un Caballo, pueden

16

Introduccin a POO Programacin Orientada a Objetos

Pablo M. Ilardi

interpretar un mensaje como dormir. Para quien enva el mensaje dormir, es indistinto si es un Perro o un
Caballo el que lo recibe.

POLIMORFISMO
El polimorfismo es una de las caractersticas esenciales de POO y est muy asociada a la
redefinicin y a la abstraccin. Cuando un Animal recibe el mensaje alimentarse, que debe hacer,
depende bsicamente del tipo de Animal. Los Carnvoros consumirn carne y los Herbvoros vegetales.
Desde el punto de vista del cliente o usuario de una clase de tipo Animal, el mensaje enviado es el mismo,
pero los resultados son muy distintos.
La forma de conseguir un comportamiento similar en programacin estructurada, sera mediante
una condicin. Por ejemplo, se tiene la funcin alimentar(animal, alimento): dentro del cdigo fuente de
la funcin se debe preguntar si animal es carnvoro alimentar_carne() sino alimentar_vegetal(). Mientras
que en objetos slo sera necesario escribir: animal.alimentar(alimento). El polimorfismo es la propiedad
que permite que un objeto, dado un mismo mensaje responda de manera distinta en funcin del tipo de
objeto.

CICLO DE VIDA
Para utilizar una instancia de una clase es necesario tener una referencia al objeto, o construir
una instancia de la misma. Para construir una instancia de una clase, se utilizan mtodos especiales de las
clases llamados constructores. Todo constructor devuelve como resultado una instancia de la clase
donde est definido. Cuando la instancia es creada se dice que es referenciada por la variable a la que se
asign. Una vez creada la instancia de la clase, ya est lista para ser utilizada mediante sus mtodos y
atributos.
Toda instancia que est creada ocupa un espacio en memoria. La forma de liberar este espacio
depende principalmente del lenguaje de programacin utilizado. Cuando se libera esta memoria, se dice
que es el objeto se destruye.
Los primeros lenguajes de POO requeran que el usuario de los mismos se encargara de alocar y
liberar la memoria utilizada por las instancias de los objetos. Por ejemplo, en C++ es necesario llamar
explcitamente al operador delete para liberar la memoria que el objeto utiliza. Algunos lenguajes ms
modernos, liberan la memoria que utilizan los objetos de forma automtica, este es el caso de Java, o C#.

PERSISTENCIA
Muchas aplicaciones desarrolladas utilizando POO requieren mantener los objetos utilizados
entre distintas sesiones o ejecuciones de la aplicacin. Los objetos que deben ser compartidos entre
distintas sesiones se dicen que son Persistentes, mientras que los que no lo son se dice que son
Transientes. Los objetos no pueden ser mantenidos en memoria entre distintas sesiones, ya que la
memoria es liberada cada vez que se cierre la aplicacin donde se utilizan los objetos. Es necesario
almacenar los objetos en algn repositorio permanente.
Si el estado de un objeto est definido por el valor de sus atributos, se puede asumir que para
recuperar un objeto de un repositorio permanente, es suficiente con almacenar los valores de sus
atributos. Pero esto no es suficiente cuando estos atributos son otros objetos con sus propios atributos o
cuando estos atributos referencian a otros objetos que pueden referenciar al objeto inicial que se quera
presistir. Los objetos en memoria pueden constituir un grafo de dependencias complejo que puede incluir
ciclos definidos por referencias cruzadas. Un mecanismo de persitencia que pueda almacenar en forma
automtica el objeto junto con estas dependecinas cruzadas, se dice que soporta persistence closure o
persitencia cerrada [BM0].

17

Introduccin a POO Programacin Orientada a Objetos

Pablo M. Ilardi

Cuando los objetos necesitan ser compartidos entre distintas sesiones, y adems ser
compartidos entre distintas aplicaciones, se agrega la necesidad de la existencia de una bases de datos u
objetos. Las bases de datos pueden ser de tipo relacional (RDBMS) que require un mecanismo de
traduccin entre el modelo de objetos y el modelo relacional, o pueden ser sistemas de bases de datos
orientadas a objetos (OODBS) que soportan los objetos en forma nativa.
Algunos mecanismos de persitencia proveen soluciones para la evolucin del esquema [BM0]. La
evolucin del esquema se aplica cuando se modifica una clase y para dicha clases ya existen instancias de
objetos con la estructura original de la clase almacenadas en un repositorio. Cuando se recuperan dichas
intancias puede ocurrir que ya no est disponible la clase original y no sea posible recuperarla con la
nueva clase ya que no existe algn atributo de la misma. A este problema se lo denomina object
mismatch o incompatibilidad de objeto. La incompatibilidad de objetos no ocurre solamente cuando se
recupera un objeto de un repositorio donde persiste, tambin puede ocurrir cuando se transmite un
objeto por la red, y el receptor del mismo posee una versin distinta de la clase a la que pertenece el
objeto transmitido.
La persistencia de los objetos no est ligada directamente a la POO, cada lenguaje puede proveer
o no, herramientas que permitan la persistencia de los objetos utilizados.

JAVA
Java es un lenguaje de programacin orientado a objetos cuya sintaxis deriva de C y C++, pero
que provee un modelo de objetos ms simple que C++. Java fue creado por James Gosling [JavaTech01] y
por la empresa SUN en el ao 1995, como parte de una plataforma llamada Java Virtual Machine o
Mquina Virtual Java. Desde entonces ha evolucionado hasta su versin 6. La mquina virtual permite
que un programa escrito y compilado en Java pueda ejecutarse en cualquier sistema operativo y
arquitectura sin ser modificado. El sistema operativo requiere tener una implementacin de la mquina
virtual instalada. Java se compila en cdigo de bytes o bytecode, y no en cdigo binario. El bytecode es la
representacin interna que entiende la mquina virtual, y es lo que permite la independencia de
arquitectura y sistema operativo.
Una de las caractersticas principales de Java y que lo diferencian fundamentalmente de C++, es
el manejo de memoria. Java provee manejo automtico de memoria, lo que implica que el programador
no debe encargarse de pedir y liberar la memoria necesaria para la creacin y destruccin de los objetos.
Esta caracterstica se implementa por medio de automatic garbage collection o recoleccin automtica
de basura [HoskingMoss01]. Este mecanismo permite que un objeto sea eliminado cuando no existan
referencias accesibles a l desde los objetos activos. La mquina virtual es la encargada de llevar el
control de las referencias a los objetos y de administrar la memoria utilizada.
Existen algunas otras diferencias importantes con C++ [TateB01]. Java no permite herencia
mltiple de clases, aunque si permite herencia mltiple de interfases. Las interfases son definiciones de
comportamientos que pueden tener o implementar las clases, pero sin su implementacin. Son anlogas
a las clases abstractas con todos sus mtodos abstractos de C++. En Java todos los mtodos son
potencialmente polimrficos, mientras que en C++, un mtodo debe ser declarado virtual para que pueda
comportarse en forma polimrfica. Java no posee destructores ni operadores redefinibles por el
programador. En Java las clases son definidas en paquetes y un paquete puede contener mltiples clases
y sub paquetes.

PATRONES DE DISEO
El diseo de sistemas en lenguajes orientados a objetos no es una tarea simple, se deben
considerar mltiples factores que permitan reutilizacin, bajo acoplamiento y alta cohesin de las clases
que conformen el sistema.

18

Introduccin a POO Programacin Orientada a Objetos

Pablo M. Ilardi

Generalmente, el mejor diseo no se obtiene en un solo paso, sino a travs de iteraciones que lo
refinen. Cuando se plantea disear una solucin a un problema, se trata de reutilizar soluciones
anteriores buscando analogas a otros problemas similares. Muchos de los problemas que se plantean al
realizar un diseo, fueron afrontados por otros diseos anteriores de la misma u otras personas. Las
soluciones a estos problemas recurrentes siguen patrones de comunicacin y estructuras de clases
comunes.
Estos patrones son los llamados Design Patterns o Patrones de Diseo que permiten reutilizar
diseos y arquitecturas exitosas. Un patrn de diseo fue definido por Erich Gamma [GA01] como:
Un patrn de diseo nombra, motiva y explica en forma sistemtica un diseo general que
soluciona un problema recurrente en sistemas orientados a objetos. Describe el problema, da su solucin,
y define cuando es aplicable, determinando las consecuencias de la solucin. Tambin da ejemplos y
lineamientos para su implementacin. La solucin es un esquema general de objetos y clases que
solucionan el problema. La solucin se debe adaptar e implementar para resolver el problema en el
contexto particular.
Los patrones de diseo se popularizaron a partir de la tesis doctoral de Erich Gamma [GA02], que
luego fue ampliada con nuevos patrones y publicada en el libro Design Patterns: Elements of Reusable
Object-Oriented Software [GA01] o Patrones de Diseo: Elementos de Software Orientado a Objetos
Reutilizable.
Algunos de los patrones de diseo ms difundidos son: Abstract Factory, Adapter, Composite,
Decorator, Factory Method, Observer, Strategy, Template Method, etc.

19

Introduccin a POO Programacin Orientada a Objetos

Pablo M. Ilardi

REFERENCIAS
AD0 Armstrong, Deborah J. The Quarks of Object-Oriented Development. Communications of the
ACM 49 (February 2006): 123-128. ISSN 0001-0782.
BM0 Meyer, Bertrand. Object-Oriented Software Construction. Prentice Hall PTR, 1997, 2da
Edicin, ISBN 0136291554.
CO0 Software engineering: Report of a conference sponsored by the NATO Science Committee.
Peter Naur, Brian Randell (eds.) Garmisch, Germany, 711 October 1968, Brussels, Scientific Affairs
Division, NATO (1969).
HJ0 John Hunt. Samlltalk and Object Orientation: An Introduction. JayDee Technology Ltd,
Hartham Park Corsham, Wiltshire, SN13 0RP United Kingdom.
PD0 David Parnas, "On the Criteria to Be Used in Decomposing Systems Into Modules".
Communications of the ACM in December, 1972.
VRH0 Peter Van Roy, Seif Haridi, Concepts Techniques and Models of Computer Programming. The
MIT Press, Cambridge, Massachusetts. London, England 2004. ISBN 0-262-22069-5
JavaTech01

Java
Technology:
The
http://java.sun.com/features/1998/05/birthday.html

Early

Years",

by

Jon

Byous.

HoskingMoss01 Protection traps and alternatives for memory management of an object-oriented


language. Antony L. Hosking J. Eliot B. Moss. Object Systems Laboratory Department of Computer
Science
University
of
Massachusetts
Amherst,
MA
01003.
ftp://ftp.cs.purdue.edu/pub/hosking/papers/sosp93.pdf
TateB01 "Beyond Java", by Bruce A. Tate. O'Reilly, September 2005. ISBN 0-596-10094-9
GA01 Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley
Professional Computing Series - by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
January 15, 1995.
GA02 Object-Oriented Software Development based on ET++: Design Patterns, Class Library,
Tools. Erich Gamma PhD thesis, University of Zurich Institut fr Informatik, 1991.

20

Introduccin a CORBA

Pablo M. Ilardi

INTRODUCCIN A CORBA
OMG y CORBA _______________________________________________________ 23
OMA _______________________________________________________________ 23
Object Services _____________________________________________________ 23
Common Facilities __________________________________________________ 23
Domain Interfases __________________________________________________ 24
Principios de Diseo en CORBA__________________________________________ 24
Caractersticas de CORBA ______________________________________________ 24
IDL Interface Definition Language ______________________________________ 24
Pasaje de Parmetros: _______________________________________________ 25
Mapeos de lenguajes (Language Mappings) ______________________________ 25
Invocacin de Operaciones y facilidades de despacho (dispatching) ___________ 25
Object Adapters (OA) ________________________________________________ 26
Protocolo Inter-ORB _________________________________________________ 26
Un request en CORBA _________________________________________________ 27
Object References __________________________________________________ 27
Adquisicin de OR ________________________________________________ 27
Proceso para la invocacin de un request ________________________________ 27
Las caractersticas de la invocacin _____________________________________ 27
Contenedor de Componentes CORBA ____________________________________ 28
Referencias _________________________________________________________ 29

21

22

Introduccin a CORBA

Pablo M. Ilardi

n Sistema Distribuido es un conjunto de computadoras independientes que se presentan al


usuario del sistema como un nico sistema. Desde la perspectiva de hardware, las mquinas o
computadoras son autnomas, pero desde el punto de vista del software, el sistema se ve por el
usuario como un todo [Tanenbaum01].
La construccin de este tipo de sistemas plantea desafos que no se presentan en los Sistemas
Centralizados. Las computadoras que se interconectan son heterogneas y pueden tener arquitecturas
diversas. La comunicacin conlleva latencia y fallos que deben ser contemplados. Esta problemtica
impone la necesidad de un modelo de abstraccin que simplifique la construccin y diseo de los
Sistemas Distribuidos [TariBukhers01]. La especificacin CORBA de OMG provee un modelo para estos
problemas.

OMG Y CORBA
OMG (Object Management Group) o Grupo de Administracin de Objetos, es una organizacin o
consorcio internacional fundado en 1989 que trata de establecer los lineamientos y modelos para el
desarrollo de aplicaciones reusables, portables e interoperables en ambientes distribuidos heterogneos,
bajo un modelo de objetos e interfases claramente definidas. OMG ha recibido un gran apoyo de la
industria, transformndose en el consorcio de software ms grande del mundo.
CORBA (Common Object Request Broker Arquitecture) o Arquitectura Comn para el Agente de
Pedidos de Objetos [CR0] es el ncleo del modelo de arquitectura propuesto por OMG, llamado OMA.

OMA
Esta arquitectura, llamada OMA (Object Management Architecture) [OM0], est dividida en dos
modelos fundamentales. El primer modelo, llamado Modelo Central de Objetos (Core Object Model),
permite el desarrollo de aplicaciones distribuidas basadas en un Agente de Pedidos a Objetos u ORB
(Object Request Broker). Se trata de un modelo con definiciones abstractas que no poseen ninguna
implementacin y permiten interpretar el modelo de objetos e interfases. Este modelo fija las bases para
CORBA. Est enfocado en el diseo e implementacin de la ORB y no en la construccin de aplicaciones.
CORBA es una especializacin de los conceptos definidos en este modelo, llevando las definiciones
abstractas a construcciones concretas.
El segundo modelo, llamado Modelo de Referencia (Reference Model), define a la ORB junto a un
grupo de interfases estandarizadas, como el ncleo para la construccin de aplicaciones distribuidas.
Estas interfases son: los Servicios de Objetos (Object Services) [COS0], las Utilidades Comunes (Common
Facilities) [CCF0] y las Interfases de Dominio (Application Domain Interfases). El modelo de referencia es el
utilizado por los desarrolladores de aplicaciones.

OBJECT SERVICES
Los servicios de objetos (Object Services) son un conjunto de interfases de servicios y objetos que
soportan operaciones bsicas para la implementacin y utilizacin de objetos. Estos servicios permiten la
construccin de aplicaciones distribuidas independientes del dominio. Los servicios definen operaciones
genricas que se aplican a objetos de cualquier dominio, por ejemplo acceder a un objeto por algn
identificador. Existen servicios, tales como Naming Service o Trading Service, que proveen referencias a
objetos que permiten accederlos desde cualquier ubicacin. Algunos de los servicios de objetos son:
Naming Service [NS01], Persistence State Service [PSS01], Transaction Service [TSS01], etc.

COMMON FACILITIES

23

Introduccin a CORBA

Pablo M. Ilardi

Las utilidades comunes (Common Facilities), son tambin servicios u objetos, pero no esenciales
para la construccin de aplicaciones, como los servicios de objetos. Su existencia permite que diferentes
aplicaciones puedan beneficiarse compartindolos, sin tener que implementar su funcionalidad en cada
aplicacin. Un ejemplo de estas utilidades son los servicios para el manejo de correo electrnico.

DOMAIN INTERFASES
Las interfases de dominio corresponden a grupos de interfases generalizadas para dominios de
aplicacin particulares, tales como: telecomunicaciones, internet, salud, etc.

PRINCIPIOS DE DISEO EN CORBA


OMA define lineamientos que se deben respetar en el diseo de interfases de servicios de CORBA:

Separacin de la interfase de su implementacin.


Las referencias a objetos deben ser tipadas por interfases.
Los clientes slo dependen de interfases, no de implementaciones.
Las interfases permiten herencia mltiple.
Para especializar o extender funcionalidades se utilizan subtipos.
Se asume que las implementaciones de los servicios son eficientes al cumplir su cometido, de
forma tal que la eficiencia no sea un problema para los clientes.

CARACTERSTICAS DE CORBA
La ORB se puede interpretar como un canal de comunicacin que transporta pedidos y
respuestas desde y hacia objetos en cualquier ubicacin, sin importar como estn implementados. La
nocin de transparencia es fundamental en CORBA. Un objeto puede ser invocado independientemente
de su ubicacin fsica, por medio de este canal. La transparencia tambin se aplica al lenguaje de
programacin. Se pueden realizar pedidos a objetos independientemente del lenguaje en el cual estn
implementados, por medio del lenguaje de definicin de interfases o IDL que es comn a todas las
implementaciones y usuarios.

IDL INTERFACE DEFINITION LANGUAGE


Uno de los lineamientos que permite la abstraccin de CORBA, es la separacin de las interfases
de los objetos de su implementacin. Las interfases se definen en un lenguaje provisto por CORBA para
este propsito, llamado IDL (Interface Definition Language o Lenguaje de Definicin de Interfases). IDL no
permite definir la implementaciones. El hecho de que la definicin se realice en un lenguaje genrico,
permite que la especificacin sea independiente del lenguaje de implementacin de los objetos.
IDL soporta todos los tipos bsicos del lenguaje C, enumerados y relaciones entre otras
interfases. La definicin de interfases, tambin soporta herencia en el formato diamante [CR0]. Toda
interfase que no declare heredar de otra en forma explcita, hereda en forma implcita de la interfase IDL
Object. De esta forma, todos los objetos CORBA, tienen una interfase comn.
La definicin IDL, es compilada en un lenguaje especfico, como puede ser C, C++. Java, Fortran,
etc. El mecanismo de compilacin de la definicin IDL, se concreta segn la especificacin de CORBA,
denominada language mappings (o mapeos de lenguaje). El cdigo que genera el proceso de compilacin
de un segmento de cdigo en lenguaje IDL, es slo la cscara para la implementacin. Para generar un
objeto servidor o servant, un desarrollador toma esta cscara e implementa el cuerpo de las operaciones
o funciones que se hayan definido en la interfase.
Cuando se compila un archivo que tiene definiciones IDL, para el caso de C++, por lo general se
crean cuatro archivos. Un archivo contiene las interfases C++, otro contiene las operaciones de la
interfase, otro contiene la implementacin C++ del cliente (stubs), y el ltimo contiene la implementacin

24

Introduccin a CORBA

Pablo M. Ilardi

base del servidor o esqueleto (skeleton) de la misma, ya que el cuerpo de cada funcin en particular es lo
que se desarrolla a posteriori.
Cuando se comunican diferentes implementaciones de ORBs, no se pueden compartir los
archivos generados por el compilador IDL, ya que el cdigo que ste genera es propietario. No tiene
sentido hablar de compartir cdigo si se comunica una ORB que funciona con Java y otra con C++.
Mediante el uso del IDL, se puede llamar a una operacin definida en una interfase IDL, que est
implementada en un objeto programado en otro lenguaje y corriendo en otra ORB.

PASAJE DE PARMETROS:
La definicin de una operacin requiere que se especifique el modo de pasaje de sus
parmetros. Las formas permitidas son: in, out, e inout.
-

in: el argumento se pasa del cliente al servidor.


out: el argumento es devuelto al cliente, desde el servidor.
inout: el argumento es inicializado por el cliente, modificado por el servidor, y devuelto al cliente
nuevamente.

Dado que IDL, carece del concepto de punteros, tiene que existir una forma ms eficiente de
pasar por parmetro, estructuras ms complejas que un tipo de dato simple. Cuando se compila una
operacin de una interfase que recibe como parmetro a otra interfase, se pasa una referencia al objeto
que implemente este parmetro, lo que es anlogo a un puntero.

MAPEOS DE LENGUAJES (LANGUAGE MAPPINGS)


Los Lenguaje Mappings especifican como se mapean las interfases IDL a un lenguaje
determinado. Para cada construccin IDL, el mapeo del lenguaje define como se traduce a ese lenguaje.
Por ejemplo, en C++ las interfases IDL se mapean a clases, mientras que en Java [IDJ0], se mapean a
interfases pblicas.
Las referencias a objetos en C++ se mapean a una construccin que soporta el operator->,
mientras que en C, se mapean a un void *.
De igual forma, los mapeos de lenguajes especifican como utilizar las facilidades que provee la
ORB (ORB facilities), y como las aplicaciones servidoras implementan los servants.
Existen mltiples mapeos de lenguajes que permite que las aplicaciones distribuidas puedan ser
construidas en partes y utilizando mltiples lenguajes.
La independencia del lenguaje que plantea CORBA, es la clave para interconectar sistemas
heterogneos.

INVOCACIN DE OPERACIONES Y FACILIDADES DE DESPACHO (DISPATCHING)


Las aplicaciones CORBA funcionan recibiendo pedidos o request, o emitiendo request a objetos
CORBA. Los tipos de invocacin que soporta CORBA son:
-

Invocacin esttica: se realiza mediante una llamada a los stubs generados por el compilador
IDL. El servant hereda o modifica el skeleton generado por el compilador IDL.
Invocacin dinmica: este mecanismo requiere la construccin del request en tiempo de
ejecucin. Dado que no se tiene informacin en tiempo de compilacin, la creacin e
interpretacin de los requests, requiere el acceso a los servicios que permitan obtener dicha
informacin. Este servicio puede estar implementado, por ejemplo, mediante la interrogacin a
un operador que brinde la informacin necesaria, o utilizando el Interfase Repository Service,
que es un servicio que provee acceso a interfases IDL en tiempo de ejecucin.

25

Introduccin a CORBA

Pablo M. Ilardi

La invocacin esttica es comnmente utilizada por los desarrolladores cuando se implementan


aplicaciones que utilicen interfases bien definidas. Mientras que el mecanismo dinmico es utilizado,
generalmente, por dispositivos que procesen informacin que a priori es desconocida, tales como los
bridges, o gateways.

OBJECT ADAPTERS (OA)


Los OA son el nexo entre los servants y la ORB, corresponden al patrn de diseo Adapter [GA0].
Un objeto adapter adapta la interfase de un objeto a otra esperada por el emisor. De esta forma, permite
a un emisor comunicarse con un receptor sin conocer realmente cual es su interfase.
Los Object Adapters cumplen con tres requerimientos bsicos:
1- Crean Object References, que permiten a los clientes acceder a los objetos.
2- Aseguran que cada objeto a invocar o target, est encarnado o representado por un servant.
3- Toman los request que llegan a la ORB en la cual se aloja el objeto target y se los transmite
al servant que es la encarnacin del target.
Esto permite a la ORB separarse de los diferentes tipos de servants que puedan existir. De esta
forma, la nica responsabilidad relacionada con el request de la ORB es entregarlo al OA que es el que
realmente se encarga de comunicarse con el servant.
En C++ [HeVi0] un servant, es una clase que probablemente herede de un skeleton generado por
el mapeo del IDL al lenguaje. Para implementar las operaciones, se deben sobrescribir los mtodos
virtuales. En el caso de Java [BgVaDk0], se deben implementar los mtodos de la interfase que defina el
skeleton. El servant se registra con el OA, permitindole a la encarnacin de las interfases que el servant
represente, recibir los request de los clientes.
Hasta la versin 2.1 de CORBA exista una especificacin base del OA, llamada Basic Object
Adapter (BOA) solamente para C. La versin 2.2 de CORBA introdujo el Portable Object Adapter (POA),
para solucionar los inconvenientes que tenia BOA. El POA, mejor mucho la relacin entre los objetos
CORBA, y las encarnaciones servants. Como resultado de esto, la especificacin de BOA fue eliminada de
CORBA.

PROTOCOLO INTER-ORB
Antes de CORBA 2.0, una de las principales desventajas que se le criticaban a CORBA, era la
inexistencia de una especificacin de protocolo para comunicar ORBs. Por ello, cada proveedor de ORB
deba definir el protocolo de red que usaba para comunicar la ORB. Lo que daba como resultado el
aislamiento de las distintas implementaciones de ORB, ya que cada una contaba con un protocolo
propietario.
En CORBA 2.0, se introdujo una arquitectura para la interoperabilidad de distintas
implementaciones de la ORB llamada General Inter-ORB Protocol (GIOP se pronuncia gee-op). GIOP es
un protocolo abstracto que define la sintaxis para la transmisin y el conjunto de formatos de mensajes
que permite a cualquier implementacin de ORB comunicarse sobre una capa de transporte orientada a
la conexin. Internet Inter-ORB Protocol (IIOP se pronuncia eye-op) especifica como GIOP se mapea
sobre TCP/IP.
Para la interoperabilidad de las ORBs se requiere un formato estndar de Object References. Este
formato se denomina Interoperable Object Reference (IOR), y es lo suficientemente flexible como para
permite almacenar cualquier tipo de IOP. Los IOR, identifican uno o ms protocolos soportados (IOPs).
Para cada protocolo, el paquete IOR contiene la informacin propietaria del mismo. En el caso de IIOP, el

26

Introduccin a CORBA

Pablo M. Ilardi

IOR contiene el nombre del host, el puerto TCP/IP, y una clave de objeto que identifica al objeto target,
para la combinacin host - puerto.

UN REQUEST EN CORBA
OBJECT REFERENCES
Las Object References (OR), son anlogas a los punteros a objetos de C++ o las referencias de
Java.
-

Cada OR identifica una nica instancia de objeto.


Pueden existir mltiples OR que referencien al mismo objeto.
La referencia puede ser null (nil reference)
Las referencias pueden apuntar a objetos eliminados.
Son opacas, los cliente no conocen el contenido de las mismas. (deber ser tratadas como caja
negra)
Son fuertemente tipadas.
Soportan late-binding (soporta el polimorfismo de C++, a diferencia del de RPC).
Pueden ser persistentes (las referencias pueden haber sido almacenados en disco para luego ser
recuperadas nuevamente).
Pueden ser interoperables (diferentes implementaciones de ORBs, pueden intercambiar OR).

A DQUISICIN DE OR
La nica forma de acceder a un objeto CORBA es a travs de las OR. Cada servidor puede
publicar las ORs que contiene. La forma ms natural de adquirir una OR por un cliente es la de recibirla
como respuesta a una invocacin a un servicio. Otra forma es la de buscarla en un servicio como Naming
o Trading Service.

PROCESO PARA LA INVOCACIN DE UN REQUEST


Cuando un cliente invoca una operacin por medio de la OR de un objeto, la ORB hace lo
siguiente:
-

Ubica el objeto target.


Activa la aplicacin servidor, si es que esta no est activa.
Transmite los argumentos para la operacin.
Activa el servant para el request si es necesario.
Espera que se complete el request.
Devuelve todos los parmetros out, o inout, y el resultado del request.
Alternativamente devuelve una excepcin, en conjunto con los datos, cuando el request falle.

El mecanismo para el cliente es completamente transparente y lo ve como la invocacin de


cualquier otro mtodo en un objeto no controlado por la ORB.

LAS CARACTERSTICAS DE LA INVOCACIN

Transparencia de la ubicacin: El cliente no sabe si el objeto es local al proceso en el que


corre, o si se encuentra en otro proceso de la misma mquina, o si realmente se encuentra en
otro proceso de otra mquina. Los procesos servidores, no estn obligados a permanecer en la
misma mquina eternamente, pueden ser movidos de mquina en mquina sin que los clientes
sean conscientes de ello.
Transparencia del servidor: El cliente no necesita saber cual es el servidor que implementa
el objeto.
Independencia del lenguaje: Al cliente no le interesa saber en cual lenguaje est
implementado el objeto que est invocando.

27

Introduccin a CORBA
-

Pablo M. Ilardi

Independencia de la implementacin: El cliente no necesita saber como funciona la


implementacin. Incluso los objetos servidores, no necesariamente deben estar implementados
en un lenguaje orientado a objetos.
Independencia de la arquitectura: El cliente no conoce realmente el tipo de mquina en la
que est corriendo el objeto.
Independencia del sistema operativo: no se sabe realmente cual es el sistema operativo
que est corriendo el servidor.
Independencia del protocolo: El cliente no conoce el protocolo que se est utilizando para
comunicarse. La ORB, es la encargada de seleccionar, en tiempo de ejecucin, el protocolo que
utilizar para comunicarse.
Independencia del Transporte: El cliente desconoce el transporte o topologa de la red que
se utilice para la comunicacin. Se pueden utilizar distintos tipos de red sin que el cliente sea
consciente de ello.

CONTENEDOR DE COMPONENTES CORBA


La versin 3.0 de CORBA incluye un nuevo modelo de trabajo, denominado modelo de
componentes [CCM01]. Los componentes extienden el modelo de objetos de CORBA (las interfases de
IDL), y promueven la composicin en vez de la herencia.
El modelo de componentes de CORBA toma caractersticas del modelo de componentes de Java,
llamado EJB (Enterprise Java Bean), y del modelo de componentes de Microsoft llamado COM
(Component Object Model), pero a diferencia de ambos no est basado en un lenguaje particular o en un
nico entorno como Windows.
CCM o CORBA Component Model (Modelo de Componentes CORBA) promueve un modelo de
desarrollo de aplicaciones, donde se oculta parte de la complejidad de CORBA. Los componentes de
CORBA tienen acceso a los servicios estndar de CORBA, tales como el de Transacciones, Seguridad,
Persistencia o Eventos.
Todo componente se instala en un contenedor de componentes. La especificacin CCM
introduce el concepto de componente y un conjunto compuesto por interfases, tcnicas para especificar
la implementacin, empaquetado, y despliegue (deploy) o instalacin de los componentes.
Los componentes implementan al menos una interfase, pero adems permiten definir a los otros
componentes que se requieren para que un componente pueda funcionar. Un componente tambin
puede exponer atributos que permiten configurarlos en el contenedor donde sean instalados. Adems, se
define un modelo de conexin de componentes mediante eventos, que permite independencia de
interfases de los componentes conectados. Este modelo de conexin sigue el patrn de diseo Observer
[GA0].
Todas estas nuevas caractersticas son definidas mediante un nuevo lenguaje llamado CIDL
(Component Implementation Definition Language), que extiende al lenguaje PSDL [PSS01] y al IDL versin
3.0 de CORBA.

28

Introduccin a CORBA

Pablo M. Ilardi

REFERENCIAS
Tanenbaum01 Distributed Operating Systems, Andrew, S. Tanenbaum, Practice-Hall Inc 1996.
ISBN 0-13-219908-4
TariBukhers01 Fundamentals of Distributed Object Systems, the CORBA Perspective, Zahir Tari,
Omran Bukhers, Willey Inc. 2001. ISBN 0-471-35198-9
CR0 Object Management Group, Common Object Request Broker Architecture, version 3.0.3,
OMG document number formal/04-03-01. http://www.omg.org/cgi-bin/doc?ptc/04-03-01
OM0 Richard Mark Soley, Object Management Architecture Guide, June 13, 1995, Ph.D. (ed.)
Christopher M. Stone
COS0 CORBAservices: Common Object Services Specification, Updated: November 1997.
ftp://ftp.omg.org/pub/docs/formal/98-07-05.pdf
CCF0 CORBAfacilities: Common Facilities Architecture.
ftp://ftp.omg.org/pub/docs/formal/97-06-08.pdf
NS01 Object Management Group, Naming Service Specification, version 1.1. February 2001.
OMG document number formal/01-02-65.
http://www.omg.org/cgi-bin/doc?formal/01-02-65
PSS01 Object Management Group, Persistent State Service, version 2.0. September 2002. OMG
document number formal/02-09-06.
http://www.omg.org/cgi-bin/doc?formal/02-09-06
TSS01 Object Management Group, Transaction Service Specification, version 1.4. September
2003. OMG document number formal/03-09-02.
http://www.omg.org/cgi-bin/doc?formal/03-09-02
IDJ0 - Object Management Group, Java to IDL Language Mapping Specification, version 1.3.
September 2003. OMG document number formal/03-09-04. http://www.omg.org/cgibin/doc?formal/03-09-04
GA0 Erich Gamma, Design Patterns: Elements of Reusable Object-Oriented Software, AddisonWesley Professional Computing Series, Richard Helm, Ralph Johnson, John Vlissides, January 15,
1995.
BgVaDk0 Gerald Brose, Andreas Vogel, Keith Duddy, Java Programming with CORBA, Advanced
Techniques for Building Distributed Applications, 3rd Edition, Wiley 2001.
HeVi0 Michi Henning, Steve Vinoski, Advanced CORBA Programming with C++. Addison Wesley.
February 12, 1999. ISBN: 0-201-37927-9
CCM01 CORBA Component Model Specification, OMG Available Specification Version 4.0
formal/06-04-01. http://www.omg.org/cgi-bin/doc?formal/06-04-01

29

30

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

SERVICIO DE ESTADO PERSISTENTE CORBA - PSS


Conceptos Fundamentales en el Servicio ................................................................. 33
Identificacin ........................................................................................................... 35
Tipos y Herencias. .................................................................................................... 35
Claves ....................................................................................................................... 36
Uso del Servicio de Persistencia ............................................................................... 36
Acceso al Servicio de Persistencia ............................................................................ 37
Transacciones .......................................................................................................... 38
Construcciones en PSDL ........................................................................................... 38
Caractersticas de las construcciones bsicas PSDL ............................................... 39
AbstractStorageObject ...................................................................................... 39
AbstractStorageHome....................................................................................... 40
StorageObject ................................................................................................... 40
StorageHome .................................................................................................... 41
Mapeo del lenguaje PSDL a un lenguaje concreto ................................................... 41
Diferencias entre C++ y Java del servicio de persistencia ...................................... 41
Crticas a la especificacin ....................................................................................... 42
Notas finales sobre el servicio de estado persistente .............................................. 43
Alternativas a PSS en Java ....................................................................................... 43
Referencias .............................................................................................................. 45

31

32

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

n 1997 OMG cre un RFP (Request for Proposal) para la creacin de un servicio CORBA. Se trat de
un servicio de persistencia de objetos [PSS01]; Una RFP consiste en el llamado a entidades a
participar en la creacin de una nueva especificacin.

El servicio de persistencia de CORBA tiene el objeto de facilitar y unificar la forma de hacer


persistente el estado de los servants [CORBA01] y fue denominado: Servicio de Estado Persistente
(Persistent State Service) PSS.
El hacer persistente el estado del objeto significa que su estado sobrevive o se mantiene sin
importar cuantas veces el objeto sea encarnado o destruido. No debe confundirse el persistir referencias
a servants, con el hacer persistente el estado de un objeto. El hacer persistente las referencias a los
servants significa guardar en forma persistente una referencia a un servant y no el estado del mismo.
En el ao 2000, PSS reemplaz una especificacin anterior del ao 1994, denominada POS
Persistent Object Service [POS01], que fue muy poco aceptada y ampliamente criticada [KjPfTp].
Actualmente est definida la revisin 2 de PSS que data de Septiembre del 2002.
PSS no intenta ser una interfase a una base de datos orientada a objetos OODBMS, sino el de
proveer una forma estndar de hacer persistentes a los objetos. No define los conceptos fundamentales
en OODBMS como transacciones y consultas [BgVaDk]. Su fundamento es la separacin de intereses
(separation of concerns) que est presente en todas la arquitectura y especificaciones de servicios CORBA
[CORBA01]. De esta forma, si se tienen requerimientos transaccionales, stos no sern implementados
por este servicio sino que este servicio se conectar o comunicar con el servicio de transacciones CORBA
[TS01]. Una de las caractersticas que fue mas ampliamente criticada a POS fue no usar los otros servicios
que CORBA provee [KjPfTp].
PSS est basado en dos lenguajes de programacin: C++ y Java. Aunque su modelo tiene mas
similitudes con el segundo que con el primero.

CONCEPTOS FUNDAMENTALES EN EL SERVICIO


Segn la especificacin, los clientes de los servants son ajenos a este servicio y no tienen forma
de saber si se est usando el mismo. El PSS es visible solo dentro de la implementacin de los servants.
Segn muestra el Grfico 1, el cliente de la ORB que accede al servant, no accede al PSS directamente
sino que lo hace a travs del Servant.
Dominio de ORB

Servant

Interface PSS (PSDL)

Interface ORB externa (IDL)

Cliente
ORB

Dominio de PSS

Objeto del
dominio
PSS

GRFICO 1 - INTERACCIN CON LA ORB

En PSS, la informacin persistente se presenta como objetos almacenados (Storage Objects) en


almacenes (Storage Homes), que a su vez se encuentran ubicados en repositorios de datos (DataStores)
tales como una base de datos o un conjunto de archivos. Este modelo est representado en el Grfico 2.

33

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

Data Store o Repositorio de Datos


Almacen o Storage
Home

Almacen o Storage
Home

Objeto
Almacenado

Objeto
Almacenado

Objeto
Almacenado

Objeto
Almacenado

GRFICO 2 - MODELO LGICO

Dentro de un repositorio de datos pueden existir mltiples almacenes y a su vez dentro de los
almacenes pueden existir mltiples objetos almacenados. Conceptualmente, un repositorio de datos es
un conjunto de almacenes, cada almacn contiene objetos de un tipo definido dentro del repositorio.
Dentro del repositorio, un almacn es un Singleton [Gamma01], es decir que existe a lo sumo una nica
instancia de un almacn por tipo de objeto almacenado.
Los objetos almacenados se manipulan a travs de instancias de una clase definida en el lenguaje
de implementacin del programa o proceso que utilice el servicio. Estas instancias representan en un
momento dado un objeto existente en el repositorio de datos, mediante el cual se accede al estado
persistido. Las instancias de objetos que estn ligadas a un objeto en el repositorio se llaman
encarnaciones, al cambiar un atributo de una de estas instancias se est cambiando el estado del objeto
almacenado en el repositorio.
Los almacenes de objetos tambin son manipulados mediante instancias de los mismos. Estas
instancias son provistas por catlogos. Para acceder a las instancias de los objetos almacenados desde del
proceso o programa se requiere de una conexin con el repositorio de datos, denominada sesin. El
Grfico 3 define la relacin entre el modelo lgico y el modelo real de la aplicacin.

Programa o Proceso

Data Store o Repositorio de Datos

Catlogo

Almacenes o
Storage Homes

Instancia de
Almacen
Encarnaciones

Objetos
Almacenados
Instancia de
Almacen

sesin

Objetos
Almacenados

Encarnaciones

GRFICO 3 - SESIN PARA ACCEDER AL DATASTORE

Muchos de los conceptos existentes en PSS, fueron tomados del estndar SQL3 o SQL 1999
[EisenbergMelton01]. SQL3 fue una extensin propuesta al estndar SQL en el ao 1999, que agrega
conceptos de los lenguajes de programacin orientados a objetos. Las bases de datos que lo soportan son
llamadas Object-Relational DBMS u ORDBMS [Ramakanth01]. Las tablas en SQL3 permiten tipos de datos

34

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

ms ricos llamados ADT (Abstract Data Type) que soportan herencia. Los almacenes de PSS son el
anlogo a las tablas de SQL3, mientras que los objetos almacenados son los registros o tipos de datos de
SQL3.
Todos los objetos definidos por el servicio de persistencia implementan la interfase
LocalInterface [CORBA01]. Segn la especificacin de CORBA, todos los objetos que implementen dicha
interfase tienen su ciclo de vida limitado al proceso en el que fueron engendrados. De esta forma, es
imposible para un servant exportar un objeto definido en el dominio del servicio de persistencia. Esta es
otra forma de encapsular el servicio de persistencia slo dentro de la implementacin de los servants.

IDENTIFICACIN
Dado que existen mltiples instancias de objetos dentro de un repositorio y de un almacn, es
necesaria una forma de diferenciarlos.
Cada objeto almacenado posee un nmero nico que lo identifica dentro del almacn al que
pertenece denominado short-pid (Short Process Identifier o Identificador corto de Proceso). Adems
posee un identificador nico dentro del repositorio en el que existe, que es denominado pid (Process
Identifier o Identificador de Proceso). El alcance de este pid est limitado a todas las instancias que
pueden ser accedidas por el mismo catlogo.
El concepto de pid es anlogo al de oid dentro de CORBA. Una forma simple de relacionar un
objeto CORBA con un objeto del servicio de persistencia (un objeto persistente) es directamente por sus
identificadores (oid igual al pid).

TIPOS Y HERENCIAS.
Los tipos estn separados en dos grandes categoras abstractos y concretos, los primeros
implican definiciones que no pueden ser instanciadas, las segundas son las construcciones que sern
instanciadas en el programa que utilice el servicio.
custom Herencia Diamante

i nterface

interface

A'

i nterface

interface

i nterface

interface

i nterface

B'

E'

C'

i nterface

interface

D'

GRFICO 4 - HERENCIA DIAMANTE DE INTERFASES EN CORBA

Este modelo es muy similar al modelo de herencia del lenguaje de programacin Java, los tipos
abstractos son anlogos a las interfases de Java, mientras que los concretos son anlogos a las clases. Al
igual que las interfases, los tipos abstractos admiten herencia mltiple, mientras que los concretos solo
pueden heredar a lo sumo de un nico tipo concreto. De igual forma que las clases, los tipos concretos
pueden implementar mltiples interfases. La herencia mltiple incluye el modelo de herencia diamante.

35

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

La herencia diamante (grfico 4) est definida en la especificacin de CORBA [CORBA01], se


utiliza principalmente para la definicin de interfases.
almacena

AlmacenTipoA

Hereda
AlmacenTipoB

TipoA

Hereda

Hereda

almacena

TipoB

AlmacenTipoC

Hereda

TipoC

almacena

Implementa
Implementa
Implementa
AlmacenConcreto

Implementa
almacena

TipoConreto

GRFICO 5 - TIPOS Y MODELO DE HERENCIA EN PSS

Tanto los objetos almacenados como los almacenes son tipados con tipos abstractos o concretos,
segn si son abstractos o concretos respectivamente.
Cada objeto almacenado tiene un tipo asociado, este tipo define el estado y las operaciones que
poseen todas las instancias de este tipo. A su vez un tipo puede ser derivado de otros tipos definidos en el
repositorio.
Cada almacn a su vez est definido por un tipo, el cual define los tipos de objetos que el
almacn puede contener o manejar junto con las operaciones que pueda realizar. De igual forma que los
tipos de objetos, los tipos de almacenes tambin pueden derivar de otros tipos de almacenes definidos
dentro del repositorio.
Dentro de un repositorio, un almacn puede manejar tanto las instancias de sus objetos
almacenados como las de sus subtipos, que se denomina familia de almacenes.
En el grfico 5 se muestra la herencia de tipo diamante soportada por el servicio de persistencia
CORBA.

CLAVES
Un almacn puede definir que una serie de atributos de los objetos que maneja, definen una
clave que representa un identificador nico para cualquier instancia de los objetos existentes en el
almacn. Los almacenes pueden definir tantas claves como deseen. Hay una clave implcita que es el
short-pid. Un concepto muy importante, es que las claves no estn definidas por los objetos
almacenados, sino por el almacn donde se encuentran. Esto permite que diferentes almacenes definan
diferentes claves. Una implicacin importante es que la unicidad de los objetos slo es vlida dentro del
almacn en el que existen.

USO DEL SERVICIO DE PERSISTENCIA


Para hacer uso del servicio de persistencia, se requiere que el usuario defina los tipos que usar
en un programa, la especificacin propone dos formas para definir los tipos de objetos.
-

Mediante el lenguaje de definicin llamado PSDL (Persistent State Definition Language); o

36

Servicio de Estado Persistente CORBA (PSS)


-

Pablo M. Ilardi

mediante el uso del lenguaje programacin en el que se quiera acceder al servicio.

PSDL es una ampliacin al IDL estndar de CORBA, que agrega cuatro construcciones: abstract
storage object, abstract storage home, storage object y storage home. En el caso de utilizar la primera
forma de definir los tipos, la implementacin del servicio deber proveer una herramienta o compilador
que transforme el cdigo definido en PSDL al cdigo fuente que utilice el servicio.
En el caso de utilizar la segunda, tambin llamada persistencia transparente, el usuario ser
responsable de programar las clases que usar el servicio de persistencia.
Ambas alternativas son igualmente vlidas, la segunda no requiere que el usuario entienda el
lenguaje PSDL. Tiene algunas limitaciones ya que no hay un estndar para cada lenguaje, que defina cmo
hacer uso de algunas de las funcionalidades que provee el servicio, tales como definir claves adicionales a
las implcitas. Este problema surge porque el servicio requiere que el usuario sea quien defina y provea
los tipos y no alcanza con solo llamar a una rutina del servicio. A cualquier usuario acostumbrado a
trabajar con CORBA le es natural utilizar el lenguaje IDL y por consiguiente le debiera ser relativamente
sencillo aprender a utilizar PSDL.
Segn la especificacin del servicio, las aplicaciones que utilicen el servicio de persistencia solo
deberan tratar con los tipos abstractos, de esta forma se puede lograr una aplicacin aislada o separada
de la implementacin del servicio. Por otro lado, los tipos concretos son mapeados a construcciones
definidas en el lenguaje de implementacin del servicio (Java o C++). Algunas de estas construcciones
estn definidas en el mapeo de PSDL al lenguaje concreto, pero otras no, y en este punto es donde se
pierde la independencia de la implementacin del servicio de persistencia.

ACCESO AL SERVICIO DE P ERSISTENCIA


La puerta de entrada al servicio es el ConnectorRegistry (o registro de conectores). Este objeto es
un Singleton registrado en la ORB como una referencia inicial [CORBA01]. El nombre de la referencia
depende de la implementacin del servicio, pero generalmente es PSS. Como su nombre lo indica, el
ConnectorRegistry tiene un registro de los conectores que tiene registrados el servicio de persistencia.

ConectorRegistry

Tiene
registrados

Refencia inicial

Connector

Provee

ORB

CatalogBase

Session

SessionPool

TransactionalSession

GRFICO 6 - ACCESO AL SERVICIO

El conector (Connector) determina el tipo de servicio de persistencia que se usar. Se dice que el
conector define la implementacin del servicio de persistencia a utilizar. Un conector tpico podra ser uno
que se conecte a una base de datos relacional o uno que utilice un sistema de archivos para almacenar el
estado de los objetos. Los conectores son responsables de crear los catlogos (CatalogBase) que se

37

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

usarn para trabajar con el servicio de persistencia. El tipo de catlogo que se cree, ser dependiente del
conector y el mtodo que se utilice para crearlo.
La sesin, o sea la conexin lgica entre el o los repositorios y el proceso, tiene credenciales de
uso, como por ejemplo, solo lectura o lectura-escritura. Las sesiones pueden a su vez ser de tipo
transaccional (TransactionalSession) mediante el uso del servicio de transacciones CORBA, o sesiones
donde la atomicidad de las operaciones dependa del conector utilizado, por ejemplo, con acceso de tipo
archivo (Session), donde cada operacin se hace inmediatamente persistente.
El acceso a las sesiones puede ser en forma explcita o implcita. Cuando se trabaja con sesiones
implcitas (ya sean transaccionales o no) el usuario del servicio de persistencia es el encargado de
crearlas, escribiendo cdigo en el lenguaje utilizado. Cuando se maneja en forma implcita, un pool de
sesiones es el encargado de administrarlas (SessionPool). Un pool de sesiones tiene el objeto de permitir
la reutilizacin de las conexiones o sesiones a un repositorio, ya sea dentro de la misma aplicacin o no.
Por lo general, su existencia tiene dos justificaciones: la creacin de una sesin puede ser costosa en
trminos de recursos involucrados para crearla, y cmo y dnde conectarse puede ser centralizado en un
slo punto, permitindole a la aplicacin desentenderse de ello.
El servicio de persistencia puede ser utilizado tambin mediante un contenedor de componentes
CORBA [CCM01, CCM02], tanto en forma explcita como implcita.

TRANSACCIONES
Las transacciones en el servicio de persistencia estn presentes a travs del servicio de
transacciones CORBA [TS01]. Esto implica que los objetos almacenados pueden ser accedidos en el
contexto de una transaccin. Para interactuar con el servicio de transacciones es necesario registrar en l
los recursos que sern utilizados en la transaccin.
En el caso de que se trate de sesiones explcitas, las instancias de los objetos almacenados estn
relacionadas con una transaccin por medio de una sesin transaccional. Esta sesin est asociada a una
transaccin de datos (datastore transaction), que es el recurso que se registra con el servicio de
transacciones. En el modo de trabajo explcito, la sesin transaccional provee operaciones explcitas para
interactuar directamente con el servicio de transacciones.
El escenario anterior no es el ms tpico, por lo general, cuando se trabaja con transacciones se
utiliza un proveedor de las mismas, y es el pool de sesiones el que se comunica con este servicio. En el
caso de utilizar el pool (sesiones implcitas), ste es el encargado de verificar cuando es necesario iniciar
una transaccin y no se tiene control programado del manejo de transacciones.

CONSTRUCCIONES EN PSDL
PSDL define el mdulo CosPersistentState, que contiene todas las construcciones propias del
lenguaje. Las principales son:
CatalogBase, Connector, Session, SessionPool, TransactionalSession, AccessMode,
ParameterList, StorageHomeBase, StorageObjectBase, StorageObjectFactory, StorageHomeFactory,
SessionFactory, NotFound, TypeId, Pid, ShortPid, ConnectorRegistry.
A continuacin, voy a hacer una breve descripcin de las construcciones que agrega PSDL a IDL
no definidas hasta este punto.

38

Servicio de Estado Persistente CORBA (PSS)


-

Pablo M. Ilardi

AccessMode define el modo de acceso que tendr garantizado el usuario del servicio sobre una
sesin al momento de crearla, mediante el uso de un conector. Puede ser solo lectura, o lectura
escritura.
ParameterList es simplemente una lista de parmetros variables que le permiten al conector
recibir parmetros propios de la implementacin del mismo para crear una sesin. Por ejemplo,
un conector podra requerir un nombre de usuario y clave para conectarse a un repositorio, si el
repositorio es de tipo remoto, podra ser necesario indicarle la ubicacin del mismo en la red.
NotFound es una excepcin utilizada para indicar que un objeto que se quiere localizar no existe
o no est disponible. Es utilizada tanto por el registro de conectores para indicar que un conector
no existe, como por una sesin cuando se quiere ubicar un objeto por su pid.
TypeId es una cadena de caracteres que identifica un tipo PSDL. El formato de la misma es
similar a los ids de los repositorios IDL [CORBA01 ver seccin 10.7.1], pero en vez de comenzar
con IDL lo hacen con PSDL. Al igual que los ids de repositorios, estos ids incluyen el nmero de
versin al que corresponden. Estos ids son utilizados por los conectores para registrar las
fbricas de objetos de un tipo PSDL. Por ejemplo, para un tipo persistido:
ar.uba.fi.pmi.corba.pss.prueba1.Persona, en su primer versin podra tener asociado un tipo
persistido: PSDL:ar.uba.fi.pmi.corba.pss.prueba1.Persona:1.0. Esta cadena de caracteres ser
utilizada por el usuario final para registrar la clase Persona en el conector donde quiera utilizarla.

CARACTERSTICAS DE LAS CONSTRUCCIONES BSICAS PSDL


En este punto se definen las caractersticas principales de las definiciones PSDL. La sintaxis de las
mismas se podr consultar en la especificacin del servicio [PSS01].

A BSTRACT S TORAGE O BJECT


La sintaxis para definir un objeto de este tipo es prcticamente la misma que para una interfase
IDL, salvo que esta no puede contener constantes ni definiciones de subtipos. Un objeto almacenado
abstracto puede heredar de mltiples objetos almacenados abstractos, pero slo puede ser definido
como supertipo directo una nica vez en la misma definicin. No se permite heredar de tipos que
contengan estados u operaciones con el mismo nombre, salvo para el caso de la herencia diamante
explicada anteriormente. Se permiten definiciones hacia adelante (forward), pero las mismas tienen que
estar completas dentro de la misma especificacin PSDL (dentro del mismo documento).
Estas definiciones pueden contener definiciones de estados que representan a los atributos
persistentes de los objetos almacenados. Los estados pueden ser definidos como lectura escritura o
slo lectura (explcitamente). Los estados son tipados y los tipos vlidos son: un tipo bsico (nmero o
carcter), una cadena de caracteres, una referencia a un tipo persistido abstracto, u otra definicin local
(interfase u objeto almacenado).
Cuando el estado tiene definido un tipo que sea otro tipo persistido, se dice que el objeto est
empotrado (embedded) en el otro. Este objeto que representa el estado, no posee identidad propia y no
puede ser referenciado fuera del contexto del objeto que lo contiene.
Cuando el tipo del estado es una referencia a otro objeto almacenado mediante el uso de la
palabra strong (fuerte), se puede indicar que cuando el objeto almacenado que lo referencia sea
destruido tambin lo sea el referenciado.
La definicin puede contener operaciones locales (local operations), que podrn utilizar
parmetros de entrada, salida o entrada - salida tal como cualquier operacin IDL. Adems, podrn
utilizar como parmetros, cualquier definicin IDL vlida o algn objeto almacenado abstracto definido
previamente. Las operaciones pueden ser definidas adems como constantes, en cuyo caso no se les
estar permitido modificar el estado del objeto al que pertenecen. Se les denomina operaciones locales
dado que los objetos almacenados definen interfases locales en CORBA.

39

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

Toda definicin de objeto almacenado abstracto que no herede de otra definicin


explcitamente, heredar implcitamente del objeto almacenado abstracto StorageObject definido en el
mdulo CosPersistentState.

A BSTRACT S TORAGE H OME


La definicin de un almacn de objetos almacenados debe especificar que tipo de objeto
almacenado abstracto es el que puede contener (un nico tipo). Al igual que los objetos almacenados
abstractos, se admiten definiciones hacia delante, que deben ser completadas en el mismo documento.
Los almacenes abstractos pueden heredar de mltiples almacenes abstractos, con la nica
condicin de que los tipos de objeto persistidos manejados por los almacenes heredados, deben ser un
supertipo o el mismo que el manejado por el almacn. Tampoco se permite redefinir operaciones con el
mismo nombre, salvo para el caso de la herencia diamante, que tambin es soportada por los almacenes
abstractos.
Los almacenes abstractos pueden definir claves (keys), que son simplemente una lista de
nombres de estados (al menos uno), que estn identificados por un nombre. Una clave determina que
para el almacn donde est definida, slo puede existir un nico objeto almacenado con los mismos
valores de los estados definidos en ella. Los estados que conforman la clave no debern estar repetidos y
los tipos de los mismos debern ser comparables (tipos nativos, cadenas de caracteres, o estructuras de
tipos comparables).
La definicin de una clave implica la definicin implcita de dos operaciones locales en el
almacn, que permitirn ubicar un objeto almacenado dentro del mismo. Estas operaciones sern
find_by_nombreclave, y find_ref_by_nombreclave, ambas tomarn como parmetro los valores de los
estados que conformen la clave, pero la primera devolver el objeto almacenado, mientras que la
segunda, una referencia al objeto. Si dicho objeto no existe, se lanza una excepcin NotFound en el
primer caso y se devolver NULL en el segundo.
Adems, se permite una definicin extendida de operacin, llamada factory method (operacin
de fbrica) [Gamma01], que permite construir un objeto almacenado en el almacn. Los parmetros
sern una lista de estados presentes en el objeto almacenado (por lo menos uno).
Factory Method es un patrn de diseo que permite encapsular la construccin de un objeto. El
tipo o clase ser definido por el objeto que implemente dicho factory method en funcin de su estado
interno y de los parmetros de dicho mtodo. En el contexto de un almacn de objetos, segn la
configuracin del servicio de persistencia, se definir la clase que implementa el objeto almacenado. De
esta forma, el usuario del servicio de persistencia puede tratar siempre con las interfases de los objetos,
sin necesidad de conocer las implementaciones de los mismos, que por lo general, se encuentran ligadas
a la implementacin del servicio de persistencia.
Al igual que los objetos almacenados abstractos, los almacenes abstractos tambin admiten la
definicin de operaciones locales.

S TORAGE O BJECT
Se permite la herencia de a lo sumo un objeto almacenado por definicin, mientras que es
posible implementar mltiples definiciones de objetos almacenados abstractos. Se dice que el objeto
almacenado implementa directamente una definicin de un objeto almacenado abstracto cuando se
define en forma explcita que lo implementa. Tambin puede implementarlo en forma indirecta, si
hereda de otro objeto almacenado que implemente la definicin abstracta. Esta definicin es importante,

40

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

ya que existen mltiples restricciones que se aplican cuando se implementa en forma directa otra
definicin.
Por ejemplo, cuando un objeto almacenado implemente directamente un objeto almacenado
abstracto, que defina un estado que sea otro objeto almacenado abstracto o una referencia, la definicin,
deber declarar una directiva de almacenamiento (store directive) al compilador. Esta directiva indica
cual es el objeto almacenado concreto que ser referenciado o utilizado en dicho estado, y
adicionalmente, si se trata de una referencia, cual ser el almacn concreto donde se albergar a dicho
objeto almacenado. Esto le permite al compilador, por ejemplo, optimizar el espacio requerido para
almacenar el objeto conociendo de antemano de que tipo de objeto se trata.
Toda definicin de objeto almacenado que sea la primera en la jerarqua, podr indicarle al
compilador los estados que definen una referencia a un objeto almacenado de este tipo. Esta lista de
estados, adems constituir una clave nica dentro del almacn de objetos almacenados que contenga
objetos de este tipo.

S TORAGE H OME
La definicin de un objeto almacenado requiere indicar que tipo de objeto almacenado concreto
ser el que manejar este almacn. El almacn puede heredar de a lo sumo un almacn y el tipo
almacenado de dicho almacn deber ser un supertipo del tipo almacenado definido por el almacn.
Adems, dos almacenes dentro de la misma jerarqua no podrn tener definido el mismo tipo de objeto
almacenado.
El almacn puede implementar mltiples almacenes abstractos, siempre y cuando los tipos
almacenados de los almacenes abstractos sean implementados por el objeto almacenado definido por el
almacn.
Al igual que los objetos almacenados, para los almacenes tambin se define el concepto de
implementar en forma directa. Se dice que un almacn implementa en forma directa una definicin del
almacn abstracto, cuando el almacn sea el primero dentro de la jerarqua que lo implemente.
Tambin, se dice que un almacn implementa directamente un objeto almacenado abstracto
cuando ste sea el primero en su jerarqua en implementar dicha definicin. Y en base a esto, el almacn
implementar en forma directa un estado, cuando implemente en forma directa el objeto almacenado
abstracto donde dicho estado est definido.
Estas definiciones se aplican en restricciones a la jerarqua del almacn. Cada clave definida en
un almacn abstracto, que sea implementado directamente por un almacn, deber tener como mnimo
un estado implementado directamente por el almacn. Esto evita que existan almacenes que definan
claves nicas sin contener estados definidos en l. Es como si en una base de datos relacional, una tabla
definiera una clave nica que no tenga columnas de dicha tabla, sino todas columnas de una tabla con la
que se tiene una clave fornea (foreign key).
Todo almacn, que sea el primero dentro de la jerarqua, puede definir una de sus claves o la
representacin de la referencia del tipo de objeto que almacena, como la clave primaria.

MAPEO DEL LENGUAJE PSDL A UN LENGUAJE CONCRETO


El servicio de persistencia define el mapeo de las entidades definidas en PSDL al lenguaje que
implemente el servicio. Algunos son de tipo nativo, o sea que su valor depende puramente del lenguaje
que se utilice.

DIFERENCIAS ENTRE C++ Y JAVA DEL SERVICIO DE PERSISTENCIA

41

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

El mapeo de PSDL a C++ requiere agregar estructuras que en Java ya se encuentran presentes.
Algunos de los mapeos de tipo nativo a Java se traducen en clases ya existentes en el lenguaje, mientras
que en C++, son construcciones nuevas. Por ejemplo, en Java, toda clase hereda implcitamente de la
clase Object, mientras que en C++ no existe una clase base a todas las clases, por lo que se requiere
agregar la construccin CosPersistentState::StorageObject. Otro ejemplo, es el de las fbricas (factories),
para instanciar o crear objetos de los tipos definidos por los usuarios (mapeo nativo): en Java se traduce
directamente en un objeto de tipo Class, mientras que en C++ se traduce a una clase Factory definida por
el servicio de persistencia, que deber crear objetos en forma programtica. Esta es una de las diferencias
de mapeo del servicio a los lenguajes de programacin, donde se muestra que el servicio se adapta ms
naturalmente al lenguaje Java. Dado que Java es un lenguaje ms moderno que C++, provee de
herramientas que hacen ms simple los programas escritos en este lenguaje.
Otro tem importante, es el manejo automtico de la memoria. En Java, el ciclo de vida es
manejado automticamente por la mquina virtual, mientras que en C++, el programador es el encargado
de reservar y liberar la memoria requerida por los objetos. El servicio de persistencia provee mtodos
para liberar referencias a objetos accedidos en una sesin y que ya no son utilizados. En C++ se requiere
de esta operacin, ya que es el programador el encargado de liberar la memoria que ha alocado, en Java
sta operatoria es automtica.

CRTICAS A LA ESPECIFICACIN
El servicio de persistencia define un tipo persistido llamado StorageObject, que tiene una serie
de mtodos, tales como get_pid() o get_short_pid(), entre otros. Segn la especificacin (seccin 3,
pgina 8[PSS01]), toda definicin de un objeto persistido abstracto que no herede explcitamente de otro,
hereda de la clase StorageObject. Sin embargo, de acuerdo a la especificacin, todos los objetos
almacenados concretos heredan implcitamente de la clase StorageObjectBase. En Java, esta clase est
representada por la clase java.lang.Object, mientras que en C++, al no existir una clase base de todos los
objetos, se define una nueva clase CosPersistentState::StorageObjectBase. Ninguna de estas dos clases
(tanto en Java como en C++) definen los mtodos que tiene definidos la clase abstracta StorageObject.
Dado que no es obligatorio que la definicin de un objeto almacenado concreto, implemente
alguna definicin de un objeto almacenado abstracto, lo expresado en el prrafo anterior sobre
StorageObject y StorageObjectBase, no constituye una contradiccin.
Esto implica que no est definido que ocurre cuando un objeto almacenado concreto
implementa alguna definicin abstracta. Qu pasa con las operaciones definidas en StorageObject?
Queda completamente libre y depende puramente de la implementacin del servicio de persistencia.
Tampoco est claro, por qu es necesaria la existencia de la definicin de StorageObject, ya que todas las
operaciones del servicio de persistencia estn basadas en la clase StorageObjectBase.
La existencia de StorageObject, hace que los usuarios del servicio de persistencia estn obligados
a atarse a una implementacin del servicio, si es que quieren utilizar las definiciones abstractas. Esto
contradice uno de los principales objetivos de PSDL, que es el de liberar al usuario final del servicio de
usar una implementacin particular del mismo.
Gran parte de las inconsistencias surgen de tratar de dar soporte de persistencia transparente y
por PSDL, en forma simultnea. Si bien la idea de la persistencia transparente es potencialmente muy
atractiva, al tener que coexistir con el mundo de PSDL, crea un modelo hbrido difcil de compatibilizar.
Las excepciones, cdigos de error, o condiciones de error no estn especificadas en todos los
casos, cada implementacin es libre de generar los tipos de error que considere apropiados. Por ejemplo,

42

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

qu sucede cuando se trata de registrar una clase como factory de un tipo de objeto almacenado que no
es compatible con la implementacin del servicio o conector?
Otro tipo de errores que tambin son muy importantes, son los relacionados con la integridad
referencial y el ciclo de vida de los objetos. Qu pasa cuando se trata de eliminar un objeto que esta
referenciado en otro como un estado del mismo?. Qu pasa si se quiere asignar un objeto empotrado
como un atributo de otro objeto almacenado? De acuerdo con la especificacin, los estados no pueden
ser compartidos. Esto implica que cuando se asignan objetos empotrados a otros objetos, se debera
realizar una copia implcita de dicho objeto, el modo e implicancia de la copia no se encuentra definido,
por lo que cada implementacin puede tener formas distintas de realizarlo.
Existe tambin una indefinicin en cuando a los tipos de datos que soportan los estados. Un
estado puede ser de una interfase o estructura IDL definida dentro del archivo PSDL compilado. Como se
almacena dicha interfase o estructura no se encuentra definido en la especificacin.
Otro punto problemtico, son los mapeos de los estados al lenguaje Java. En Java existe una
convencin que la definicin de los mtodos que permiten acceder a los atributos que definen el estado
de los objetos. Si un atributo se llama nombre, el mtodo para acceder al nombre, se debe llamar
getNombre(), y el mtodo para modificarlo debe llamarse setNombre(nombre). En el mapeo de PSLD a
Java, se define que un estado se lee por un mtodo generado por el compilador, que para el caso de un
estado llamado nombre, ser nombre(), y para modificarlo el mtodo deber llamarse nombre(nombre).
Esta diferencia entre Java estndar, y el mapeo de PSDL, puede traer problemas al integrar los objetos
generados por el compilador con otras herramientas que esperen mtodos estndar.
La especificacin es amplia en muchos sentidos, dejando puntos libres que pueden ser resueltos
de diferentes formas en distintas implementaciones del servicio. Este tipo de situaciones, hacen ms
complicada la portabilidad entre distintas implementaciones del servicio, y van en contra del objetivo
inicial de lograr una interfase comn con la que se pueda lograr independencia de la implementacin del
servicio.

NOTAS FINALES SOBRE EL SERVICIO DE ESTADO PERSISTENTE


La especificacin de PSS est definida solamente para dos lenguajes de programacin: C++ y
Java, por lo que el campo de trabajo est limitado a estos dos lenguajes y no a mltiples lenguajes como
se promueve a CORBA.
Algunos conceptos que promueve PSS, tales como los identificadores globales de objetos y los
almacenes, no pertenecen a POO, esto se debe a que el modelo est basado en SQL3 y no en el modelo
de Objetos. Para una persona que no conoce SQL3, estos conceptos resultarn desconocidos e
incrementarn la complejidad de uso del servicio. PSS tampoco respeta algunas de las buenas prcticas
reconocidas en Java, tal como la forma de acceder a los atributos de los objetos. Estas caractersticas que
hace que el modelo de PSS se aleje del modelo de objetos incrementan la complejidad de uso del
servicio.
El servicio de estado persistente de CORBA es una solucin parcial para obtener soporte de
persistencia de objetos, tiene sus limitaciones y no es necesariamente la opcin ms simple de utilizar,
pero sin embargo dentro del mundo CORBA, es una estndar lo cual le aporta un gran valor, y para el
objetivo de obtener estado persistente dentro de un servant es completo y funcional.

ALTERNATIVAS A PSS EN JAVA


Al utilizar el lenguaje de programacin Java existen varias alternativas para obtener persistencia
de los objetos, algunas de ellas sern analizadas en la siguiente seccin. Entre las alternativas se

43

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

encuentran Hibernate [KingG01], JDO [RoodsR01], entre otras. Estas dos herramientas forman parte de
un gran grupo herramientas similares que permiten persistir objetos en una base de datos Relacional,
llamadas genricamente ORM (Object Relation Mapping o Mapeo objeto - relacin). Este tipo de
herramientas no estn directamente relacionadas con CORBA, por lo que su integracin con CORBA
requiere de trabajo especfico del programador sobre la aplicacin. Por ejemplo, la integracin con el
servicio de transacciones de CORBA deber ser programada directamente.
Existe otra alternativa en Java denominada J2EE (Java2 Enterprise Edition o edicin empresarial
de Java2). J2EE es una especificacin de SUN que extiende a Java agregando una serie de servicios entre
los que se encuentran un modelo de componentes (en el que se base CCM [CCM01]) que permiten lograr
un estado persistente. Este modelo de componentes est integrado con CORBA y el servicio de
transacciones. Permiten funcionalidades mucho ms avanzadas que PSS, como por ejemplo, acceso
remoto a los objetos almacenados mediante diferentes protocolos entre los que se encuentran GIOP. La
nica desventaja de este modelo es que se requiere utilizar un contenedor de componentes, no es
suficiente con la mquina virtual misma. Este modelo debe ser comparado con el modelo de
componentes CORBA CCM.
Tambin sera posible utilizar una base de datos orientada a objetos tal como DB4O [DBO401]
directamente sin PSS, pero nuevamente esta alternativa queda fuera del alcance de CORBA, por lo que la
integracin debe ser implementada explcitamente por el programador. Esta y otras alternativa ser
analizada en ms detalle en la siguiente seccin.

44

Servicio de Estado Persistente CORBA (PSS)

Pablo M. Ilardi

REFERENCIAS
PSS01 Persistence State Service V2.0 OMG 2002. http://www.omg.org/cgi-bin/doc?formal/0209-06
CORBA01 Common Object Request Broker Architecture, Core Specification OMG.
http://www.omg.org/technology/documents/corba_spec_catalog.htm
POS01 Persistent Object Service POS, OMG 2000.
http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
TS01 Transaction Service Specification, OMG 2003.
http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
BgVaDk Gerald Brose, Andreas Vogel, Keith Duddy Java Programming with CORBA, Advanced
Techniques for Building Distributed Applications. 3rd Edition.- Wiley 2001.
KjPfTp Jan Kleindienst, Frantiek Plil, Petr Tuma What we are missing in the CORBA
Persistent Object Service Specification.
EisenbergMelton01 SQL:1999, formerly known as SQL3. Andrew Eisenberg, Sybase, Concord,
MA 01742 andrew.eisenberg@sybase.com; Jim Melton Sandy UT 84093 jim.melton@acm.org
Ramakanth01 Object-Relational Database Systems - The Road Ahead; Ramakanth S.
Devarakonda; http://www.acm.org/crossroads/xrds7-3/ordbms.html
Gamma01 Design Patterns: Elements of Reusable Object-Oriented Software - Addison-Wesley
Professional Computing Series - by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
January 15, 1995
CCM01 CORBA Component Model (CCM) Specification, OMG
http://www.omg.org/technology/documents/formal/components.htm
CCM02 CORBA Component Model Tutorial, Yokohama OMG Meeting Wednesday, April 24th,
2002. http://www.omg.org/docs/ccm/02-04-01.ppt
KingG01 Hibernate in Action, Christian Bauer, Gavin King; Manning, 2005. ISBN: 1932394-15-X.
http://www.hibernate.org
RoodsR01 Java Data Objects, Robin M. Roods; Addison-Wesley, 2003. ISBN 0-321-12380-8.
http://java.sun.com/javaee/technologies/jdo
DBO401 Database for Objects. http://www.db4o.com/about/productinformation
DEVQTC01 Developing Quality Technical Information. A handbook for Writers and Editors.
Second Edition. G. Hargis, M. Carey, A. Hernandez, P. Hughes, D. Longo, S. Rouiller, E. Wide. ISBN
0-13-1477490.

45

46

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

IMPLEMENTACIN DEL SERVICIO DE ESTADO PERSISTENTE CORBA - PSS


Consideracines iniciales .......................................................................................... 51
Partes ....................................................................................................................... 51
Persistencia Transparente..................................................................................... 51
El lenguaje de definicin PSDL .............................................................................. 52
Compilador PSDL ..................................................................................................... 52
Bases para el Compilador...................................................................................... 52
Partes del Compilador .......................................................................................... 53
Entender el cdigo de Entrada .............................................................................. 53
Generacin del Parser por JAVACC ................................................................... 54
Estructura del rbol generado ........................................................................... 56
Errores a nivel del Parser .................................................................................. 57
Generar el cdigo de Salida .................................................................................. 57
El patrn de diseo Visitor ................................................................................ 57
Identificadores...................................................................................................... 58
Proceso de Compilacin........................................................................................ 59
Cmo funciona el compilador ............................................................................... 60
Clases fundamentales que definen al compilador ............................................. 60
PSDLCompiler ............................................................................................... 60
PSDLParser.................................................................................................... 60
NodeProcessor.............................................................................................. 60
CompileProcess............................................................................................. 61
FullTypeDefinition ......................................................................................... 61
BaseStorageElementBuilder .......................................................................... 61
TargetCompiler ............................................................................................. 61
IdentifierProcessor ........................................................................................ 61
AbstractIdentifierProcessor .......................................................................... 62
ModuleIdentifierProcessor ........................................................................... 62
HolderGenerator y HelperGenerator............................................................. 62
CompilerDefinitionWriter ............................................................................. 62
Primera Fase Procesamiento .......................................................................... 62
Primer ejemplo de generacin de una definicin: ......................................... 64
Pasos requeridos ....................................................................................... 65
Segunda Fase Validacin ................................................................................ 67
Fallos en el proceso de validacin ................................................................. 67
Validacin del primer ejemplo de generacin de una definicin: .................. 68
Tercer Fase Generacin. ................................................................................. 69
Qu generar?, generacin de cdigo fuente ................................................ 69
Propio del Servicio, configuracin del Compilador ..................................... 71
Lo que es comn a todo servicio ................................................................... 72
Generacin de cdigo para el primer ejemplo ............................................... 73
Pasos......................................................................................................... 73
Conclusiones del Compilador ................................................................................ 74
Conexin del servicio de persistencia con la ORB .................................................... 74
Configuracin de la ORB para el acceso a sus referencias iniciales. ....................... 75

47

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Registro de Conectores para el servicio de persistencia ........................................ 76


Implementacin del servicio provisto por diferentes conectores ............................ 77
El conector del Servicio de Persistencia ................................................................ 77
Operaciones del conector ................................................................................. 79
Problemas que presenta la creacin de un conector ............................................. 81
Creacin de objetos .......................................................................................... 81
El patrn de diseo Template Method .......................................................... 81
Almacenes y Objetos almacenados ............................................................... 82
Almacenes ................................................................................................ 83
Modelo de Delegacin .......................................................................... 84
Objetos Almacenados ............................................................................... 84
StorageObjectSpec ................................................................................ 86
StorageObjectIdentifier ......................................................................... 86
Operaciones de bsqueda de Objetos............................................................... 87
Validacin de Claves ......................................................................................... 88
Destruccin de objetos almacenados ................................................................ 89
Diferentes Conectores .......................................................................................... 90
Conector de persistencia temporal ................................................................... 90
Funcionamiento ............................................................................................ 91
Manejo de identificadores ........................................................................ 91
Almacenes temporales .............................................................................. 92
Operaciones de bsqueda ......................................................................... 92
Conector de persistencia durable...................................................................... 92
Requerimientos para un conector de persistencia durable ........................... 92
Distintas alternativas para obtener persistencia durable ............................... 93
Persistencia mediante archivos ................................................................. 93
Persistencia mediante una base de datos relacional.................................. 93
Persistencia mediante una base de datos orientada a objetos .................. 95
DB4O .................................................................................................... 95
Conector persistente con soporte de DB4O .................................................. 99
Registro del Conector ................................................................................ 99
Funcionamiento ........................................................................................ 99
Relacin con DB4O ...............................................................................100
Objetos con estado compartido ...........................................................100
Identificadores .....................................................................................101
Operaciones atmicas ..........................................................................101
Almacenes............................................................................................103
Operaciones de consulta ......................................................................104
Creacin de objetos almacenados ........................................................104
Acceso remoto al repositorio ...............................................................105
Transacciones.......................................................................................106
Construcciones Resultantes del Trabajo .................................................................107
Un ejemplo concreto ..............................................................................................108
Cdigo PSDL.....................................................................................................108
Resultado de la compilacin del cdigo PSDL...................................................108
Persona ........................................................................................................109

48

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

PersonaHome ..............................................................................................109
PersonaBase ................................................................................................110
PersonHomeBase .........................................................................................112
PersonaBaseImpl .........................................................................................112
Uso del modelo en una aplicacin CORBA .......................................................113
Referencias .............................................................................................................117
Referencias a Bibliotecas ........................................................................................119

49

50

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

CONSIDERACINES INICIALES
Mi idea original para este trabajo fue utilizar C++, pero despus de un tiempo de trabajar en un
prototipo del servicio, desist y comenc a utilizar Java. Las razones fueron sencillas ya que la
especificacin se adapta mucho ms fcil a Java que a C++ y el modelo de objetos es anlogo al de Java.
Java provee de muchas ms herramientas de uso libre que C++. Por ejemplo, por el slo hecho de utilizar
Java, se cuenta con una ORB lista para ser utilizada que es parte de la especificacin del lenguaje.
El servicio de estado persistente de CORBA tiene como objetivo principal proveer estado
persistente a los servants. Mi implementacin cumple con ese cometido, pero tambin plantea la forma
de compartir ese estado desde distintas ubicaciones y servants.

PARTES
El trabajo se puede dividir en dos partes principales. La primera se fundamenta en que el servicio
de persistencia requiere que el usuario sea quin defina los tipos o clases que estarn disponibles. Y la
segunda es el servicio de persistencia propiamente dicho. Para la primer parte, el estndar define las dos
alternativas: Persistencia Transparente y uso del lenguaje PSDL.

PERSISTENCIA TRANSPARENTE
La persistencia transparente es atractiva ya que parece ms simple, slo es necesario definir los
objetos tal cual se hara en cualquier aplicacin. Sin embargo no es completa, tiene algunas limitaciones
tales como la definicin de las claves que definen la unicidad de los objetos, la definicin de operaciones
que pueden realizar los almacenes de objetos (storage homes), etc. El otro inconveniente que trae
acarreado esta alternativa es el cmo se integra en tiempo de ejecucin.
Segn la especificacin [PSS01] existen cuatro alternativas para integrar la persistencia
transparente:
1-

234-

Un pre procesador que agregue las construcciones necesarias del servicio de persistencia al
cdigo fuente Java. Por ejemplo, tome un atributo de la clase y modifique el cdigo donde
se utilice dicho estado.
Un compilador Java especial que haga algo similar al pre procesador antes mencionado.
Un pos procesador que realice modificaciones similares al cdigo binario resultante de la
compilacin (llamado bytecode en Java), pero en forma binaria.
O una mquina virtual Java especial que intercepte los accesos a los atributos de las clases.

El problema de las primeras dos opciones es que requieren que se tenga a mano el cdigo fuente
de las clases, lo cual no es siempre posible. Por consiguiente, las nicas dos opciones posibles son la 3 y 4.
A partir de la versin 5 de Java se han incorporado una serie de alternativas que le permiten a la
mquina virtual exportar puntos de control, que podran ser utilizados por un posible servicio de
persistencia que implemente persistencia transparente.
Uno de ellos se denomina JVMTI o JVM Tool interface [JVMTI01] (interfase de herramienta para
la mquina virtual), que consiste en que la mquina virtual permite configurar en el momento del inicio
de la misma, una biblioteca nativa llamada agente, que implementar dicha interfase. A grandes rasgos
dicha interfase exporta puntos de control de ejecucin del cdigo que se ejecuta dentro de la mquina
virtual. De esta forma, se podra seguir utilizando la misma mquina virtual para lograr lo mismo que lo
descrito en el punto 4. La desventaja es que se trata de una biblioteca implementada en cdigo nativo,
que debe entre otros, soportar las convenciones de las llamadas a funciones definidas en C y C++. Esto
agrega complejidad a la solucin ya que no solo se trata de una solucin escrita en Java.

51

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Otra alternativa tambin agregada a partir de a versin 5 de Java se denomina JVM


Instrumentation (Instrumentacin) [JVMI01]. Esta alternativa le permite a la maquina virtual utilizar una
biblioteca externa que modificar el cdigo binario de las clases cargadas antes de ser utilizadas. Este
mtodo, entre otros, sirve para interceptar las llamadas a todos los mtodos de las clases que se
requiera. La ventaja es que se trata de una herramienta que permite utilizar el mismo lenguaje Java para
modificar el cdigo a ejecutar en tiempo de ejecucin. Pero al igual que JVMTI, tiene que ser indicada al
momento de iniciar la mquina virtual y la modificacin al cdigo binario o bytecode deber hacerse cada
vez que se inicie la mquina virtual. La desventaja que comparten estas dos alternativas mencionadas
anteriormente, es que requieren utilizar una mquina virtual que sea compatible con la versin 5 de Java
o superior.
El principal inconveniente de cualquiera de las soluciones planteadas, es que requieren tener
control de la ejecucin de la mquina virtual. Las bibliotecas tienen que ser pasadas como parmetro en
la lnea de comando que inicie la mquina virtual. No siempre se tiene control de ejecucin de la mquina
virtual. Por ejemplo, en el mbito de ejecucin de las aplicaciones web, por lo general, se utilizan los
llamados contenedores web, como pueden ser el Tomcat o Jetty. En dichos entornos coexisten mltiples
aplicaciones para una misma mquina virtual. Y dependiendo de donde se ejecute dicha mquina virtual
es posible que por diversas razones no se tenga el control de la misma o que ni siquiera se conozca el
servidor donde se ejecuta la mquina virtual.

EL LENGUAJE DE DEFINICIN PSDL


Esta segunda alternativa para la definicin de los tipos a utilizar por el servicio de persistencia
requiere de la construccin de un compilador de PSDL que genere las clases en el lenguaje de
construccin del servicio. Es probable que requiera de mucho ms trabajo que cualquiera de las
soluciones planteadas en la persistencia transparente, pero es ms til a los efectos del usuario final del
servicio, dado que provee muchas ms funcionalidades. Otro punto a favor que tiene, es que podra ser
utilizada en cualquier entorno, sin importar si se tiene el control de la ejecucin de la mquina virtual o
no. Adems, vale notar que ninguna de las dos alternativas invalida a la otra, es decir, que se puede tener
un servicio de persistencia que provea las dos alternativas o incluso la segunda podra incluir a la primera.
Haciendo un balance de todas las alternativas posibles, la construccin del compilador PSDL es la
que aporta mayor valor agregado, dado que brinda ms funcionalidad y tiene menos limitaciones.
Por esta razn, la primer parte del trabajo consiste en la construccin del compilador, y la
segunda en la implementacin del servicio de persistencia.

COMPILADOR PSDL
El compilador del servicio de persistencia tiene que transformar el cdigo fuente PSDL en cdigo
fuente Java que cumpla con la especificacin del servicio y adems debe hacer que las construcciones
concretas construidas por ste, cumplan con alguna implementacin del servicio.
Segn el objetivo de mi trabajo, el compilador debe proveer la funcionalidad necesaria para
interactuar con el servicio de persistencia. Si bien, un compilador PSDL podra ser utilizado para compilar
archivos IDL, mi compilador se limitar a compilar las construcciones especficas del PSDL junto con
algunas otras del IDL que podran ser requeridas por PSDL. Si se quiere utilizar IDL siempre est
disponible el compilador IDL de la ORB que se utilice. De todas formas el compilador necesita entender
las construcciones IDL para cumplir con el estndar, aunque no genere cdigo Java para las mismas.

BASES PARA EL COMPILADOR

52

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

El lenguaje PSDL es una extensin al lenguaje estndar de CORBA, IDL. La especificacin del
servicio define completamente el mapeo de las construcciones abstractas como almacenes y objetos,
mientras que las concretas son ms abiertas y dependen de la implementacin del servicio.
La especificacin del servicio contiene la gramtica del lenguaje. Dicha definicin utiliza la
notacin EBNF (Extended Backus-Naur form), la cul es una extensin a BNF (Backus-Naur form).
BNF es la notacin formal estndar, definida por John Backus, utilizada para definir la gramtica
de los lenguajes [Garshol00]. Algol 60 fue el primer lenguaje popular en utilizarla. EBNF agrega pocos
cambios, pero que simplifican mucho su uso, entre los que se destacan los operadores: ?, * y + que
reducen la necesidad de utilizar definiciones recursivas.
Debido a que BNF realiza una definicin formal del lenguaje (con fundamentos matemticos y sin
ambigedades), es posible a partir de ella construir de forma mecnica un parser del lenguaje sin hacer
prcticamente cambios a la definicin.
Un parser es una herramienta que toma una entrada de texto realizando un anlisis gramatical
del mismo y validando su sintaxis.

PARTES DEL COMPILADOR


El proceso de compilacin que realiza el compilador se puede dividir en dos pasos que tienen
objetivos muy distintos [CooperRice00]. El primer paso es el de entender el cdigo de entrada, y el
segundo es el de traducirlo al cdigo de salida.

Representacin
Interna

Entender Cdigo de
Entrada

Cdigo
Fuente

Generar Cdigo de
Salida

Errores

Cdigo Salida

COMPILADOR 1 - PROCESO DE COMPILACIN

Estos dos pasos se comunican mediante una Representacin Interna del cdigo fuente que
ambos conocen, el primero la genera y el segundo la utiliza. Ambos pasos pueden generar errores que
impidan o no, la generacin del cdigo de salida. Estos errores son, por lo general, de distinta naturaleza,
el primero detecta errores de sintaxis mientras que el segundo detecta errores semnticos que no son
visibles sintcticamente.
Dependiendo de la complejidad del compilador, se pueden agregar ms pasos intermedios al
proceso. Por ejemplo, un paso que realice una optimizacin de la representacin interna que permita
generar un cdigo de salida ms ptimo que la solucin trivial.

ENTENDER EL CDIGO DE ENTRADA


Para entender el cdigo de entrada es necesario leer el cdigo e interpretarlo para as poder
generar la Representacin Interna. Este es un proceso comn a cualquier compilador y existen formas

53

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

estndar de realizar este paso [CooperRice00]. Se realiza con dos herramientas, la primera es un
analizador lexicogrfico y la segunda es un parser.
Un analizador lexicogrfico, descompone una secuencia de caracteres en sub-secuencias de los
mismos llamadas tokens (smbolo en ingls) y a su vez clasifica estos tokens segn la categora a la que
correspondan. A esta herramienta tambin se lo denomina scanner.
El parser toma estas secuencias de tokens, y las analiza para determinar la estructura del cdigo
fuente. El resultado del parser es un rbol que refleja esta estructura.

Entender Cdigo de Entrada

Analizador Lxico

Parser

Cdigo
Fuente

Representacin
Interna

Errores
COMPILADOR 2 - PRIMER PASO

Tanto el parser como el analizador lexicogrfico son responsables de generar los errores cuando
el cdigo fuente de entrada no respete las reglas sintcticas del lenguaje.
Existen dos tcnicas ampliamente utilizadas en la construccin de parsers, TOP-DOWN y
BOTTOM-UP. La mayora de los parsers utilizan alguna de estas dos tcnicas.
- TOP-DOWN: (de arriba hacia abajo en ingls) estos parsers tienen la estrategia de separar la
secuencia de entrada en grupos de caracteres grandes, para luego ir separndolos
sucesivamente en los elementos fundamentales o tokens. Es bsicamente un juego de prueba y
error donde se plantea la hiptesis de que una secuencia de caracteres representan una
determinada construccin del lenguaje.
- BOTTOM-UP: (de abajo hacia arriba) estos parsers tratan de ubicar los elementos fundamentales
o tokens, y en base a ellos tratan de enmarcarlos en las construcciones ms grandes definidas en
el lenguaje.
La complejidad de los parsers radica en como tomar la decisin de que construccin es la que
corresponde a una secuencia de caracteres determinados.
Por lo general, la construccin tanto del parser como del analizador lexicogrfico no es una tarea
simple y puede llevar mucho tiempo. Ambas estrategias de procesamiento, se pueden escribir en forma
de algoritmo y en base a l construir un programa que realice el proceso sobre un archivo.
Existen herramientas que tienen el objeto de generar el analizador lexicogrfico y el parser en
base a una definicin del lenguaje de forma ms o menos automtica. Esta definicin se realiza en
notacin EBNF, con algunos agregados propios de la herramienta.

G ENERACIN DEL P ARSER POR JAVACC

54

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Para la construccin del parser decid utilizar una herramienta denominada javacc (Java Compiler
Compiler) [Javacc00]. Javacc es una herramienta de uso libre bajo licencia BSD (Berkely Software
Distribution), publicada en la comunidad abierta: java.net, que es patrocinada por la empresa SUN,
creadora del lenguaje Java. Al tener licencia BSD se puede construir y distribuir cualquier tipo de software
construido mediante esta herramienta (tanto comercial como libre) sin tener que pagar por ello.
Javacc es una herramienta que permite generar un parser de tipo TOP-DOWN a partir de una
definicin gramatical. Javacc toma como entrada un archivo fuente (generalmente con extensin jj) y lo
transforma en uno o ms archivos Java que representan un programa que es capaz de procesar y
entender archivos fuente escritos mediante el lenguaje que defina la gramtica. Este programa no tiene
utilidad prctica, tan solo se limita a reportar si existe un error en el archivo fuente procesado.
Javacc utiliza la notacin EBNF junto con agregados que le indican a su pre procesador algunos
parmetros que son utilizados para generar las dos rutinas a construir: el parser y el analizador
lexicogrfico [JavaccTu00].
Si bien tericamente con la gramtica del lenguaje es posible definir un parser de forma
sistemtica [Garshol00], en la prctica es posible que el tiempo en determinar la validez o no de un
archivo o secuencia de caracteres relativamente grande, sea prohibitiva para un parser generado en
forma genrica. Un parser genrico utiliza habitualmente la tcnica de backtracking [Dasgupta00] para
analizar la validez de una secuencia de caracteres. Backtracking se aplica cuando al analizar una
secuencia de caracteres se llega a un punto donde se debe tomar una decisin sobre dos o ms caminos a
tomar. Se toma la decisin de seguir un camino, luego de un tiempo de seguirlo se llega a un punto donde
se determina que la secuencia de caracteres es invlida, pero entonces es necesario considerar que la
decisin tomada originalmente podra haber sido incorrecta. Se debe volver a dicho punto para
considerar la otra alternativa. Bsicamente, cada punto de bifurcacin debe ser registrado para poder
volver a l en caso de que se llegue a un punto que determine un error. Esta tcnica requiere de mucho
tiempo de procesamiento y memoria, y en muchos casos eso lleva a un programa o sistema que consume
recursos inadmisibles.
Por esto los parsers generados por javacc no utilizan la tcnica de backtracking, lo que hacen es
tratar de recaudar la mayor cantidad de informacin para tomar la decisin correcta, de forma tal de no
tener que volver atrs. Javacc lee los N tokens siguientes en la secuencia para determinar si es vlido o no
el rbol. La cantidad de niveles del rbol a procesar por cada nodo, es determinada por el parmetro
LOOKAHEAD del pre procesador. Un valor muy bajo puede determinar que el parser de cmo invlido
algo que no lo es, en cambio, uno muy alto puede hacer que el parser consuma mucha memoria y tiempo
en analizar y procesar el archivo. Por lo general, se define un LOOKAHEAD global y para ciertas
definiciones se pueden aumentar este valor, esto es necesario sobre todo en las definiciones recursivas.
Javacc toma como entrada un archivo de texto que contiene las directivas al pre procesador, la
notacin EBNF que define el lenguaje y cdigo Java que ser ejecutado por cada construccin que el
parser detecte en tiempo de ejecucin. Al ejecutar javacc sobre el archivo, se generan algunas clases Java
que sern utilizadas internamente por el parser y una clase Parser, que es la base para la construccin del
compilador.
La clase Parser generada solamente valida la sintaxis del archivo. Una forma prctica de utilizar el
Parser es utilizar javacc combinado con otra herramienta denominada jjtree. JJtree es un pre procesador
para javacc, que toma como entrada un archivo fuente javacc, y lo adapta de forma tal que el parser
generado por javacc genere un rbol con la estructura del archivo fuente procesado. Este pre procesador
inserta acciones que construirn el rbol a medida que el documento de entrada con cdigo fuente es
procesado.

55

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Primer
Paso

Segundo
Paso

jjtree

javacc

PSDL.jjt

PSDL.jj

Usa

Node*,java
PSDLParserVisitor.java

PSDLParser,java

COMPILADOR 3 - JAVACC

El rbol generado por jjtree estar compuesto por nodos. El tipo de nodo variar en funcin de la
estructura que el parser haya detectado en el archivo fuente. Se le puede indicar a la herramienta que
genere una clase para cada tipo de nodo que pueda existir en el rbol, este es el caso de mi compilador.
Por lo general, el tipo de nodo se corresponde uno a uno con las definiciones de la gramtica del
lenguaje. Por ejemplo:

<psdl_state_type_spec> ::= <base_type_spec>


| <string_type>
| <wide_string_type>
| <abstract_storagetype_ref_type>
| <scoped_name>

Es la definicin en notacin BNF del tipo de atributo de un estado de un objeto almacenado. En


la definicin del rbol, esto se traduce como un nodo de tipo: psdl_state_type_spec, que puede contener
como nodo hijo, algn nodo de los siguientes tipos: base_type_spec, string_type, wide_string_type,
abstract_storagetype_ref_type, o scoped_name. Entonces, jjtree generar una clase para cada uno de
estos nodos.
A veces no es til tener en el rbol algunos nodos que no sern utilizados por el compilador, en
esos casos se le puede definir al pre-procesador de jjtree que los ignore, por lo que ste no generar una
clase para dicho nodo y obviamente no existir en tiempo de ejecucin un nodo que tenga como hijo a un
nodo de este tipo.
Volviendo al esquema inicial del compilador en dos fases, se puede pensar que el rbol resultado
del procesamiento del parser, puede ser la Representacin Interna con la que se comunicarn las dos
partes del compilador.

E STRUCTURA DEL RBOL GENERADO


Como ya mencion anteriormente la estructura del rbol depende fundamentalmente de:
-

La definicin que se le haya otorgado a jjtree, y javacc para que generen el parser.
El archivo fuente procesado

56

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Segn mi definicin del lenguaje PSDL en notacin EBNF, todo rbol generado por el parser tendr
como raz un nodo de tipo: Nodepsdl_specification. Este nodo contendr nodos hijos con las
construcciones encontradas en el archivo procesado. En el caso de PSDL, las construcciones sern las
bsicas definidas por el lenguaje ms las existentes en IDL.
Todos los nodos generados por jjtree heredan de una clase base generada llamada SimpleNode.
Esta clase tiene como atributos el nodo padre y los nodos hijos junto con operaciones que permitirn
construir el rbol a medida que se procese el archivo de entrada. Adems, se le pueden agregar atributos
que podrn ser utilizados cuando se procese el rbol para reportar errores, por ejemplo, los tokens que
definieron la creacin del nodo. Los tokens aportan informacin importante como el nmero de lnea y
columna donde se encuentran en el archivo de entrada.

E RRORES A NIVEL DEL P ARSER


La clase Parser se encarga de detectar los errores lexicogrficos y sintcticos. Los errores
lexicogrficos se traducen en excepciones de tipo TokenMgrError, y los sintcticos en excepciones de tipo
ParseException. Estas dos clases de excepciones pueden reportar precisamente la ubicacin del error
detectado en el archivo de entrada, adems generan un mensaje de error que describe la causa del
mismo, por ejemplo, se esperaba un token {...} y no X.
Los errores lexicogrficos ocurren cuando el parser encuentra un carcter no esperado en una
secuencia. Por ejemplo, dada la siguiente gramtica para definir un nmero:

DEFINICION := NUMERO (+ NUMERO)*


, la siguiente secuencia de entrada:
45 12
, dar como resultado un error lexicogrficos diciendo que se esperaba un carcter + despus del 12 .
Los errores de tipo sintctico ocurren cuando los caracteres de entrada son vlidos, pero sin
embargo se encuentran ubicados de forma tal que no corresponden a una construccin vlida. Por
ejemplo, dada la misma definicin anterior de un nmero, ante una secuencia de entrada de tipo:
45 + + 12
, el parser generar un error sintctico diciendo que se esperaba un token de tipo NUMERO despus del
smbolo +.
El proceso de parsing puede detectar slo esta clase de errores descriptos. Existen otros errores
que no son derivados de la definicin gramatical del lenguaje y que no sern detectados por el parser. Por
ejemplo, que un identificador nico en el documento se encuentre duplicado. Esta clase de errores
tendrn que ser detectados en la segunda fase del proceso de compilacin.

GENERAR EL CDIGO DE SALIDA


Generar el cdigo de salida en lenguaje Java es el ltimo paso del compilador. La salida ser el
resultado de procesar el rbol generado por el parser. La herramienta que provee jjtree para simplificar
este proceso es una opcin que se basa en el patrn de diseo Visitor [Gamma01]. Cuanto la opcin es
activada el procesador generar una interfase Visitor (en ingls visitante), que permitir recorrer el rbol.

E L PATRN DE DISEO VISITOR

57

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

El patrn de diseo Visitor permite que un rbol de nodos sea recorrido o visitado por diferentes
objetos sin que los nodos tengan que estar al tanto de ello. Un ejemplo, sera recorrer el rbol para
generar una representacin del mismo en texto o para validar la estructura y la relacin entre los nodos,
o generar el cdigo de salida en base al mismo.
Este patrn es utilizado para recorrer estructuras, en este caso un rbol y su beneficio radica en
que la estructura o los elementos que la conforman no tienen que estar al tanto de que se hace con ese
procesamiento. Por otro lado, quien visita la estructura tampoco requiere conocer como est compuesta.
Podran existir diferentes implementaciones del visitante, sin que los nodos sean afectados por ellos. El
compilador representa una implementacin del visitante, y a la par podran existir otras
implementaciones, por ejemplo, un optimizador del rbol o para buscar errores en el mismo.

class Visitor
i nterface

i nterface

parser::PSDLParserVisitor

parser::Node
-chi
-parent
l dren

reali ze
compiler::
PSDLCompiler

real i ze
-parser

parser::
PSDLParser

-parser

parser::
SimpleNode

parser::
Nodepsdl_module

parser::
Nodepsdl_directiv e

COMPILADOR 4 - DIAGRAMA GENERAL DEL COMPILADOR

Bsicamente, existe un objeto Visitor, que visitar los nodos del rbol. Todos los nodos heredan
de una clase comn o implementan la misma interfase, que define un mtodo aceptar(Visitor), el cual
ser implementado por cada tipo de nodo invocando al mtodo visitar en el Visitor pasndose a s mismo
como parmetro: visitor.visitar(this). El Visitor tendr que implementar un mtodo visitar distinto por
cada tipo de nodo que quiera manejar de forma distinta o particular.
En el contexto del compilador, el Visitor est representado por la interfase PSDLParserVisitor, la
clase PDLCompiler es una implementacin del mismo. La interfase Node define todo aquello que puede
ser visitado. Para cada nodo que sea visitado, existir una clase concreta que implementar el mtodo
aceptar, que solamente deber llamar al mtodo visitar del Visitor que reciba como parmetro.

IDENTIFICADORES
La gramtica de PSDL contiene mltiples definiciones que referencian identificadores. Este
concepto es compartido o heredado de la definicin del IDL y por consiguiente del PSDL. Muchos tipos de
construcciones del IDL y PSDL utilizan el concepto de identificador, pero la definicin del mismo vara en
funcin del lugar donde se lo utilice. Por ejemplo, un identificador puede identificar a un tipo de objeto
almacenado o a un mtodo en un almacn. En otros casos, como por ejemplo, cuando se hace referencia
a una entidad definida anteriormente en el cdigo fuente (como en la declaracin de un estado), es

58

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

posible utilizar mltiples identificadores para identificarla, dado que la referencia puede ser dada tanto
en forma absoluta como relativa.
Existen mltiples reglas que determinan cuando un identificador es vlido y cuando no. Las
mismas estn asociadas a la definicin que utilice el identificador, y no son explcitas en la definicin
gramatical del lenguaje.
El hecho de que el concepto de identificador est presente, es un buen punto para definir un
diseo que permita un grado alto de reutilizacin de funcionalidades, ya que ser utilizado prcticamente
en todas las construcciones que procese y/o genere el compilador.

PROCESO DE COMPILACIN
La recorrida del rbol generado plantea algunos obstculos que tuvieron una gran influencia en
mi diseo del compilador:
1
2

Era necesario detectar aquellos errores que no fueran detectados por el parser
El rbol puede requerir incluir archivos externos, que se definen como #include en el cdigo
fuente de entrada. Este proceso puede ser recursivo y adems puede llevar a ciclos, que deben
ser contemplados.
El cdigo a generar para las construcciones concretas depende fuertemente de la
implementacin del servicio de persistencia, mientras que el cdigo a generar para las
construcciones abstractas es independiente de la implementacin (segn la especificacin del
servicio).
Las referencias a otros elementos puede hacerse tanto en forma absoluta como relativa
mediante en uso de los identificadores. Por ejemplo, en Java se puede referenciar a la clase
String por java.lang.String o simplemente por String. El compilador de Java determina las
referencias relativas en base a los imports de la clase. En PSDL, las referencias relativas se
resuelven en base al mdulo en el que se est referenciando a esta otra entidad.
Las definiciones pueden hacerse en forma directa, o en dos pasos mediante las declaraciones
forward o hacia adelante. Las definiciones forward permiten que la definicin sea referenciada,
sin estar completa su definicin, por ejemplo, para objetos almacenados que tengan declarados
estados de su mismo tipo.

Los errores que no detecta el parser son diversos y a veces no son simples de detectar. Algunos
de ellos son:
-

Contemplar la existencia de identificadores repetidos en el mismo archivo y / o en los archivos


incluidos.
Validar que las referencias a los identificadores estn disponibles
Validar que la jerarqua tanto de los objetos almacenados como de los almacenes sea
consistente, tanto para las construcciones concretas como para las abstractas.
Validar algunos requerimientos de la definicin de los objetos en PSDL, que no estn expuestos
en la definicin gramatical.

Para procesar los archivos incluidos por el archivo fuente original, es necesario procesar cada
uno de ellos de forma tal que se recaude la informacin necesaria para las validaciones antes descriptas.
Este proceso debe ejecutar el parser sobre estos archivos y no debe generar el cdigo de salida, adems
el proceso ejecutado por el parser debe lidiar con referencias circulares de archivos incluidos.
La existencia de definiciones forward, requiere al menos de dos pasos para poder recolectar toda
la informacin necesaria para determinar cuando una definicin es vlida y cuando no.
Por ltimo, pero no menos importante, el cdigo de salida depende fuertemente del servicio de
persistencia, se requiere que el compilador o una parte de l conozca el servicio de persistencia para el

59

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

que generar cdigo. Por ende, se requiere tener un servicio de persistencia totalmente definido para
poder construir el compilador. Como este no era mi caso, yo fui construyendo el compilador y la
implementacin del servicio en paralelo, por consiguiente tuve que desacoplar las partes del compilador
que requeran generar cdigo particular de la implementacin del servicio.

CMO FUNCIONA EL COMPILADOR


El grfico siguiente muestra una divisin arbitraria de los pasos en los que se divide el proceso de
compilacin. El paso 0 es procesar el archivo de entrada, dado que esta es una tarea que es realizada
mayormente por javacc, descripto anteriormente.
De esta forma, el proceso de compilacin ser descripto en tres fases, la primera fase
Procesamiento, la segunda Validacin y por ltimo Generacin. Cada una de estas fases requiere
de mltiples clases. A continuacin har una breve descripcin de algunas de las ms importantes.

composite structure CompilePhases

0 Parseo

ArchivoFuente

1 Procesamiento

2 Validacin

3 Generacin

Objetos Al macenados

Almacenes

COMPILADOR 5 - FASES DEL COMPILADOR

C LASES FUNDAMENTALES QUE DEFINEN AL COMPILADOR


Defin algunas clases fundamentales que estn encargadas de resolver los problemas
anteriormente descriptos. Algunas de ellas son abstractas y tienen mltiples clases que heredan de ella,
por lo general, me limitar a describir los objetivos de cada una y no los detalles de su implementacin.

PSDLC OMPILER
Esta clase modela al compilador en s mismo, es la cara visible. Toma como entrada un archivo
fuente que ser compilado y da como resultado los archivos fuentes generados. El archivo fuente es
procesado por el parser, el cual genera el rbol que describe el archivo fuente original. Este rbol ser
procesado por esta clase mediante el patrn Visitor descripto anteriormente, dado que PSDLCompiler
implementa la interfase PSDLParserVisitor.

PSDLP ARSER
Esta clase es la encargada de procesar el archivo de entrada generando el rbol que lo
represente. El compilador tiene una instancia de esta clase como atributo.

N ODE PROCESSOR
Algunos nodos del rbol requieren de varios niveles del mismo para completar una definicin, por
lo general, para cada nodo del rbol de este tipo que el compilador visite, ste crear una instancia del
procesador de nodo que es responsable de tomar acciones con la rama del rbol que se est visitando.

60

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Estas clases implementan la interfase NodeProcessor. Cuando se termine de procesar este nodo, el
compilador se lo har saber al procesador con un mensaje de tipo finalizarProceso.

C OMPILE PROCESS
El compilador crear un CompileProcess inicial para procesar el rbol. Esta clase modela el
proceso de compilacin de un archivo. El proceso tiene como objetivo recolectar las definiciones
declaradas en el rbol. Estas definiciones sern instancias de FullTypeDefinition. Existir una instancia de
CompileProcess por cada archivo procesado, es decir, si se incluye un archivo en el archivo fuente
original, esto resultar en la creacin en otro proceso de compilacin para dicho archivo. Adicionalmente,
el proceso mantiene informacin de estado del procesamiento del rbol, que es muy importante para
realizar las validaciones.

F ULL T YPE DEFINITION


Es una superclase que modela una construccin en el lenguaje Java. Existen dos clases concretas
que heredan de ella una es InterfaceDefinition, y la otra ClassDefinition. La primera modela una interfase
y la segunda una clase. Esta clase consta de los atributos bsicos que puede tener un objeto Java, tales
como: definicin de mtodos y atributos.
Estas definiciones sern construidas a medida que se procese el rbol por objetos de tipo
BaseStorageElementBuilder. Los builders sern notificados de los atributos de las definiciones a medida
que el rbol sea procesado.

B ASE S TORAGE E LEMENT B UILDER


Builder (constructor en ingls) es un patrn de diseo que permite encapsular la construccin de
un objeto complejo permitindole al objeto que lo utiliza deslindarse de la responsabilidad de cmo
construir dicho objeto [Gamma01].
Existen diferentes subclases de BaseStorageElementBuilder, una para cada tipo de construccin:
objetos almacenados abstractos que generan interfases Java, objetos almacenados concretos que
generan clases Java, almacenes abstractos que generan interfases y almacenes concretos que generan
clases.
Dichos builders tratan con el problema de la generacin de definiciones que se correspondan con
la implementacin del servicio de persistencia, para ello utilizan otra clase muy importante llamada
TargetCompiler.

T ARGET C OMPILER
TargetCompiler es una interfase que define las operaciones requeridas para generar definiciones
concretas (clases Java) que dependen de la implementacin del servicio. Por ejemplo, de cual clase debe
heredar una clase que represente un objeto almacenado concreto que deba ser utilizado por una
implementacin del servicio de persistencia que se basa en archivos.

I DENTIFIER PROCESSOR
Cada proceso de compilacin necesita de un objeto que ser el encargado de procesar los nodos
que representen un identificador en el rbol. Esta clase es necesaria debido que los identificadores
pueden ser definidos tanto en forma absoluta como relativa. Cuando estn en forma relativa, qu
identifican, estar dado por el mdulo que el proceso est navegando.
Cada proceso tiene un procesador de identificadores que lleva la cuenta de los identificadores que
no fueron procesados realmente, es decir, si este objeto tiene que procesar un nodo de identificador es
porque se produjo un error interno en el compilador, y alguna definicin no fue contemplada o fue mal
procesada. Cuando el compilador visite un nodo que defina una entidad, el objeto que procese ese nodo

61

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

ser responsable de indicarle al proceso cual es el objeto que procesar el siguiente nodo de identificador
en el rbol.
De esta forma cada vez que se visite un nodo que represente un identificador, el procesador que
est definido en el proceso ser notificado de ello.

A BSTRACT I DENTIFIER P ROCESSOR


Existen mltiples nodos del rbol que dependen de un identificador para concretar una
definicin vlida. Esta clase base permite tomar del proceso el identificador para luego hacer con l lo
que corresponda al tipo de nodo.

M ODULE I DENTIFIER P ROCESSOR


Esta clase es una subclase de AbstractIdentifierProcessor y adems implementa la interfase
NodeProcessor, cuando un nodo que identifique un mdulo sea visitado, el compilador le indicar al
proceso que el procesador de identificadores a utilizar ser una instancia de esta clase. Cuando esta clase
procese un identificador le indicar al proceso que el paquete de Java que se est procesando en ese
momento, es el anterior ms el nuevo identificador. Cuando se termine de procesar el nodo que define al
mdulo, se restaura en el proceso el paquete que se estaba procesando anteriormente.

H OLDER G ENERATOR Y H ELPER GENERATOR


Segn la especificacin, las interfases generadas deben generar sus respectivas clases Helper y
Holder acordes con la especificacin de CORBA [IDL2Java]. Todas las definiciones abstractas del servicio
requieren de sus respectivas clases Holder y Helper. HolderGenerator y HelperGenerator se encargan, en
base a una instancia de FullTypeDefinition, de generar las clases Helper y Holder respectivamente. Una
clase holder se utiliza como objeto que permite pasar parmetros a mtodos IDL, tanto de entrada como
de salida. Dicha clase almacena un objeto del tipo que transporta. Soporta operaciones para leer o
escribir el objeto que almacena en un stream de bytes (una secuencia de bytes que pueden definir un
conjunto de objetos en su representacin binaria). Las clases Helper, se utilizan para interactuar con el
objeto genrico Any de CORBA. Any es un contenedor de cualquier objeto definido en IDL. Se necesita de
una clase Helper, para insertar y sacar un objeto de un tipo especfico del contenedor.

C OMPILER D EFINITION W RITER


Esta clase es la responsable de plasmar en archivos fuente Java, las definiciones generadas por el
proceso de compilacin. El compilador tiene un atributo de este tipo que ser invocado una vez por cada
definicin recolectada por el proceso al finalizar el proceso de compilacin. Para generar el archivo
fuente, esta clase crear una instancia de un objeto de tipo FileBuilder, que procesar la definicin a
construir interrogndola sobre cada uno de sus atributos.

P RIMERA F ASE P ROCESAMIENTO


El objetivo de esta fase es generar un CompileProcess, que contendr todas las definiciones que
tendrn que ser generadas en cdigo fuente en la tercera fase, junto con otras que son necesarias para
generar y/o validar las definiciones. Para ello se parte del rbol generado por el parser, cuya raz, en el
caso de mi definicin del lenguaje, ser siempre de tipo Nodepsdl_specification.

62

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class ClassDefinitions

parser::SimpleNode

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

childrenAccept(PSDLParserVisitor, Object) : Object


dump(String) : void
getFirst() : T oken
getLast() : T oken
jjtAddChild(Node, int) : void
jjtClose() : void
jjtGetChild(int) : Node
jjtGetNumChildren() : int
jjtGetParent() : Node
jjtOpen() : void
jjtSetParent(Node) : void
setFirst(T oken) : void
setLast(T oken) : void
SimpleNode(PSDLParser, int)
toString() : String
toString(String) : String

parser::Nodepsdl_specification
+
+

jjtAccept(PSDLParserVisitor, Object) : Object


Nodepsdl_specification(PSDLParser, int)

COMPILADOR 6 - NODOS DE RBOL

Todos los nodos del rbol heredan de la clase SimpleNode. Las dos clases que se muestran en el
diagrama anterior, fueron generadas por el procesador jjtree. A los efectos de procesar el rbol, los
nicos mtodos que importan son jjAccept y childrenAccept. El primero tiene que estar implementado
en cada clase de nodo en particular, dado que as lo requiere el patrn Visitor. El segundo ser invocado
por el compilador para procesar el siguiente nivel del rbol. La implementacin es tan simple como tomar
cada nodo hijo e invocar al mtodo jjAccept sobre l.
Entonces el proceso comienza cuando se invoca al mtodo jjAccept sobre el nodo raz, con dos
parmetros, el primero el compilador mismo y el segundo el proceso de compilacin. Para cada nodo los
pasos son:
o
o
o

Se visita el nodo. El nodo le indica al compilador que se est visitando un nodo del tipo que
corresponde.
El compilador realiza una operacin en base al tipo de nodo,
Se visitan a los hijos del nodo, donde el proceso comienza nuevamente, hasta que no queden
nodos por visitar.

En este punto, el proceso de compilacin habr recolectado todas las definiciones generadas al
visitar nodos de definicin.
El siguiente diagrama de objetos muestra la interaccin entre los objetos para concretar la
primera fase, donde se tendr como resultado el proceso de compilacin.

63

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

object SimpleCompileProcess

1: PSDLCompi ler(fi leNam e,targetName) :aCompil er

w riter :
CompilerDefinitionWriter

2: com pi le(targetFol der)


1.4: Com pil erDefi nitionWriter(aCom pi ler) :writer

endUser

aCompiler :
PSDLCompiler

1.3: PSDLParser(fi leNam e) :aParser


aParser :PSDLParser
2.1: parse() :aSpeci fi cati on

1.1: forName(name) :target


3: j jtAccept(visi tor,process)
registrySingleton :
TargetCompilerRegistry

2.2: Nodepsdl _speci fi cati on(aParser,i d)


3.1: vi sit(node,process) :Obj ect
3.2: chil drenAccept(aCompil er, process)

1.2: l ookup
aSpecification :
Nodepsdl_specification

interface
target :
TargetCompiler

2.3: Com pileProcess(aCompil er,i dProcessor)

3.3: fini shProcess(compi ler,process)

process :
CompileProcess
2.4: new

identifierProcessor :
CounterIdentifierProcessor

COMPILADOR 7 - PRIMERA FASE

En mi implementacin existen cuatro tipos de nodos que agregan definiciones al proceso de


compilacin, los cuales son: nodos de definiciones abstractas de objetos almacenados y almacenes, y los
nodos de las respectivas definiciones concretas.
Cada tipo de nodo que genere una definicin tiene una subclase de BaseStorageElementBuilder,
que se encargar de acumular la informacin necesaria para construir la definicin. Por ejemplo, en el
caso de un objeto almacenado abstracto, el builder que se crea es de tipo: AbstractStorageTypeBuilder.

P RIMER EJEMPLO DE GENERACIN DE UNA DEFINICIN :


A continuacin voy a ilustrar la secuencia de ejecucin para llegar a construir un proceso de
compilacin que contenga la definicin de un objeto almacenado. El cdigo PSDL a procesar ser el
siguiente:
module ejemploFaseUno {
abstract storagetype Prueba {
state string nombre;
};
};

En el cdigo anterior se define un objeto almacenado dentro de un mdulo con un nico estado
llamado nombre y de tipo string (secuencia de caracteres).

64

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

El rbol generado por el parser ser el siguiente:

Nodepsdl_specification
|-->Nodepsdl_module
|-->Nodeidentifier(ejemploFaseUno)
|-->Nodeabstract_storagetype
|-->Nodeidentifier(Prueba)
|-->Nodepsdl_state_dcl
|-->Nodepsdl_state_type_spec
|
|-->Nodestring_type
|-->Nodesimple_declarator
|-->Nodeidentifier(nombre)

PASOS REQUERIDOS
1- El compilador genera un CompileProcess, inicialmente con un IdentifierProcessor que llevar la
cuenta de los identificadores no procesados, una instancia de CounterIdentifierProcessor.
2- Se inicia el proceso de recorrido del rbol con el nodo raz Nodepsdl_specification, llamando al
mtodo jjAccept con el proceso creado anteriormente.
3- El nodo Nodepsdl_specification le indica al compilador que se visita a este tipo de nodo
llamando al mtodo visit con s mismo como parmetro y el proceso que recibi anteriormente.
Como el compilador no necesita realizar otra tarea adicional, sigue el proceso de recorrido del
rbol llamando al mtodo childrenAccept en el nodo visitado.
4- El primer nodo hijo es Nodepsdl_module, el cual termina llamando al mtodo visit del
compilador. Al visitar este nodo el compilador instancia un objeto de tipo
ModuleIdentifierProcessor. Cuando el ModuleIdentifierProcessor es creado, ste le indica al
proceso que el nuevo procesador de identificadores ser l. Luego de esto, se sigue procesando
la rama del rbol debajo del mdulo.
5- El primer nodo debajo del nodo del mdulo es Nodeidentifier. Al visitar este tipo de nodo el
compilador le pide al proceso, el procesador de identificadores para procesar este nodo, que en
este caso ser ModuleIdentifierProcessor (definido en el paso anterior). Esta clase toma el
identificador y genera una definicin de paquete Java indicndole al proceso actual cual es el
paquete que corresponde, en este caso: ser ejemploFaseUno. Luego restaura el procesador
anterior y sigue procesando los nodos hijos. Como el nodo de identificador no tiene nodos hijos,
se vuelve a procesar los nodos hijos del nodo que defini el mdulo.
6- El siguiente nodo hijo es Nodeabstract_storagetype. Cuando el compilador visita este tipo de
nodos, crea una instancia de AbstractStorageTypeBuilder. Cuando este tipo de nodo es creado,
ste le pide al proceso actual el paquete Java procesado (definido en el paso anterior),
inicializando la definicin del objeto con l. Adems le indica al proceso actual que l mismo ser
el procesador de identificadores. Luego de ello se procesan el nodo con sus hijos.
7- El primer nodo hijo ser Nodeidentifier. Cuando se visite este nodo se terminar utilizando el
identificador de procesos definido en el proceso, que es justamente el nodo
Nodeabstract_storagetype, definido en el paso anterior. Este nodo tomar el identificador
definido, en este caso Prueba, y lo asociar a la definicin que se est construyendo del objeto
almacenado. Restaura nuevamente el procesador de identificadores anterior y sigue procesando
los nodos hijos.
8- El siguiente nodo hijo de Nodeabstract_storagetype es Nodepsdl_state_dcl, en este caso el
compilador crear una instancia de objeto de tipo StateMemberBuilder, y luego procesar los
nodos hijos de ste.
9- El primer nodo hijo ser Nodepsdl_state_type_spec, el cul define el tipo de dato del estado que
se est definiendo. En este caso, el compilador instancia un objeto de tipo
StorageTypeStateDeclarationProcessor, que al ser creado le indica al proceso actual que l ser

65

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

el objeto encargado de registrar los prximos identificadores a procesar del rbol. Luego de esto
se procede a procesar los nodos hijos del nodo.
10- El nico nodo hijo de Nodepsdl_state_type_spec, en este caso es Nodestring_type, que al ser
procesado por el compilador lo nico que hace es indicarle al builder actual que el tipo de dato
es STRING.
11- Como no hay ms nodos hijos del Nodepsdl_state_type_spec, se le indica a este nodo que se ha
completado el procesamiento de sus hijos. En este punto, el nodo tiene la oportunidad de armar
la definicin completa del tipo de dato del estado. Como en este caso es un STRING no hay ms
nada que hacer, pero si se tratara de un tipo de dato, como por ejemplo, una referencia a otro
tipo de objeto almacenado definida en forma relativa al paquete actual, se transformara en una
referencia a un tipo absoluto. Luego se restaura el procesador de identificadores anterior. Y se
siguen procesando los nodos hijos de Nodepsdl_state_dcl.
12- El prximo nodo hijo es Nodesimple_declarator. Cuando el compilador detecta este tipo de
nodos instancia un objeto de tipo SimpleDeclaratorIdentifierProcessor, que simplemente se
pone a s mismo como procesador de identificadores. Al procesar el siguiente nodo de
identificador se almacenar el valor nombre.
13- Como no hay ms nodos por procesar, StateMemberBuilder tomar el identificador generado
por SimpleDeclaratorIdentifierProcessor, y definir el nombre del estado. En este punto, el
nodo puede realizar una validacin simple, que es que no exista otro estado con ese nombre
dentro de la lista de estados que se pueden definir agrupadamente. Este tipo de validaciones no
pueden ser realizadas por el parser, ya que no son parte de la definicin gramatical del lenguaje.
14- Luego de que se procesaron todos los nodos por AbstractStorageTypeBuilder, ste tomar como
resultado de visitar la rama, lo que define al StateMemberBuilder, y lo agregar como definicin
de un estado. Adems, realizar una serie de validaciones, por ejemplo, si el tipo de estado es
una referencia a otro tipo de objeto, ste debe estar definido previamente. Nuevamente estas
validaciones se hacen en este punto ya que no es estn definidas en la gramtica del lenguaje
que define al parser. De todas formas esta validacin ser parcial ya que es tambin necesario
validar la unicidad de los estados dentro de la jerarqua a la que pertenezca el objeto
almacenado. Esta validacin ser realizada en la siguiente fase, dado que en este punto no est
definida dicha jerarqua.
15- En este punto AbstractStorageTypeBuilder termin de procesar todos los nodos hijos y puede
registrarse con el proceso actual como un tipo de objeto almacenado definido durante el
proceso. Al procesar el registro, el proceso tiene la oportunidad de realizar algunas operaciones,
como validar definiciones duplicadas o reemplazar una definicin anterior parciales (forward). El
caso de las definiciones parciales se da cuando en el archivo fuente se encuentra una definicin
con solamente un identificador, de forma tal que pueda ser referenciada en otras definiciones
sin estar an definida completamente en el documento.
16- Se han terminado de procesar todos los nodos. El compilador le indica al procesador de
identificadores actual, que se ha completado el proceso. CounterIdentifierProcessor sabr en
este punto si alguno de los identificadores no ha sido considerado, en cuyo caso generar un
error interno de compilacin.
17- Finalmente, el proceso de compilacin est completo y la primera fase del compilador.

El proceso de la fase anterior en el ejemplo da como resultado un objeto de tipo CompileProcess,


que contendr un objeto que, en principio, representa la posibilidad de generar el cdigo para la
definicin del objeto almacenado ejemploFaseUno.Prueba. Este objeto es de tipo
AbstractStorageTypeBuilder y representa la posibilidad de genera cdigo porque su uso depende de la
siguiente fase. En algunos casos, el proceso de compilacin puede ser generado como resultado de la
inclusin de un archivo en el documento original que se est compilando, y su utilidad es la de permitir
validar las definiciones que se declaren en el archivo original y no la de generar cdigo fuente.

66

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Como puede verse, la compilacin de una estructura simple como la descripta anteriormente
requiere de mltiples objetos e interacciones entre los mismos.
Resumiendo, el resultado siempre es un objeto de tipo CompileProcess. Dicho objeto almacena la
lista de definiciones existentes en el archivo original. Estas definiciones se concretan siempre en objetos
que heredan de la clase BaseStorageElementBuilder. Esta familia de clases sigue el patrn Builder
(constructor) definido en Gamma01. Estos objetos sern utilizados en la ltima fase para generar los
archivos fuente resultantes.

S EGUNDA F ASE V ALIDACIN


Esta fase se caracteriza por realizar todas las validaciones necesarias que no pudieron ser
concretadas en las fases anteriores. A medida que se va procesando el rbol se va recolectando
informacin que sirve tanto para construir el resultado, como para realizar todas las validaciones que
describo a continuacin.
Al invocar el mtodo validate sobre el proceso de compilacin generado en la fase anterior se
inicia esta fase. Cada una de las definiciones acumuladas ser validada. Cada definicin generada hereda
de la clase abstracta BaseStorageElementBuilder, la cual define un mtodo validate que ser invocado
para cada definicin registrada en el proceso. Cuando la fase sea exitosa el resultado de la validacin del
proceso ser la lista de nombres de las definiciones que debern ser generadas. Esta lista ser la entrada
para la siguiente fase. Cuando la fase falle, su resultado ser una excepcin de tipo
PSDLCompilerException.

F ALLOS EN EL PROCESO DE VALIDACIN


Existen mltiples circunstancias por las cuales esta fase puede fallar. Cada tipo de falla tiene su
representacin en una subclase de PSDLCompilerException, a continuacin enumerar las ms comunes:
-

DefinitionNotFoundException: esta excepcin indica que en alguna definicin PSDL se hace


referencia a otra definicin, y sta no pudo ser encontrada. Las causas pueden ser mltiples,
por ejemplo hacer referencia a una definicin que se encuentra ms adelante en el archivo
sin haberla declarado como forward, o simplemente un error de tipografa en el nombre.
DuplicateDefinitionFoundException: ocurre cuando se trata de definir una entidad que ya
se encontraba definida anteriormente, en el mismo archivo o en otro incluido
anteriormente.
IllegalFactoryMethodException: esta excepcin representa que el compilador encuentra
una definicin invlida de un mtodo factory. Esto ocurre cuando se definen nombres de
estados no existentes como parmetros al mtodo, o bien cuando se agrega ms de una vez
el nombre del estado al mtodo.
IllegalKeyDefinitionException: representa una definicin invalida de una clave. Puede ser
tanto por contener un estado no existente o tener ms de una vez el mismo estado como
parte de la clave.
IllegalStateDefinitionFound: se trata de una excepcin que se produce cuando la definicin
de un estado esta dada por un tipo invlido, como por ejemplo, un almacn en vez de un
tipo de objeto almacenado.
IncludeFileException: es la excepcin que se genera cuando se trata de incluir un archivo y
este no fue encontrado.

67

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class exceptions
RuntimeException
PSDLCompilerException

DefinitionNotFoundException
+

DefinitionNotFoundException(ful lT ypeDefinition, referenci ngDefi niti on)

+
+

PSDLCompil erExcepti on(message)


PSDLCompil erExcepti on(message, cause)
IllegalStateDefinitionFound

IllegalFactoryMethodException
+

Il legal FactoryMethodException(factoryName, message, referencer)

Il legalStateDefinitionFound(parent, stateDefinition, message)

IllegalKeyDefinitionException

DuplicateDefinitionFoundException
+

Dupl icateDefi ni ti onFoundException(defi nition, m essage)

Il legalKeyDefinitionExcepti on(keyName, message, referencer)

IncludeFileException
IllegalDefinitionFoundException
+

IllegalDefinitionFoundExcepti on(full T ypeDefi niti on, m essage)

IllegalStateException
+
+

IllegalStateExcepti on(message)
IllegalStateExcepti on(message, e)

+
+

IncludeFil eException(m essage)


IncludeFil eException(m essage, cause)

COMPILADOR 8 - EXEPCIONES DE VALIDACIN

Existen dos clases de excepciones de validacin que representan errores mas generales de la
definicin, que son: IllegalDefinitionFoundException y IllegalStateException.
La primera excepcin se genera cuando se llega a un punto del procesamiento en el que la
definicin que se esta procesando debe ser marcada como invlida dado que viola alguna regla. Pero esto
no se debe a, por ejemplo, un estado mal definido o un estado duplicado, sino a que la suma de atributos
de la definicin la hacen invlida. Por ejemplo, cuando en la definicin de una herencia de almacenes se
detecta que el tipo almacenado de un almacn hijo no es un subtipo de tipo almacenado por alguno de
los almacenes padres. O cuando se trata de agregar una clave primaria a un nodo que no es la raz de la
familia de almacenes. Por lo general, como este tipo de errores no se pueden atribuir a una parte de la
definicin, el usuario final tendr que verificar a que corresponde el error.
La segunda excepcin IllegalStateException est asociada a potenciales errores internos del
compilador. Por ejemplo, tratar de construir definicines en base a definiciones no validadas, o tratar de
agregar una definicin ms de una vez a un proceso de compilacin, etc. Este tipo de errores es probable
que se produzcan cuando se agreguen extensiones al compilador para generar cdigo para otros servicios
de persistencia.
A continuacin voy a ejemplificar la serie de pasos para la validacin del ejemplo de la fase
anterior.

V ALIDACIN DEL PRIMER EJEMPLO DE GENERACIN DE UNA DEFINICIN :


1- El compilador invoca al mtodo validate del CompileProcess.
2- Para cada definicin acumulada, el proceso ejecuta el mtodo validate. En este caso la nica
definicin acumulada es de tipo AbstractStorageTypeBuilder.
a. AbstractStorageTypeBuilder verifica que no se trate de una definicin forward. Esto sera un
error ya que se referencia a una definicin no existente en el documento.
b. AbstractStorageTypeBuilder verifica que no existan operaciones o mtodo declarados
dentro de la jerarqua del objeto. Para ello visita todas las definiciones que sean parte de su
jerarqua recolectando todos los mtodos definidos. Todas las definiciones de sus supertipos
tienen que ser accesibles desde el proceso de compilacin o alguno de los procesos de
compilacin resultantes de los archivos incluidos en el proceso.
c. AbstractStorageTypeBuilder verifica que no existan nombres de estados duplicados en la
jerarqua. El proceso es similar al punto anterior. Como la definicin de un objeto
almacenado abstracto soporta la herencia en forma diamante, pueden existir estados o
mtodo duplicados en la jerarqua, pero lo importante es que estas definiciones duplicadas
provengan del mismo origen, en este caso de la misma definicin de objeto almacenado.
d. AbstractStorageTypeBuilder se marca como validada y el proceso de validacin concluye.

68

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

T ERCER F ASE G ENERACIN .


Una vez validado el proceso de compilacin generado en la fase uno, se deben generar todos los
archivos fuente Java que resulten de compilar el archivo PSDL. Esta fase da comienzo cuando se invoca al
mtodo generate del objeto CompileProcess resultante de la fase uno.
Como mencion anteriormente segn la especificacin del servicio, las definiciones abstractas
debieran ser independientes de la implementacin del servicio, mientras que para las concretas se
recomienda mantenerlas lo ms separadas posible de los detalles de implementacin del servicio. Esto
implica que el cdigo a generar depender en algunas circunstancias de la implementacin del servicio y
en otras ser dependiente de la especificacin del mismo.
Hasta este punto, ninguna parte del compilador dependa de la implementacin del servicio. Es
una prioridad mantener la separacin del compilador de la impementacin del servicio de persistencia, ya
que me permite tener dos o ms implementaciones del servicio de persistencia sin tener que modificar al
compilador. De igual forma le permite a otra persona utilizar el mismo compilador para su propia
implementacin del servicio de persistencia. En definitiva, promueve un bajo acoplamiento entre el
compilador y la implementacin del servicio.
Esto requiere que al menos una parte del compilador sea configurable o extensible en funcin del
servicio de persistencia que se quiera utilizar. Cualquiera de los posibles servicios de persistencia que
utilicen el compilador, requerirn tambin generar el cdigo fuente resultante, parte del cul ser
compartido y otra ser propia.
Al tener un nico compilador para mltiples servicios, trat de lograr el mayor grado de
reutilizacin de cdigo, de manera de minimizar el trabajo requerido. Para ello divid esta fase en tres
partes, expresadas en el grfico siguiente:
composite structure Generacin

Propio del Serv icio

Generacin de
Cdigo

Comn a todo
Serv icio

COMPILADOR 9 - TRES PARTES

GENERACIN DE CDIGO FUENTE

Cualquier implementacin del servicio requerir generar cdigo fuente. La forma de lograr un alto
grado de reutilizacin entre diferentes implementaciones del servicio es definir un modelo comn que
puedan utilizar todas las implementaciones. El grfico 10 muestra el qu generar, bsicamente es un
modelo casi completo de cualquier elemento que se quiera definir en lenguaje Java, una clase, interfase,
etc.
Se trata de una serie de clases que modelan las distintas partes que podran componer un archivo
fuente. Las clases representadas en el grfico son la base para un generador de cdigo fuente
independiente del compilador. A continuacin, dar una breve descripcin de algunas de las clases ms
importantes.
 Type Definition: la definicin de un tipo de objeto en Java est dada por un paquete y un nombre.
 Import Declaration: todo archivo fuente Java puede importar otras definiciones para poder
utilizarlas directamente. Considero que siempre se importan tipos de objetos, por lo cual, una
declaracin de import es simplemente una referencia a una definicin de un tipo. Tambin se
podran importar paquetes enteros pero no creo que sea algo necesario, por lo que esta definicin
no lo soporta.

69

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

 Instance Definition: es simplemente una definicin de un tipo nombrada, de forma tal que puede
ser utilizada como parmetro a un mtodo o en la declaracin de un atributo.

class generationLite

TypeDefinition

Comparabl e
ImportDeclaration

NestedGenerator
PackageDefinition
InstanceDefinition

OperationDefinition
NestedGenerator
AccessibilityDefinition

M ethodDefinition

AttributeDefinition

ConstructorDefinition

FullTypeDefinition
Keyw ord
DefinitionFactory

ElementTypeKeyw ord

InterfaceDefinition

ClassDefinition

COMPILADOR 10 - QU GENERAR

 Accessibility Definition: es la modelizacin de los niveles de accesibilidad que pueden definirse en


Java, por ejemplo pblico, esttico, etc.
 Attribute Definition: se define como la definicin de una instancia con un nivel de accesibilidad.
Esto permite, por ejemplo, modelar un atributo de una clase.
 Operation Definition: Una operacin es una superclase, que sirve como base para definir mtodos
y constructores. Una operacin est definida por una lista de instancias que seran los parmetros,
junto con una visibilidad y una definicin de un tipo que representa el tipo de valor que retorna la
operacin. Un mtodo solo agrega un nombre a la superclase.
 FullTypeDefinition: Se trata de otra superclase que representa la definicin completa de un tipo en
Java. Es la base para definir una interfase o una clase. Se compone de una lista de atributos, una
lista de mtodos y la visibilidad del tipo. Tambin tiene una lista de interfase que implementa o
extiende. La definicin de una clase agrega la posibilidad de heredar de otra clase.
 Keyword: es cualquier palabra clave reservada en el lenguaje.
 DefinitionFactory: Es una clase basada en el patrn de diseo Factory [Gamma01]. Bsicamente se
trata de una clase que permite generar definiciones basadas en clases reales de Java.

Cada implementacin del servicio, ser responsable de generar sus clases mediante el uso de
este modelo.

70

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Desde la perspectiva del CompileProcess, cada builder generado en la primer fase generar al
menos un FullTypeDefinition cada uno. Cada una de estas definiciones de tipos genera un archivo fuente.
Como se construyen estos tipos es transparente para el compilador y ser la tarea del TargetCompiler.
class fileBuilding

generation::CompilerDefinitionWriter
compiler::CompileProcess

+
-

COMPILER_KEY: String = "compiler" {readOnly}


headerTm pl: URL {readOnly}
prop: Map<String, Object> {readOnly}

+
#
#
+

CompilerDefinitionWriter(PSDLCompiler)
getCom pilerProperties() : Map<String, Object>
getFileHeaderT mpl() : URL
write(T, File) : void

interface
Generator

instantiate

+
+

addTo(TypeDefinitionAppender) : void
w riteYouSelfInto(FileBuilderColaborator) : void

instantiate
T:extends FullTypeDefinition

TextAppender

realize

interface
FileBuilder

FileBuilderColaborator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

attributeEnd() : void
attributeStart() : void
bodyEnd() : void
bodyStart() : void
getFileProperties(Generator) : Map<String, Object>
getStringRepresentation(TypeDefinition) : String
methodEnd(boolean) : void
methodStart(boolean) : void
writeAccesibility(AccessibilityDefinition) : void
writeBlock(String, Generator, Map<String, Object>, boolean) : void
writeExceptions(List<TypeDefinition>) : void
writeInstance(InstanceDefinition) : void
writeKeyw ord(Keyw ord) : void
writeLiteral(String) : void
writeOperationWithParameters(String, List<InstanceDefinition>, boolean) : void
writeSuperClass(TypeDefinition) : void
writeSuperInterfaces(Keyw ord, List<TypeDefinition>) : void
writeTemplateText(URL, Map<String, Object>, boolean) : void
writeTypeDefinition(TypeDefinition) : void

FullTypeDefinition
+
+
+
+

build(URL, File) : void


build(File) : void
FileBuilder(T , Map<String, Object>)
with(D) : FileBuilder<T>

#types

instantiate

realize

FileBuilder::
LocalFilebuilderColaborator

COMPILADOR 11 - GENERACIN DE ARCHIVOS

El grfico anterior define como a partir del modelo, se procede a generar los archivos fuentes.
Cada parte del modelo implementa la interfase Generator. Esta interfase define que el objeto que la
implementa sabe como agregarse a s mismo a un objeto encargado de construir un archivo, mediante el
mtodo writeYourSelfTo. Este mtodo recibe como parmetro un objeto que implementa la interfase
FileBuilderColaborator. Una instancia de FileBuilder, ser la encargada de tomar cada una de las
definiciones construidas en el CompileProcess y mediante una llamada al mtodo writeYourSelfTo,
construir el archivo fuente para cada tipo definido.

P ROPIO DEL SERVICIO , CONFIGURACIN DEL C OMPILADOR


La implementacin del servicio de persistencia debe proveerle al compilador una clase que le
permita a ste generar cdigo propietario. Esta clase deber implementar la interfase TargetCompiler.
Esta interfase tiene definidas todas las operaciones que requieran construir definiciones particulares para
la implementacin del servicio. Por ejemplo, el mtodo generateRead, indica que debe generarse la
implementacin de un mtodo para leer un estado de un objeto almacenado. El compilador conoce los
TargetCompilers que existen por medio de la clase TargetCompilerRegistry, que modela un registro al
que se accede por nombre del target. Cuando el compilador es creado se le indica a ste cual es el
servicio de persistencia para el que se generar el cdigo. Con este nombre se acceder al registro del
compilador para recuperar el TargetCompiler necesario.
Cmo se definen los posibles targets para el compilador?. TargetCompilerRegistry es un
Singleton (Gamma01), cuya nica instancia de esta clase es creada por demanda. Dicha instancia es
configurada mediante un archivo de propiedades llamado pss_pmi_compiler.properties. En Java todos
los archivos de propiedades son simples archivos de texto. Dichos archivos representan un mapa con
entradas definidas por una clave y valor. Cada lnea que no sea un comentario, comienza con el valor de
la clave, seguida por un carcter =, finalizado con el valor de dicha clave. En este archivo debe existir

71

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

una entrada con el nombre registered, cuyo valor debe contener la lista de targets registrados en el
compilador. Por ejemplo: registered=transient, persistent. Por cada una de los targets registrados, tiene
que haber otra entrada en dicho archivo que contenga el nombre completo de la clase que implementa la
interfase TargetCompiler, para dicho target.
class compileGenerationLite
i nterface
TargetCompiler

AbstractGenerator

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

generateConstraintVali dations(process, homeBui lder, defi ni ti on, keyIdentifi er, stateNames) : voi d
generateCreateFour(process, homeBuil der, definition, methodDefi ni ti on) : voi d
generateCreateOne(process, homeBui lder, defi ni ti on, methodDefinition) : void
generateCreateThree(process, homeBuil der, defi niti on, methodDefi ni ti on) : voi d
generateCreateTwo(process, homeBui lder, defi ni ti on, methodDefinition) : void
generateFactoryMethod(process, homeBuil der, factoryMethodBuil der, definition, methodDefi ni ti on) : voi d
generateFinderMethod(process, homeBuil der, definition, methodDefi niti on, keyBui l der) : void
generateLifeCycl eListener(process, storageHome, definition, stateBuil der) : voi d
generateRead(process, buil der, defi nition, attribute) : void
generateReadRef(process, bui lder, defi ni ti on, attri bute) : voi d
generateReadWri te(process, storageTypeBuil der, bui lder, defi ni ti on, attri bute) : voi d
generateRefFi nderMethod(process, homeBui lder, defi ni ti on, methodDefini tion, keyBuil der) : voi d
generateStorageHome(process, storageHome, definition, isAbstract) : voi d
generateStorageObject(process, storageType, defi ni ti on, i sAbstract, properStates) : void
generateWrite(process, storageTypeBui l der, bui lder, defi niti on, attri bute) : void
generateWriteRef(process, storageTypeBuil der, bui l der, defini ti on, attri bute) : voi d
getCompi leInstance() : TargetCompi l er
getDescri pti on() : Stri ng
getName() : String
getTempl ates() : Compi lerTempl ates
i ni t(name, regi stry) : voi d

reali ze
HelperGenerator

Generati onTemplates

AbstractTargetCompiler

HolderGenerator

-tem plates

CompilerTemplates
{l eaf}

-i nstance
TargetCompilerRegistry
+
+
+
+
+

defaultOne() : T argetCom pi l er
forName(nam e) : TargetCom pil er
getInstance() : TargetCom pil erRegistry
getProperty(key) : String
getRegi stered() : Set<Stri ng>

configures
flow
pss_pmi _com pil er.properties

memory::
TransientTargetCompiler

persistent::
PersistentTargetCompiler

COMPILADOR 12 - CMO GENERARLO

L O QUE ES COMN A TODO SERVICIO


El modelo presentado anteriormente para la representacin un archivo fuente, permite que las
distintas implementaciones de TargetCompiler, no tengan que tratar directamente con la generacin de
los archivos. Dicho modelo es parte de mdulo que permite generar cdigo fuente mediante la utilizacin
de plantillas (templates) que en realidad no es parte del compilador. Este mdulo podra ser utilizado por
cualquier aplicacin Java que requiera generar archivos de cdigo fuente en forma dinmica.
En el grfico 12 se muestra la clase AbstractTargetCompiler. Su nico objeto es el de tener un
punto comn donde poner todas las partes que podran ser comunes a todo TargetCompiler, como por
ejemplo, todos los mtodos para acceder a los atributos que definen el estado en los objetos
almacenados. Todos estos mtodos comparten la definicin de los mismos, pero varan en su
implementacin. En este punto es donde entra en juego la clase CompilerTemplates.
CompilerTemplates, es una especie de registro donde se configura cual archivo de plantilla o
template, se utiliza para determinada operacin o mtodo. A simple vista podra pensarse que es
suficiente con tener diferentes plantillas para diferentes implementaciones de servicio, pero no es as. Por
ejemplo, muchas partes de las clases a generar requieren diferentes implementaciones de los mtodos en

72

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

funcin del tipo y cantidad de atributos persistentes que tengan los objetos almacenados. Esto requiere
que los mtodos sean construidos dinmicamente en funcin de lo que se este compilando.

G ENERACIN DE CDIGO PARA EL PRIMER EJEMPLO


Para mostrar como interactan todas estas partes, voy a continuar con el ejemplo de la fase
anterior, pero esta vez para esta tercera y ltima fase.
module ejemploFaseUno {
abstract storagetype Prueba {
state string nombre;
};
};

En el cdigo PSDL anterior, se define un objeto almacenado abstracto. Segn la especificacin


PSDL, en Java esto se traduce a una interfase Prueba, en el paquete ejemploFaseUno y con dos mtodos
que permitirn acceder al estado nombre, tanto como para lectura como escritura. Adicionalmente al
tratarse de una interfase, se deben generar los clases Helper y Holder, para la misma.
Esta fase parte de un proceso de compilacin (CompileProcess) ya validado, que se encuentra
listo para generar el cdigo resultante.

PASOS
1- Para cada uno de los builders registrados en el CompileProcess de llama al mtodo generate. En
este caso slo existe un builder registrado que representa al objeto almacenado abstracto. Y se
trata de un AbstractStorageTypeBuilder.
2- AbstractStorageTypeBuilder construir una instancia de InterfaceDefinition.
a. Para cada tipo heredado, se agregar una extensin a la definicin de la interfase construida.
Como en este caso, no se hereda de ninguna otra definicin, se agregar automticamente la
extensin de la interfase StorageObject.
b. Para cada estado definido en el tipo, se llamar al mtodo addTo, pasando como parmetro la
definicin de la interfase construida. Slo existe una definicin de estado nombre, que est
representada por un objeto StateMemberBuilder.
i. StateMemberBuilder en el mtodo addTo, como primer medida, determinar si se trata de
una definicin concreta o abstracta (como en este caso) para saber que tipo de mtodos se
deben generar. Construye una definicin de atributo (AttributeDefinition) con el nombre
del estado, luego llamar al mtodo addReadAccessorFor con el atributo construido.
ii. El mtodo addReadAccessor construye una instancia de MethodDefinition, en base al tipo
de objeto del atributo construido anteriormente. Adems le indica al TargetCompiler del
proceso que se est ejecutando, que le agregue un encabezado al mtodo construido. Este
encabezado ser a modo de comentario en sintaxis Java Doc. Si el mtodo debiera ser
implementado por tratarse de un tipo concreto, se llamara al mtodo generateRead del
TargetCompiler. De esta forma, TargetCompiler es el nico objeto que puede referenciar
partes dependientes del servicio de persistencia para el cual se est compilando.
Finalmente, StateMemberBuilder agrega el mtodo a la definicin.
iii. StateMemberBuilder llama al mtodo addWriteAccessorFor. De manera anloga a
addReadAccessor, se construye una definicin de mtodo. TargetCompiler le agrega un
encabezado y finalmente se agrega el mtodo a la definicin que se est construyendo.
c. Para cada operacin definida en el tipo almacenado se llama al mtodo addTo del builder
(OperationBuilder). En este caso no se han definido operaciones.
d. Finalmente, AbstractStorageTypeBuilder agrega al proceso la definicin de la interfase
construida, con el mtodo addGenerated, indicndole que se deben generar la clase Holder para
la interfase.

73

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

e. El mtodo addGenerated registra la definicin construida y le indica al HolderGenerator del


compilador que genere la clase Holder registrndola de igual forma en el proceso.
3- El CompileProcess toma cada una de las definiciones registradas y le indica al
CompilerDefinitionWriter del compilador que las escriba en el directorio destino mediante el
mtodo write. En el caso de este ejemplo, las definiciones registradas son dos, la interfase y la
clase Holder para la misma.
4- CompilerDefinitionWriter crea una instancia de FileBuilder con la definicin a escribir, llamando al
mtodo build.
a. El mtodo build de FileBuilder construye un PrintStream, en base a la definicin a construir y el
directorio donde se crearn las definiciones. En este caso, apuntar a un archivo llamado
Prueba.java, en el sub directorio ejemploFaseUno. El primer paso a escribir ser el encabezado
para el archivo con informacin del compilador y la fecha de generacin.
b. Luego se escribir el paquete Java al que corresponda el archivo, mediante la definicin de
paquete (PackageDefinition) del tipo a escribir.
c. Los imports del archivo son generados dinmicamente mediante el uso del patrn Visitor
(Gamma01). Los imports de un archivo en Java permiten utilizar referencias a clases slo con su
nombre sin tener que indicar el paquete. De esta forma si se importa el paquete java.util, se
podr hacer referencia a cualquier clase que est contenida en l, como por ejemplo Collection.
Con el patrn Visitor lo que se hace es recorrer todos los generadores de cdigo (que
implementen la interfase Generator) que constituyan la definicin a construir, pasando como
parmetro un objeto de tipo TypeDefinitionAppender. Cada generador de cdigo que utilice una
definicin de tipo, la registrar en este objeto. Al final del proceso, este objeto conoce todos los
tipos de objetos utilizados en el archivo y puede generar en forma ordenada y sin duplicados
todos los imports que requiera la clase. El otro beneficio, es que el builder del archivo puede
determinar en base a esto si necesita utilizar el nombre con el paquete de un tipo de objeto o
solo el nombre. Esto permite que los archivos generados por el compilador contengan solo los
imports requeridos por la clase, y adems que slo utilicen referencias absolutas a clases cuando
existan ambigedades con los nombres simples de las mismas (por ejemplo que se use una clase
String que est en otro paquete que no sea java.lang).
d. Finalmente, slo resta escribir la definicin en el PrintStream. Para ello todo Generator tiene un
mtodo writeYouSelfInto, que le permite escribirse a s mismo dentro del archivo.

CONCLUSIONES DEL COMPILADOR


El compilador cumple con el objetivo inicial de generar cdigo Java en base a un archivo PSDL de
entrada. Por la forma en que est construido, permite reutilizar el mismo ncleo para diferentes
implementaciones del servicio de estado persistente, tal como lo ejemplificar en la siguiente seccin.
El grado de reutilizacin que propone el compilador, obedece principalmente a dos razones: la
primera es lograr un alto grado de reutilizacin. Esta es una buena prctica cuando se desarrolla software,
dado que permite optimizar el trabajo. En segundo lugar, porque al momento de la construccin del
compilador no tena definido el servicio de estado persistente y al plantearlo como procesos separados
me permiti construir ambos en paralelo.
Antes de plantearme la posibilidad de construir el compilador, analic la posibilidad de extender
algn compilador IDL, pero la mayora de los compiladores (incluido el mo) tienen el mismo problema.
Los parsers son construidos con herramientas como Javacc que generan cdigo Java que es
prcticamente imposible extender o modificar (por su elevado costo de hacerlo manualmente) si no es
por medio de la herramienta, por lo que esta posibilidad qued descartada.

CONEXIN DEL SERVICIO DE PERSISTENCIA CON LA ORB


En CORBA todo servicio perteneciente a la especificacin se accede de la misma forma, mediante
una referencia inicial a la ORB. Por ejemplo, uno de los servicios ms utilizados, se llama NameService
(servicio de nombres), para acceder a este servicio se llama al mtodo resolve_initial_references del
objeto ORB, pasndole como parmetro el nombre del servicio que se quiere acceder:

74

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

ORB orb = .....;


Object objSrv = orb.resolve_initial_references(NameService);
NamingContextExt context = NamingContextExtHelper.narrow(objSrv);
El nombre del servicio es, por lo general, una cadena de caracteres bien definida por la
especificacin del servicio, en este caso se trata de NameService, mientras que en el caso del servicio de
persistencia se trata de PSS. A esta cadena de caracteres se la denomina objectId (identificador de
objeto).
La razn por la que los servicios son referenciados o accedidos por su nombre y no por un
mtodo es simple: los servicios que estn disponibles en la ORB dependen de la configuracin de la
misma y no de la definicin de ella. Los servicios de CORBA son contribuciones adicionales a la ORB que
pueden estar o no presentes en ella. Existen identificadores de objetos reservados por CORBA para
referenciar a los servicios bien conocidos (pg. 4-29 de CORBA01 de la especificacin) entre los que se
encuentran NameService y PSS, pero mediante este mecanismo se puede acceder a cualquier objeto que
est registrado como referencia inicial a la ORB.
La pregunta que se plantea aqu es cmo sabe la ORB que objeto le corresponde a cada
nombre?. La respuesta es parte de la especificacin de la ORB [CORBA01].

CONFIGURACIN DE LA ORB PARA EL ACCESO A SUS REFERENCIAS INICIALES.


La ORB provee referencias a estos objetos que sern recolectadas durante el proceso de
inicializacin. Los objetos pueden ser tanto referencias a objetos locales como remotos. En el caso del
servicio de persistencia, la referencia que se provee es una instancia de la clase
org.omg.CosPersistentState.ConnectorRegistry,
que
al
implementar
la
interfase
org.omg.CORBA.LocalInterface, se trata de una referencia local. Las referencias remotas son objetos que
residen en otra ORB que en general est en otra mquina. Bsicamente se resuelve pasndole la
representacin en forma de cadena de caracteres (string) a la ORB.
Las referencias locales son construidas mediante el uso de los interceptors (interceptores). Un
interceptor es un mecanismo que permite que los servicios de CORBA y otros objetos, puedan intervenir
en el procesamiento de la ORB. Estos interceptores son registrados en la ORB durante el proceso de
inicializacin de la misma. La interfase org.omg.PortableInterceptor.ORBInitializer permite definir un
interceptor que participar del proceso de inicializacin de la ORB. Existen otros interceptores que
permiten intervenir en otros procesos de la ORB, como la invocacin remota a un mtodo.
En la especificacin de la ORB para Java (CorbaJava00), este tipo de interceptores se registran
pasndole una propiedad como parmetro a la mquina virtual, con el siguiente formato:
org.omg.PortableInterceptor.ORBInitializerClass.XXX
, donde XXX ser el nombre completo de la clase que implementa ORBInitializer. Las propiedades se
pasan a la mquina virtual de Java anteponiendo D a la propiedad en la lnea de comando. Tambin se
admite definir estas propiedades como entradas en el archivo orb.properties.
El archivo orb.properties es la forma ms simple de configurar una instalacin Java que requiera
CORBA. La mquina virtual Java (JVM) contiene una implementacin completa de la ORB. Mediante el
archivo orb.properties se puede configurar, tanto la implementacin de ORB a utilizar, como por ejemplo
JacORB, como los servicios que estarn disponibles en la misma.

75

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class ORBInitialization
ConnectorRegistryOperations
org.omg.CORBA.LocalInterface
org.omg.CORBA.portable.IDLEntity

Object
interface
PortableInterceptor::ORBInitializer

interface

configures

orb.properties

flow

CosPersistentState::ConnectorRegistry

LocalInterface

realize
interface

org.omg.CORBA.LocalObject

pss::ConnectorRegistryInitializer

CosPersistentState::
_ConnectorRegistryLocalBase

+
+

post_init(ConnectorRegistry, Properties) : void


pre_init(ConnectorRegistry, Properties, String) : void

_ids() : String[]
pss_pmi_regi stry.properties
pss::ConnectorRegistryImpl

realize

configures
flow

+
+
+
+
+
+
+

ConnectorRegistryImpl()
find_connector(String) : Connector
is_registered(String) : bool ean
post_init(ORBInitInfo) : voi d
pre_init(ORBInitInfo) : void
register_connector(Connector) : Connector
unregister_connector(String) : void

_ConnectorLocalBase
connector::ConnectorBase

DISEO DEL SERVICIO 1 - CONFIGURACIN DE LA ORB

En el grfico anterior se muestran las partes que interactan para que el servicio de persistencia
de CORBA est disponible en la ORB. El proceso que permite al servicio de persistencia estar disponible
en la ORB es el siguiente:

REGISTRO DE CONECTORES PARA EL SERVICIO DE PERSISTENCIA


La ORB leer de la lnea de comandos o del archivo orb.properties la propiedad que identifica a
un inicializador:
org.omg.PortableInterceptor.ORBInitializerClass.ar.uba.fi.pmi.corba.pss.ConnectorRegistryImpl

, en este caso: ar.uba.fi.pmi.corba.pss.ConnectorRegistryImpl es la clase que representa al registro de


conectores del servicio de persistencia y es a su vez la puerta de entrada al servicio.
ConnectorRegistryImpl implementa la interfase ORBInitializer de CORBA. No es necesario que sea el
mismo registro el que implemente dicha interfase, podra ser cualquier objeto que sea capaz de generar
el registro, para luego registrarlo en la ORB, como una referencia inicial. Para simplificar opt por utilizar
el mismo registro como inicializador. ORBInitializer expone dos mtodos:
void pre_init (org.omg.PortableInterceptor.ORBInitInfo info);
void post_init (org.omg.PortableInterceptor.ORBInitInfo info);
, el primero identifica el comienzo de la etapa de inicializacin de la ORB y el segundo su fin. El
parmetro que reciben ambos mtodos es una instancia de la clase ORBInitInfo, la cul expone un

76

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

mtodo register_initial_reference(String, org.omg.CORBA.Object), que es el que permite indicarle a la


ORB que objeto representa la referencia inicial.
El registro de conectores permite acceder a los distintos conectores que estarn disponibles en
funcin de la configuracin de la instalacin. El proceso de registracin de un conector es similar al que
permite a la ORB registrar las referencias iniciales en forma dinmica. Por ello, opt por definir un
mecanismo muy similar para configurar el registro.
El registro es configurado, o bien, por variables pasadas por la lnea de comandos o por un
archivo de propiedades, que en este caso se llama: pss_pmi_registry.properties. El registro tomar las
propiedades que comiencen con el prefijo: PSSPMIConnector.:
PSSPMIConnector.ar.uba.fi.pmi.corba.pss.connector.TransientConnector=Transient

, en este caso se identifica el conector Transient. Cada vez que se le pida al registro, un conector
identificado por la cadena de caracteres Transient, se har referencia al conector provisto por la clase
ar.uba.fi.pmi.corba.pss.connector.TransientConnector. La nica condicin para estas clases es que
implementen la interfase:
ar.uba.fi.pmi.corba.pss.ConnectorRegistryInitializer:
public void pre_init(ConnectorRegistry registry, Properties initialzationProperties,
String creationProperty);
public void post_init(ConnectorRegistry registry, Properties initialzationProperties);

, como se aprecia, al igual que ORBInitializer expone dos mtodos que representan la fase de
inicializacin, en este caso, del registro de conectores. De forma anloga, el objeto que hace las veces de
inicializador del registro, no tiene por que ser el mismo que representa al conector. Sin embargo, para
simplificar opt por utilizar el mismo. Se espera que en la implementacin del mtodo post_init, se
registre un conector, mientras que el mtodo pre_init se utilice para recolectar y configurar toda la
informacin requerida por el conector a registrar. Existe una implementacin parcial de
ConnectorRegistryInitializer que puede ser utilizada como clase base para la implementacin de
cualquier conector.
De esta forma mi servicio de persistencia propone un mecanismo de configuracin que permite a
cualquier implementacin de conector, incorporarse al registro por medio de una configuracin.

IMPLEMENTACIN DEL SERVICIO PROVISTO POR DIFERENTES CONECTORES


Toda implementacin del servicio requiere de dos partes por lo menos. La primera es su
contribucin al compilador, que permita generar cdigo fuente para el servicio. La segunda es la parte
interna al servicio que ser utilizada en tiempo de ejecucin y que se presenta al usuario final como el
conector (org.omg.CosPersistentState.Connector). En esta seccin me focalizar en el conector
propiamente dicho.

EL CONECTOR DEL SERVICIO DE PERSISTENCIA

77

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class connector
interface
CosPersistentState::ConnectorOperations
~
~
~
~
~
~
~

Local Interface
interface
UnregistrableConnector
+

onUnregistered(regi stry) : void

create_basic_sessi on(access_mode, additi onal _parameters) : org.omg.CosPersistentState.Session


get_pi d(obj) : byte[]
get_short_pid(obj) : byte[]
impl ementation_id() : java.lang.String
register_session_factory(session_factory) : Class
register_storage_home_factory(storage_home_type_name, storage_home_factory) : Class
register_storage_object_factory(storage_type_name, storage_object_factory) : Cl ass

org.omg.CORBA.Local Interface
org.omg.CORBA.portabl e.IDLEnti ty

reali ze
_ConnectorLocalBase
ConnectorBase
+
+
+
+
+
+
+
+
+
+
+
+
+

i nterface
CosPersistentState::Connector

create_basi c_sessi on(access_mode, additional _parameters) : Session


get_pi d(obj ) : byte[]
get_short_pi d(obj ) : byte[]
getStorageHomeFactory(storage_home_id) : Class
getStorageObj ectFactory(storage_obj ect_id) : Class
implementation_i d() : Stri ng
onUnregi stered(registry) : void
post_i nit(registry, properties) : void
pre_i nit(registry, properti es, creationProperty) : voi d
register_session_factory(sessi on_factory) : Cl ass
register_storage_hom e_factory(storage_home_type_name, storage_home_factory) : Class
register_storage_obj ect_factory(storage_type_name, storage_object_factory) : Cl ass
toString() : String

TransientConnector
+

T ransi entConnector()

PersistentConnector
+
+

getConnection(sessi on, connectionParameters) : DataStoreConnection


PersistentConnector()

DISEO DEL SERVICIO 2 - CONECTORES

El grfico anterior muestra las principales clases que estn relacionadas con el conector. Mi
modelo de registro dinmico de conectores extiende la interfase Connector de CORBA mediante la
interfase: ar.uba.fi.pmi.corba.pss.connector.UnregistrableConnector. La cual permite que los conectores
registrados tengan un callback (llamada) representado por el mtodo onUnregistered, que les permite a
los conectores liberar los recursos que tengan utilizados, cuando la ORB donde se registr el conector,
finalice.
El hecho de que en Java las clases estn representadas por objetos de tipo java.lang.Class
simplifica enormemente el desarrollo. En Java solo se necesita de un objeto de tipo Class para poder
construir un objeto de dicha clase, mientras que en C++, la nica forma de construir una clase es
mediante una llamada explicita a un constructor de la misma mediante cdigo escrito por el
programador. Por esto, las definiciones IDL nativas que hacen referencias a Factory se traducen a objetos
Class en Java, mientras que en C++, se traducen a una clase concreta para cada factory.
La simplicidad del modelo de Java, me permiti crear una implementacin bsica de la interfase
Connector, que es la clase ar.uba.fi.pmi.corba.pss.connector.ConnectorBase y que es funcionalmente
completa. Sin embargo, esta clase est declarada como abstracta, dado que para poder funcionar
correctamente se requiere que el conector conozca el tipo de sesiones que debe crear. Aunque no es
obligatorio heredar de ella para implementar un conector, si es conveniente.
En el diagrama se muestran dos implementaciones del conector TransientConnector y
PersistentConnector, las cuales explico en detalle ms adelante. Bsicamente se trata de las dos
implementaciones que provee mi servicio de persistencia. La primera con soporte de persistencia en
memoria y la segunda en un repositorio persistente ante el reinicio del servidor.

78

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Ambos conectores heredan de la implementacin bsica del conector, agregndole el registro


automtico del tipo de sesin que utiliza cada una. Por registro automtico se entiende que el usuario no
necesita registrar la clase que se utilizar para crear sesiones.

O PERACIONES DEL CONECTOR


El conector es la puerta de entrada para el servicio de persistencia. Sus operaciones estn
definidas en la interfase ConnectorOperations. En el conector se debern registrar los tipos o clases que
estarn disponibles para el servicio en tiempo de ejecucin.
Class register_storage_object_factory(java.lang.String storage_type_name,
Class storage_object_factory);
Class register_storage_home_factory(java.lang.String storage_home_type_name,
Class storage_home_factory);
Class register_session_factory(Class session_factory);

Estos mtodos permiten registrar clases para diferentes propsitos en el conector. El primer
mtodo registra la clase que lo representa para un nombre de objeto almacenado. Para estos nombres se
adopta una nomenclatura similar que los nombres de IDL, o sea, la cadena de caracteres comienza con
PSDL:, es seguida por el nombre completo de la clase y finalmente por la versin de la misma. Por
ejemplo, para registrar la clase ar.fi.uba.pmi.corba.pss.test.Persona se deber utilizar un nombre:
PSDL:AR.FI.UBA.PMI.CORBA.PSS.TEST.PERSONA:1.0
, en este caso se registrar la versin 1.0 de la clase Persona.
Para simplificar la generacin de estos nombres proveo la clase ar.uba.fi.pmi.corba.pss.psdl
.PSDLUtils:
class connector

psdl::PSDLUtils
{l eaf}
+
+
+
+
~
+

getReposi toryID(entityClass) : String


getReposi toryID(entityClass, maj orVersion, mi norVersion) : String
getReposi toryID(packageNam e, entityNam e, m ajorVersion, minorVersion) : String
getReposi toryID(entityName, majorVersion, m inorVersi on) : String
PSDLUtils()
versionToString(majorVersion, m inorVersion) : Stri ng

DISEO DEL SERVICIO 3 - PSDLUTILS

, que permite generar los nombres en base a la clase que se quiera registrar.
El segundo mtodo register_ del conector es anlogo al primero, permitiendo registrar la clase
que representa un almacn para un nombre dado.
Y finalmente, el tercero de ellos permite registrar la clase que representa una sesin en el
conector. En general, se puede suponer que el conector conoce el tipo de sesiones que puede manejar,
sin tener que indicrselo programticamente. Sin embargo, no es cierto para las clases que representan
almacenes y objetos almacenados. En mi esquema, donde cada tipo de conector tiene su clase que lo
representa, este mtodo no sera necesario. Probablemente sera necesario, si se tiene una nica clase
Connector para todo conector. Al tratarse de un detalle de implementacin del mismo, no debera ser un

79

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

mtodo pblico del conector dado que el usuario final del servicio no tiene por que conocer cual es la
clase que representa la sesin.
El conector tiene, adems, las siguientes cuatro operaciones:
java.lang.String implementation_id();
byte[] get_pid(Object obj);
byte[] get_short_pid(Object obj);
org.omg.CosPersistentState.Session create_basic_session(
short access_mode, org.omg.CosPersistentState.Parameter[] additional_parameters);

El primer mtodo (implementation_id) devuelve el identificador con el que se encuentra


registrado el conector en el registro de conectores.
El segundo y tercer mtodo (get_pid, get_short_pid) permiten obtener a partir de un objeto
almacenado, el identificador que lo representa globalmente y localmente respectivamente, dentro del
almacn. Estos dos mtodos se utilizan generalmente en el esquema de trabajo de persistencia
transparente, donde los objetos que se persisten no tienen ninguna relacin con el servicio de
persistencia.
class Parameters
org.omg.CORBA.portabl e.IDLEntity
Parameter
{leaf}
+
+

nam e: j ava.lang.String = ""


val : org.omg.CORBA.Any

+
+

Param eter()
Param eter(java.l ang.Stri ng, org.om g.CORBA.Any)

pss::SessionParameterBuilder

#
+
#
+
+
+
+
+
+

appendParameter(String, Seriali zable) : Sessi onParameterBui lder


buil d(ORB) : Parameter[]
createAny(ORB, DynAnyFactory, M ap.Entry<String, Seri ali zabl e>) : DynAny
withFil eName(String) : Sessi onParameterBui lder
withHostNam e(String) : Sessi onParam eterBuil der
withPort(Integer) : SessionParam eterBuil der
withProperti esFi le(String) : Sessi onParameterBui lder
withUserNam e(String) : Sessi onParam eterBuil der
withUserPassword(Stri ng) : SessionParameterBuil der

connector::SessionParametersExtractor

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

getFil eName() : String


getHostNam e() : String
getParam s() : Map<Stri ng, Object>
getPort() : Integer
getUserNam e() : String
getUserPassword() : Stri ng
hasFi leNam e() : boolean
hasHostNam e() : boolean
hasPort() : bool ean
hasUserNam e() : boolean
hasUserPassword() : bool ean
isEmpty() : boolean
isRemote() : boolean
SessionParametersExtractor(Param eter[])
toM essage() : Message
toStri ng() : String

DISEO DEL SERVICIO 4 - PARAMETERS

Y por ltimo, el mtodo ms importante del conector (create_basic_session) es el que permite


generar una sesin de trabajo en el servicio de persistencia. Este mtodo requiere de dos parmetros, el
primero es el tipo de sesin a crear, que puede ser READ_ONLY o READ_WRITE. La primera slo permitir
lecturas sobre los objetos, y la segunda lectura y escritura. El segundo parmetro es un array de objetos
Parameter.
La funcin de estos parmetros es permitirle al conector acceder a la informacin necesaria para
generar la sesin. Por ejemplo, si se trata de una sesin que se guarda en disco, un parmetro podra ser
el nombre del directorio y archivo donde se almacena la sesin. Si el conector se conecta a un repositorio
remoto, podra ser el nombre de usuario y password necesarios para conectarse.

80

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

La clase Parameter est definida por dos atributos, el primero es el nombre del parmetro, y el
segundo es su valor, que est representado por un objeto de tipo org.omg.CORBA.Any. La clase Any se
define en CORBA como un contenedor de cualquier tipo de dato u objeto. Esta clase provee operaciones
para transportar el objeto que contenga como valor [CORBA01]. Para trabajar con los objetos de tipo Any
se requiere utilizar algn servicio de CORBA, como por ejemplo, el servicio DynAnyFactory [CORBA01]
(que es una referencia inicial a la ORB). Para mantener encapsulada la creacin y lectura de estos
parmetros proveo dos clases, la primera ar.uba.fi.pmi.corba.pss.SessionParameterBuilder, que
representa la realizacin del patrn de diseo builder de Gamma [Gamma01]. Esta clase captura los
parmetros necesarios para la creacin de la sesin y finalmente con el mtodo build construye un array
de objetos Parameter que podr ser pasado como parmetro, al mtodo create_session del conector.
La otra clase es ar.uba.fi.pmi.corba.pss.connector.SessionParametersExtractor, que permite
recuperar los valores de un array de objetos Parameter. Esta clase es usada internamente por el conector
para extraer los parmetros necesarios para la creacin de la sesin.
Es el tipo de conector quien define cuales nombres de parmetros aceptar (el atributo name de
la clase Any). Este tipo de pasaje de parmetros no restringe cuales son los parmetros vlidos y
requeridos por cada conector. Cada conector deber validar en tiempo de ejecucin, si los parmetros
recibidos son correctos o no, en caso de que no lo sean, lanzar una excepcin de tipo
org.omg.CORBA.PERSIST_STORE.
Tanto la clase que construye la lista de parmetros (SessionParameterBuilder), como la que la
procesa (SessionParametersExtractor), restringen los nombres y tipos de parmetros a los dos
conectores que conocen. Otro conector deber, o bien extender estas dos clases, o proveer otra forma de
generar los parmetros para s mismo.

PROBLEMAS QUE PRESENTA LA CREACIN DE UN CONECTOR


Antes de entrar en el detalle de cada uno de los conectores, voy a describir algunos de los
problemas generales que plantea la construccin de un conector.

C REACIN DE OBJETOS
El primer objeto que se necesita crear es la sesin de trabajo y el conector es el encargado de
crearla. En mi implementacin base del conector, la sesin se crea utilizando la clase registrada para tal
efecto. Se requiere solamente que dicha clase tenga un constructor sin parmetros. La clase registrada
debe heredar de la clase ar.uba.fi.pmi.corba.pss.catalog.SessionBase, tambin provista por m. Dicha
clase provee un mtodo initialize, que es llamado inmediatamente luego de la creacin del objeto por el
conector.

E L PATRN DE DISEO T EMPLATE M ETHOD

Todas las clases base que proveo exponen el comportamiento que deben proveer pero no lo
implementan completamente, es por ello que estn definidas como abstractas. El diseo de estas clases
sigue el patrn de diseo Template Method [Gamma01]. Dicho patrn permite definir un esqueleto de
una clase dejando mtodos que las subclases debern implementar para completar el comportamiento.
Estos mtodos son los llamados template. En el caso concreto de la clase SessionBase, el mtodo
initialize est declarado como final. Internamente initialize llama a otro mtodo protegido de la clase
denominado do_initialize (el template method). Las subclases deben sobrescribirlo, si lo requieren, para
poder realizar alguna inicializacin adicional tal como una conexin a la base de datos. El principal
beneficio del uso de este patrn es que permite un alto grado de reutilizacin de cdigo. En mi caso, me

81

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

permiti definir varias clases base que pueden ser utilizadas en distintas implementaciones de conectores
del servicio de persistencia.
En el diagrama que se muestra a continuacin se observan todos los template methods que
provee la clase SessionBase. Son todos aquellos que comienzan con el nombre do_xxx.
class ConnectorBases
_ConnectorLocalBase
C:extends ConnectorBase

connector::ConnectorBase

_SessionLocalBase
+
+
+
+
+
+
+
+
+
+
+
+
+

create_basic_session(short, Parameter[]) : Session


get_pid(Object) : byte[]
get_short_pid(Object) : byte[]
getStorageHomeFactory(String) : Class
getStorageObjectFactory(String) : Class
implem entation_id() : String
onUnregistered(ConnectorRegistry) : void
post_init(ConnectorRegistry, Properties) : void
pre_init(ConnectorRegistry, Properties, String) : void
register_session_factory(Class) : Class
register_storage_hom e_factory(String, Class) : Class
register_storage_object_factory(String, Class) : Class
toString() : String

catalog::SessionBase

C:extends ConnectorBase
H:extends AbstractStorageHomeBase
catalog::CommonSessionBase
#

hom es: Map<String, H> = CollectionFacto...

#
#
#
#
#
#
+

after_initialize(H) : H
afterCreateSO(SO) : void
createStorageObjectIdentifier(H, byte[], byte[]) : StorageObjectIdentifier
do_find_storage_home(String) : StorageHom eBase
getHom es() : M ap<String, H>
next_pid() : byte[]
register(SO, StorageObjectSpec, byte[], H) : SO

log: Log = LogFactory.getL... {readOnly}

+
#
+
#
#
#
+
#
#
#
#
#
#
#
+
+
+
+
#
+
+
+
+
+

access_m ode() : short


assertExist(Object, byte[]) : void
canWrite() : boolean
check_can_write(String) : void
check_not_closed(String) : void
checkInitialized() : void
close() : void
do_close() : void
do_find_by_pid(byte[]) : Object
do_find_storage_home(String) : StorageHomeBase
do_flush() : void
do_free_all() : void
do_initialize(C, Parameter[]) : SessionBase
do_refresh() : void
find_by_pid(byte[]) : Object
find_storage_home(String) : StorageHom eBase
flush() : void
free_all() : void
getAccessM ode() : AccessM ode
getConnector() : C
initialize(AccessM ode, C, Param eter[]) : SessionBase
isClosed() : boolean
refresh() : void
SessionBase()

DISEO DEL SERVICIO 5 - CONECTOR Y SESIONES

A LMACENES Y O BJETOS ALMACENADOS


Una vez creada la sesin se puede comenzar a trabajar con ella. Para poder trabajar con los
objetos, es necesario poder crearlos. Dentro del servicio de persistencia, los tipos de objetos que definen
los usuarios estn divididos en dos categoras, los almacenes y los objetos almacenados. La creacin de
estos dos tipos de objetos siempre est ligada a la sesin de trabajo. Una instancia de objeto pertenece
siempre a la sesin en la que fue creada.
En el modelo PSDL, los almacenes son siempre los encargados de la creacin de los objetos
almacenados. Entonces el siguiente problema a resolver, es: cmo obtener una referencia a una
instancia de un almacn dentro de una sesin?. La interfase org.omg.CosPersistentState.CatalogBase de
PSDL provee el mtodo:
StorageHomeBase find_storage_home(String storage_home_id) throws NotFound;
, que en base a un identificador de almacn (o nombre) permite obtener una referencia al almacn que lo
representa. Dos o ms llamadas consecutivas con los mismos parmetros al mtodo find_storage_home
deben devolver la misma instancia de almacn, dado que los almacenes son singletons [Gamma01]
dentro de una sesin. Esto requiere que la sesin adems de crear los almacenes, lleve un registro de
aquellos almacenes que fueron creados. Esta funcionalidad est provista de forma simple por una clase
llamada ar.uba.fi.pmi.corba.pss.catalog.CommonSessionBase, que contiene un mapa interno de los
almacenes creados en ella. Este comportamiento no est implementado en SessionBase, dado que es un

82

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

detalle de implementacin de la sesin y es muy probable que algunos conectores requieran de


mecanismos ms complejos para resolverlo.
Como el conector conoce la clase que le corresponde a un nombre, la clase SessionBase provee
una referencia al conector donde fue creada, permitindole a CommonSessionBase acceder a las clases
de almacenes para poder construirlos.

ALMACENES
En este punto cabe plantearse, qu implica crear un almacn? Siendo que los almacenes son
objetos que estn ligados lgicamente al repositorio donde fueron creados originalmente, ya que
almacenan objetos que pertenecen a un nico repositorio. Los almacenes creados en el contexto de una
sesin, son en realidad vistas de los almacenes existentes en el repositorio. Si dos sesiones estn
conectadas con el mismo repositorio debern obtener cada una, una instancia distinta del mismo
almacn. Entonces los almacenes creados son vistas que estn conectadas en tiempo de ejecucin a la
sesin donde fueron creados y mediante ella al repositorio que conecta la sesin.
Existe otra caracterstica de los almacenes que hacen complicada su creacin. Los almacenes
tiene una estructura jerrquica, o sea, dentro de una familia de almacenes, el primer almacn (la raz) en
la jerarqua es capaz de manejar cualquier objeto almacenado dentro de la misma jerarqua.
class storagehome hierarchy
StorageHomeBaseOperati ons
org.omg.CORBA.Local Interface
org.omg.CORBA.portabl e.IDLEnti ty

S:extends SessionBase
DH:extends ExtendedStorageHome
storageHome::AbstractChildStorageHome

i nterface
CosPersistentState::StorageHomeBase

#
#
#
+
#
+
+
+
#
#
+
#
#
#
#

AbstractChil dStorageHome()
afterDestroy(StorageObject) : voi d
beforeDestroy(StorageObject) : voi d
destroy(StorageObj ect) : voi d
destroyReference(StorageObj ect, String, byte[]) : voi d
exist(StorageObject) : bool ean
fi nd_by_short_pid(byte[]) : Object
fi nd_by_short_pid(ExtendedStorageHome, byte[]) : Object
fi nd_ref_by_spec(StorageObjectSpec) : byte[]
getDel egatee() : DH
home_fami ly_id() : Stri ng
i niti al izeChil dHome(S, String, String, String) : AbstractChi ldStorageHome
i niti al izeMe(S, Stri ng, DH, String) : AbstractChi ldStorageHome
i niti al izeRootHome(S, String, Stri ng) : AbstractChil dStorageHome
newSpec() : StorageObjectSpec

i nterface
storageHome::ExtendedStorageHome
+
+
+
+
+
+
+
+

bel ongs(Cl ass<T>) : bool ean


destroy(StorageObject) : void
exist(StorageObject) : bool ean
fi nd_by_short_pi d(ExtendedStorageHome, byte[]) : Object
getStorageType() : Cl ass<I>
home_famil y_i d() : Stri ng
i ni tial ize(Sessi on, Stri ng) : StorageHomeBase
registered_storage_home_id() : Stri ng

reali ze S:extends SessionBase


S:extends SessionBase
_StorageHomeBaseLocal Base
storageHome::
AbstractRootStorageHome

storageHome::
AbstractStorageHomeBase

DISEO DEL SERVICIO 6 - MODELO BASE DE ALMACENES

Lo anteriormente dicho y el hecho de que los almacenes son clases totalmente definidas y
construidas por el compilador PSDL, me llev a definir el siguiente modelo base para todo almacn que
pueda existir dentro de mi servicio de persistencia.
org.omg.CosPersistentState.StorageHomeBase es la interfase definida por CORBA como
almacn, la cual he extendido agregando operaciones adicionales mediante la interfase
ar.uba.fi.pmi.corba.pss.storageHome.ExtendedStorageHome. Estas operaciones me permitieron definir
el comportamiento requerido para cualquier almacn que exista dentro de mi servicio de persistencia. Se
trata de una interfase y no de una clase, ya que cualquier conector es libre de implementarla como

83

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

corresponda. De todas formas, yo he implementado algunas clases base de esta interfase para maximizar
la reutilizacin de cdigo entre mis dos implementaciones de conector. La clase
AbstractStorageHomeBase, es una implementacin base de dicha interfase. Adems, proveo otras dos
clases, que resuelven el problema de la jerarqua de almacenes y que son:
ar.uba.fi.pmi.corba.pss.storageHome.AbstractChildStorageHome
ar.uba.fi.pmi.corba.pss.storageHome.AbstractRootStorageHome
M ODELO DE D ELEGACIN
Estas dos clases resuelven el problema de la herencia de almacenes mediante la delegacin. La
jerarqua de los almacenes est parcialmente definida por el compilador. Si es el usuario quien define
algn almacn con operaciones, es l mismo quien es responsable de crear una clase que herede de la
clase provista por el compilador, quedando as fuera del control del compilador. Por otro lado, dentro de
una jerarqua pueden existir
mltiples nodos hijos, tal como
class Home Incomplete Hierarchy
muestra el grfico a la izquierda.
CompilerDefinedClasses
PersonStorageHome

VendorStorageHome

ClientStorageHome

UserDefinedClasses
ACMEPersonStorageHome

XXXVendorStorageHome

YYYClientStorageHome

En mi modelo, todos los


nodos de la jerarqua estn
conectados mediante el atributo
delegatee,
de
la
clase
AbstractChildStorageHome.
Cualquier almacn definido por el
usuario hereda de esta clase en
algn
punto.
El
mtodo
getDelegatee de la misma clase
devuelve el almacn que estar
encargado de resolver las
operaciones que requieran del
conocimiento del almacn raz.

Cual es objeto delegatee, ser


definido en tiempo de ejecucin
cuando se cree el almacn. El nico requisito para dicho objeto es que implemente la interfase extendida
de almacn propuesta por mi servicio: ExtendedStorageHome.
DISEO DEL SERVICIO 7 - DELEGACIN

Este modelo de delegacin simplifica el proceso de compilacin, ya que gran parte de las
operaciones que deben implementar los almacenes son delegadas y el compilador slo debe preocuparse
de generar las llamadas al almacn donde se delega. La diferencia entre un almacn que sea raz y otro
que no lo es, est dada por como es inicializado cuando es construido y por el almacn donde se delega.
En el caso que el almacn sea raz de la jerarqua, el almacn donde se delega es una instancia de
AbstractRootStorageHome. Por consiguiente, lo nico que debe considerar el compilador a la hora de
generar el mecanismo de inicializacin de cada almacn, es el mtodo de la superclase que debe llamar
para inicializar dicho almacn.
Este modelo contribuye a la simplicidad del compilador, ya que las clases que deben conocer los
conectores, estn limitadas a las provistas por ellos mismos y no a las clases definidas por los usuarios
mediante el lenguaje PSDL. La delegacin es una tcnica de POO, distinta de la herencia, que permite
tambin un alto grado de reutilizacin [BM0].

OBJETOS ALMACENADOS

84

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Los almacenes permiten acceder a los objetos almacenados, ya sea crendolos o recuperando
aquellos que fueron creados anteriormente. Dentro del servicio, los almacenes son los nicos objetos que
permiten crear objetos almacenados que puedan ser persistidos en un repositorio.
El mecanismo de delegacin es necesario tambin para la creacin de objetos, dado que el
compilador no sabe cuales clases sern las registradas por el usuario del servicio, como la que represente
al objeto almacenado para un determinado almacn. Se evita que el compilador genere cdigo para
construir objetos, generando solamente los mtodos que recolectarn los atributos necesarios para la
construccin del objeto almacenado.
Cuando se construye un objeto almacenado tambin existe el problema de su identidad. CORBA
provee dos formas de identificar un objeto almacenado. La primera es un identificador global dentro del
repositorio (Pid) y la segunda es un identificador dentro de la familia de almacenes a la que pertenece
(ShortPid). Los objetos almacenados pueden ser creados como entidades primarias, pero tambin existen
aquellos objetos almacenados que son parte de otros objetos almacenados que los contienen (Embedded
Storage Objects) como atributos (estado) de los mismos. En este ltimo caso, segn la especificacin de
CORBA, estos objetos almacenados no tendrn identidad propia, es decir que no tienen Pid ni ShortPid.
Dichos objetos se denominan Embedded o encastrados. Estos objetos embedded sern objetos creados
manualmente por el usuario y no por medio de un almacn.
class Extended Storage Obj ect
i nterface

Seriali zable

storageObject::StorageObjectSpec

i nterface
storageObject::StorageObjectIdentifier
+
+
+
+
+
+
-parent +
+
+
+
+
+

attach(Catal ogBase) : void


embed(String, ExtendedStorageObject) : voi d
equals(StorageObject, StorageObject) : boolean
equals(byte[], byte[]) : bool ean
get_pi d() : byte[]
get_short_pid() : byte[]
get_storage_home() : StorageHomeBase
is_destroyed() : boolean
is_embedded() : bool ean
refToStorageObject(byte[]) : StorageObject
set_destroyed() : voi d
storageObjectToRef(StorageObject) : byte[]

reali ze

interface
CosPersistentState::StorageObject
+
+
+
+
+

destroy_object() : voi d
get_pi d() : byte[]
get_short_pi d() : byte[]
get_storage_home() : StorageHomeBase
object_exists() : bool ean

real i ze
i nterface
storageObject::ExtendedStorageObject

storageObj ect::EmbeddedStorageObj ectIdentifier

+
+
+

get_i denti fi er() : StorageObjectIdentifi er


i ni tiali ze(StorageObjectIdenti fier, StorageObjectSpec) : voi d
i s_i ni tiali zed() : boolean

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

storageObj ect::BaseStorageObj ectIdentifier

addState(Stri ng, O) : void


count() : i nt
forEach(EntryProcessor) : voi d
get_bool ean(Stri ng) : boolean
get_byte(Stri ng) : byte
get_float(Stri ng) : float
get_i nt(Stri ng) : i nt
get_l ong(Stri ng) : l ong
get_reference(Stri ng) : byte[]
get_short(String) : short
get_storageObject(String) : S
get_string(Stri ng) : String
getSpeci fi cati onType() : Cl ass<? extends StorageObject>
getState(String) : O
hasVal ue(String) : bool ean
isAssi gnabl e(StorageObject) : bool ean
set_boolean(String, bool ean) : void
set_byte(String, byte) : void
set_float(Stri ng, fl oat) : voi d
set_i nt(Stri ng, int) : voi d
set_l ong(Stri ng, l ong) : voi d
set_reference(Stri ng, byte[]) : voi d
set_short(Stri ng, short) : void
set_storageObject(Stri ng, S) : voi d
set_stri ng(Stri ng, Stri ng) : void

real ize
storageObj ect::StorageObj ectSpecImpl

DISEO DEL SERVICIO 8 - OBJETOS ALAMACENADOS

Entonces los objetos almacenados presentan dos problemas, el primero es la creacin mediante
almacenes o como objetos embedded y el segundo es su identidad. Para tratar con estos problemas
propongo el esquema expuesto en el diagrama anterior.
En el centro del diagrama se muestra la interfase StorageObject provista por CORBA, la cual
debe ser implementada por todo objeto almacenado abstracto definido en PSDL. Yo he extendido dicha
interfase mediante: ar.uba.fi.pmi.corba.pss.storageObject.ExtendedStorageObject. Cualquier objeto
almacenado, ya sea embbeded o no, debe implementar StorageObject y en el caso de los embedded
prcticamente todos los mtodos de la interfase carecen de sentido. Mi interfase extendida agrega tres

85

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

operaciones que permiten trabajar con objetos almacenados que puedan ser utilizados tanto como
embedded o no. La nica restriccin que agrega mi servicio de persistencia para poder persistir objetos
almacenados, es que implementen esta interfase extendida, quedando a criterio de cada conector del
servicio, como hacerlo. Las operaciones extendidas que agrega mi interfase son:

boolean is_initialized();
void initialize(StorageObjectIdentifier identifier, StorageObjectSpec specification);
StorageObjectIdentifier get_identifier();
Estas operaciones presuponen que la creacin de un objeto en el contexto del servicio de
persistencia tiene dos etapas. La primera es la construccin fsica del objeto y la segunda una fase de
inicializacin del mismo. Cualquier objeto almacenado de mi servicio de persistencia, as sea embedded o
no, debe pasar por estas dos etapas. La diferencia radica en cmo y quin es el que inicializa el objeto.
El segundo mtodo (initialize) tiene dos parmetros. El primero parmetro es un identificador de
objeto y el segundo, una especificacin del objeto a inicializar. A continuacin voy explicar estos dos
conceptos fundamentales de mi servicio.
S TORAGE O BJECT S PEC
Esta interfase representa una especificacin de un objeto almacenado y se utiliza tanto para la
creacin como para la bsqueda de dichos objetos. La bsqueda ser explicada ms adelante. Es una
interfase de uso interno al servicio y los usuarios nunca deben lidiar con ella. Esta interfase provee la
informacin necesaria para construir o buscar un objeto almacenado, lo cul incluye tanto al tipo de
objeto (la clase) como los valores de los atributos que lo definen (estados). La clase
AbstractStorageHomeBase provee un mtodo newSpec, que permite crear un objeto que implementa
esta interfase. Este objeto puede ser
utilizado por los mtodos internos
public Two createNamed(String nameTwo, One one) {
generados por el compilador.
El
StorageObjectSpec spec = this.newSpec();
spec.set_string("nameTwo", nameTwo);
segmento de cdigo a la izquierda
spec.set_storageObject("one", one);
representa
un
factory
method
return (Two)this.create(spec);
[Gamma01] llamado createNamed de un
}
almacn generado por el compilador. Este
objeto almacenado tiene dos atributos
nameTwo y one que son pasados como parmetro al mtodo. La primer lnea crea una nueva
especificacin que en las siguientes lneas es cargada con los parmetros de entrada del mtodo.
Finalmente la creacin del objeto es delegada en el mtodo create que recibe tan solo la especificacin
de que debe crear. Esta forma de comunicacin simplifica y generaliza la lgica del compilador, ya que
toda la complejidad de la creacin del objeto est resuelta en la superclase y no en la clase generada por
el compilador.
S TORAGE O BJECT I DENTIFIER
La idea de un identificador de objetos es un concepto que agrega el servicio de persistencia de
CORBA. En el modelo de objetos de Java, los objetos no tienen identificadores. La identidad de los
objetos slo est garantizada a nivel de instancia. Para el operador == de Java, un objeto es igual a otro, si
y solo si, se trata de la misma instancia. Aunque Java tambin provee un mtodo equals (iguales en
ingls), que permite comparar dos objetos por algn criterio distinto de la instancia misma. De todas
formas para la clase Object de Java, el mtodo equals, solo devuelve verdadero cuando se trata de la
misma instancia. Si se quiere utilizar otro criterio de comparacin, las clases deben redefinir dicho
mtodo.

86

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

La interfase StorageObjectIdentifier est encargada de tratar con la identidad de los objetos,


tanto para los embedded como para los comunes, dentro del contexto de una sesin. Se trata igualmente
de una interfase interna al servicio y que los usuarios nunca utilizarn directamente.
Es recomendable que los compiladores para cada conector, generen un mtodo equals en los
objetos raz de la familia que delegue en su identificador la comparacin con otro objeto.
En mi interfase extendida ExtendedStorageObject, se puede apreciar que el primer parmetro
del mtodo initialize es una instancia de dicha interfase. Cada conector decide como implementar la
interfase. Por lo general, este objeto pasar a ser un atributo del objeto almacenado luego de la llamada
al mtodo initialize, mientras que la especificacin ser descartada, ya que slo se utiliza para inicializar
los valores de los atributos que son los estado del objeto almacenado que se est inicializado.
Algunas de las operaciones que expone esta interfase son:

public byte[] get_pid();


public byte[] get_short_pid();
public StorageHomeBase get_storage_home();
public void set_destroyed();
public boolean is_destroyed();
public boolean is_embedded();
public void embed(String attribute_name, ExtendedStorageObject storageObject);
public boolean equals(StorageObject source, StorageObject target);
public boolean equals(byte[] sourceReference, byte[] targetReference);
public void attach(CatalogBase catalog);

Los primeros cinco mtodos son importados de la interfase StorageObject. Esto permite que el
compilador delegue la implementacin de la interfase StorageObject en el atributo que represente al
identificador del objeto almacenado. Los siguientes dos mtodos, permiten tratar a un objeto
almacenado como embedded. El primero indica si el objeto identificado por este objeto es un objeto
almacenado embedded. El segundo le permite a un objeto almacenado inicializar a otro objeto
almacenado que representa un atributo embedded en l. Luego de llamar a este mtodo, el objeto
storageObject, quedar marcado como embedded dentro del objeto identificado.
Los ltimos tres mtodos son tiles para tratar con copias/instancias de los objetos que fueron
persistidos en el repositorio. Los dos primeros mtodos comparan objetos almacenados por sus
identificadores y el ltimo permite conectar una instancia de objeto almacenada con el catalogo o sesin
donde existe o ser utilizado. Esta ltima operacin es necesaria, ya que cuando una instancia es
recuperada de un repositorio persitente es cuando se puede determinar a que catlogo pertenece. Esta
informacin solo es til para una instancia de objeto activa dentro de un catlogo, por lo que no debe ser
persistida en el repositorio.

O PERACIONES DE BSQUEDA DE O BJETOS


CatalogBase::
StorageHomeBase find_storage_home(in string storage_home_id) raises (NotFound);
StorageObjectBase find_by_pid(in Pid the_pid) raises (NotFound);
StorageHomeBase::
StorageObjectBase find_by_short_pid(in ShortPid short_pid) raises (NotFound);

87

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

El otro problema que tienen que resolver los conectores y tambin el servicio en s mismo, es la
bsqueda de objetos. La bsqueda implica encontrar los objetos almacenados y los almacenes que ya
fueron creados previamente en el servicio. La especificacin de CORBA define algunas operaciones de
bsqueda estndar, tales como las expuestas en el cuadro anterior. Estas operaciones son relativamente
simples de resolver. La bsqueda de almacenes se limita a buscar en un ndice de almacenes creados
dentro de una sesin y si no existe, crearlo acorde al registro de almacenes. Esta funcionalidad est
implementada en la clase CommonSessionBase vista anteriormente. Las dos operaciones siguientes
dependen del conector.
Existe un tipo de operaciones de bsquedas ms complejas. Son aquellas que se definen
automticamente al definir claves dentro de un almacn. Cada definicin de clave define implcitamente
dos operaciones de bsqueda por los atributos que conforman la clave. La primera busca el objeto
almacenado y la segunda una referencia al objeto que est identificado por la clave.
S find_by_key_name(<parameter_list>) raises (CosPersistentState::NotFound);
ref<S> find_ref_by_key_name(<parameter_list>);

Estas operaciones requieren que los conectores provean una forma eficiente de realizar
bsquedas genricas por atributos de los objetos almacenados dentro de un almacn particular. Deben
ser genricas, ya que los conectores no conocen las claves que pueden definir los almacenes en tiempo
de diseo. Ms adelante explicar como cada conector en particular, resuelve estas operaciones.
Estas operaciones de bsqueda son necesarias en el momento de creacin de los objetos
almacenados para poder garantizar la unicidad de las claves.

V ALIDACIN DE C LAVES
La especificacin de CORBA define el concepto de clave, su significado y el cdigo que se genera
en cada lenguaje. No especifica el comportamiento esperado. Por ejemplo, las claves definen la unicidad
de los objetos dentro de un almacn o familia de ellos, pero no se especifica que sucede cuando no se
cumple la restriccin que impone alguna de las claves, ni tampoco, cuando deben verificarse estas
restricciones.
Dado que la especificacin es particularmente amplia en este sentido, he optado por definir un
mecanismo de validacin de las claves que puede ser disparado en diferentes momentos. Los conectores
pueden optar por redefinir o extender este comportamiento segn sus necesidades, definiendo cuando
ser utilizado. El modelo base obliga a que se verifiquen las claves cada vez que se construya un objeto,
generalmente, sern necesarias verificaciones adicionales.
Las cuatro clases representadas en el diagrama siguiente, modelan el comportamiento necesario
para la validacin de las claves definidas por una familia de almacenes. StorageHomeKeySet es una clase
abstracta cuyo objeto es el de recolectar el conjunto de claves, cada una representada por la interfase
StorageHomeKey, definidas por una familia de almacenes. Para ello cuentan con el soporte de la clase
StorageHomeKeyBuilder (patrn de diseo Builder [Gamma01]), que permite construir las claves definida
en los almacenes.
La clase AbstractStorageHomeBase define el mtodo:
protected void collectKeys(StorageHomeKeySet keySet)
, que se deber ser sobrescrito en cada uno de los almacenes que defina al menos una clave.

88

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class storageHome
StorageObjectSpec

H:extends ExtendedStorageHome

interface
StorageHomeKey

StorageHomeKeySet
+
+
+
+

getOri ginalSpec() : StorageObjectSpec


keyBuilder(nam e) : StorageHomeKeyBuilder
StorageHomeKeySet(spec)
validate(operati on, home) : void

getName() : String

-set

real ize
StorageObjectSpecImpl
StorageHomeKeyImpl

StorageHomeKeyBuilder
+
+

+
+
+
+

bui ld() : void


with(state) : StorageHomeKeyBuilder

getNam e() : String


StorageHom eKeyImpl(spec, name)
StorageHom eKeyImpl(type, name)
toString() : String

DISEO DEL SERVICIO 9 - RESTRICCIONES DE CLAVES

El cdigo que se muestra a


la izquierda representa
como un almacn agrega
una
clave
compuesta
nicamente por el atributo
name. La implementacin
del mtodo collectKeys, es
generada por el compilador y el usuario nunca debe hacer uso de l directamente, por eso se trata de un
mtodo declarado como protegido.
protected void collectKeys(StorageHomeKeySet keys) {
super.collectKeys(keys);
///////// Key: name
StorageHomeKeyBuilder keyname = keys.keyBuilder("name");
keyname.with("name");
keyname.build();
}

La clase StorageHomeKeySet no implementa el mtodo valdate. Cada conector ser


responsable de extender dicha clase proveyendo el mecanismo de validacin para cada clave definida
dentro de la familia de almacenes.
En el caso concreto de la creacin de un objeto, el mtodo mencionado anteriormente, ser
llamado por el mecanismo de creacin de objetos almacenados dentro de cada almacn.

D ESTRUCCIN DE OBJETOS ALMACENADOS


Otro punto donde la especificacin es particularmente amplia, es que sucede en el momento de
destruir o eliminar objetos con los objetos que referencian al objeto que se est eliminando.
La especificacin solamente indica que debe hacerse con las referencias de un objeto que es
eliminado. Las referencias a objetos de tipo embedded son directamente destruidas junto con su padre y
las referencias por identificadores son destruidas cuando estn declaradas como strong o fuertes.
Siguiendo el modelo de delegacin, he optado por centralizar las operaciones de destruccin de
los objetos en los almacenes, dado que es el almacn, en definitiva, quien tiene ms informacin sobre el
estado de los objetos y es realmente la nica clase que debe ser generada completamente por el
compilador. Por ello, el mtodo destroy_object de la interfase StorageObject, es implementado por el
compilador mediante delegacin en el almacn al que pertenece el objeto. La clase base
AbstractChildStorageHome define los siguientes mtodos para la destruccin de los objetos
almacenados:

89

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

public final void destroy(StorageObject storageObject)


protected void beforeDestroy(StorageObject storageObject)
protected void afterDestroy(StorageObject storageObject)

El mtodo destroy est definido en mi interfase extendida de almacn. Se trata de un mtodo


declarado final en esta clase, usando el patrn de diseo Template Method [Gamma01]. Los mtodos
beforeDestroy y afterDesctroy son, en este caso, los template methods. Los almacenes que hereden de
esta clase, debern redefinirlos para marcar como destruidas a aquellas referencias que estn declaradas
como fuertes en los objetos almacenados que manejen.
En el momento de la destruccin de los objetos, el identificador es marcado como destruido por
el almacn mediante la interfase StorageObjectIdentifier. Los identificadores de las referencias a objetos
de tipo embedded tienen su estado definido por medio del estado del identificador del objeto al que
pertenecen, por lo que estas referencias quedan automticamente destruidas.

DIFERENTES CONECTORES
Ya mencion anteriormente que he construido dos conectores del servicio de persistencia. La
razn principal para ello es la forma que he desarrollado el servicio. El primer conector que provee
persistencia temporal, es la implementacin ms simple que cumple con todos los requerimientos del
servicio. Este conector se us para construir el servicio y el compilador a la par.

C ONECTOR DE PERSISTENCIA TEMPORAL


Este conector permite evaluar y comprender las funcionalidades de cualquier servicio de
persistencia. La limitacin que tiene es que su estado es vlido mientras la sesin est activa. Sin
embargo, es funcional y puede ser usado siempre y cuando los requerimientos lo permitan.
class General Schema
ExtendedStorageHome
AbstractTargetCompil er

interface

memory::
TransientTargetCompiler

memory::TransientStoragetHome
+
+

do_after_create(SO, StorageObjectSpec, Transi entStoragetHome) : SO


find_ref_by_spec(StorageObjectSpec, Transi entStoragetHome) : byte[]

StorageHomeKeySet
memory::TransientStorageHomeKeySet
realize

reali ze

val idate(String, T ransientStorageHomeBase) : void

AbstractRootStorageHome
memory::
TransientRootStorageHome
{leaf}

AbstractChildStorageHome
memory::TransientStorageHomeBase
+
+
+

do_after_create(SO, StorageObjectSpec, T ransientStoragetHom e) : SO


fi nd_ref_by_spec(StorageObjectSpec, T ransientStoragetHom e) : byte[]
T ransientStorageHom eBase()

CommonSessionBase

+
+

dettach(StorageObject) : void
T ransientSession()

ConnectorBase

ExtendedStorageObject

catalog::TransientSession

connector::
TransientConnector

interface
memory::TransientStorageObject
+

matches(StorageObjectSpec, int) : boolean

T ransientConnector()

DISEO DEL SERVICIO 10 - ESQUEMA GENERAL DEL CONECTOR TEMPORAL

El diagrama anterior muestra el esquema general de las clases que componen al conector. Todo
conector debe proveer una contribucin al compilador para que este pueda generar cdigo para l. La

90

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

contribucin consiste en la clase TransientTargetCompiler, junto con las plantillas de cdigo que utilizar
el compilador para generar el cdigo fuente.
El compilador requiere, adems, que la contribucin sea registrada en su archivo de configuracin
(pss_pmi_compiler.properties):
registered=transient
transient=ar.uba.fi.pmi.corba.pss.psdl.compiler.memory.TransientTargetCompiler
transient.templateProperties=psdl_transient_templates.properties
El conector debe tener su registro en el servicio de persitencia, con una clase que implemente la
interfase ConnectorRegistryInitializer. La interfase est implementada por el conector mismo, y es:
ar.uba.fi.pmi.corba.pss.connector.TransientConnector
El conector se registra en el archivo pss_pmi_registry.properties, mediante la siguiente lnea:
PSSPMIConnector.ar.uba.fi.pmi.corba.pss.connector.TransientConnector=Transient
Habiendo agregado esta ltima lnea, el conector ya est listo para ser utilizado en tiempo de
ejecucin.

F UNCIONAMIENTO
La funcionalidad del conector est provista mayormente por la sesin de trabajo que provee. La
clase que representa una sesin en el conector temporal es TransientSession. Esta clase hereda de la
implementacin base de la sesin mencionada anteriormente: CommonSessionBase, que resuelve la
administracin de almacenes de una manera simple, por lo que lo nico que le queda resolver es la
construccin y manejo de objetos almacenados.

MANEJO DE IDENTIFICADORES
El primer problema que se necesita resolver, para la creacin de objetos almacenados, es la
asignacin de identificadores de objeto, tanto para el Pid como para el ShortPid. La especificacin indica
que para Java los identificadores se traducen en un byte[], lo cual hace complicada su manipulacin
directa. Para la generacin de identificadores que estn representados por un byte[], proveo la interfase
ByteArraySequencer, que permite obtener secuencias de identificadores en dicho formato.
class utils
interface
ByteArraySequencer
~

next() : byte[]

realize
SimpleByteArraySequencer
+
+
+

BinaryUtils

next() : byte[]
use
Sim pleByteArraySequencer()
Sim pleByteArraySequencer(initialValue)

+
+

bytesT oLong(bytes) : long


longT oBytes(num) : byte[]

DISEO DEL SERVICIO 11 - GENERACIN DE IDENTIFICADORES

La implementacin ms simple de este secuenciador es SimpleByteArraySequencer, que se


limita a incrementar un nmero de tipo long, y traducirlo a su representacin binaria mediante la clase

91

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

BinaryUtils. La sesin del conector tiene una instancia de esta clase para generar los identificadores
globales (Pid) de los objetos almacenados y a su vez cada familia de almacenes que se use en la sesin,
tendr otra instancia de este tipo de secuenciador.

ALMACENES TEMPORALES
El conector temporal extiende la interfase de almacn de CORBA mediante
TransientStoragetHome. Esto implica que todo almacn generado por este conector deber implementar
dicha interfase. Existen dos clases base la implementan que son: TransientRootStorageHome y
TransientStorageHomeBase. La primera representa la raz de una familia de almacenes y la segunda la
clase base para todo almacn generado por el compilador de este conector. El modelo de almacenes
temporales sigue el modelo de delegacin propuesto inicialmente por mi servicio.
Cada almacn raz de una familia de almacenes tiene un atributo SimpleByteArraySequencer,
que es utilizado para generar los identificadores objeto (ShortPid).
Para mantener los objetos almacenados dentro de la sesin cada almacn raz tiene un mapa
donde almacena los objetos que fueron creados durante la sesin. Dicho mapa est indexado por el
identificador ShortPid.

OPERACIONES DE BSQUEDA
La clase AbstractChildStorageHome define el mtodo:
protected abstract byte[] find_ref_by_spec(StorageObjectSpec spec);
, que permite buscar una referencia a un objeto almacenado que cumpla con la especificacin dada. Los
conectores deben implementar dicha operacin. En el caso de este conector, la implementacin ms
simple es iterar sobre todos los objetos almacenados dentro de la familia del almacn, representados por
los valores del mapa de la raiz y verificando si alguno de ellos cumple con la especificacin dada. Para ello,
la interfase TransientStorageObject, define el mtodo matches, que permite determinar si el objeto
almacenado cumple con la especificacin dada.
Cualquier operacin de bsqueda en este conector se traduce en construir una especificacin
con los atributos que se estn buscando, para luego llamar al mtodo find_ref_by_spec del almacn
donde se realizar el proceso anteriormente descrito.
La clase TransientStorageHomeKeySet es la encargada de realizar las validaciones de claves. Esta
clase utiliza el mismo mecanismo de bsqueda para buscar referencias a objetos que cumplan con la
definicin de la clave.

C ONECTOR DE PERSISTENCIA DURABLE


Si bien el conector temporal es funcional, muchas veces carece de utilidad prctica. En general,
lo que se busca con el concepto de persistencia es que sea prolongada en el tiempo e independiente de la
vida del proceso donde se cre al objeto. Por esto, mi servicio de persistencia provee otro conector que
cumple con este objetivo de persistencia durable.
Persistencia durable implica que la informacin debe ser almacenada en un repositorio
permanente y no voltil.

R EQUERIMIENTOS PARA UN CONECTOR DE PERSISTENCIA DURABLE


El primer requerimiento es que permita almacenar objetos. Las operaciones debern ser
perdurables, si se crea un objeto en una sesin, al cerrarla y abrir una nueva, se espera que el objeto siga

92

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

existiendo en la nueva sesin. Todas las operaciones de consulta definidas por el servicio de persistencia
deben tambin estar soportadas. Y las claves definidas en el modelo debern ser igualmente respetadas.
El repositorio deber permitir ms de una conexin o sesin concurrente.
Es importante recalcar que el servicio de persistencia de CORBA no tiene el objeto de reemplazar
una base de datos, por lo general los repositorios no contendrn una gran cantidad de objetos.
El acceso remoto al repositorio es un adicional, ya que el servicio de persistencia no lo impone
como requerimiento, aunque si constituye una cualidad muy til.
Antes de entrar en los detalles de mi conector persistente, voy a realizar un anlisis de las
distintas alternativas que consider para lograr persistencia durable.

D ISTINTAS ALTERNATIVAS PARA OBTENER PERSISTENCIA DURABLE


PERSISTENCIA MEDIANTE ARCHIVOS
La alternativa ms primitiva es uno o ms archivos almacenados en el sistema de archivos del
sistema operativo. Esta forma de lograr persistencia tiene como ventaja que no requiere nada ms que el
conector para funcionar, dado que Java provee los mecanismos necesarios para utilizar archivos. Las
principales desventajas son: que requiere la construccin de mecanismos de indexacin para acceder de
manera eficiente a el o los archivos, se debe hacer una traduccin entre los objetos almacenados y el
formato de registro que se utilice en el archivo, se debe construir un mecanismo que permita el acceso
concurrente del archivo si es que se permite abrir ms de una sesin por vez, y el acceso remoto a los
archivos requiere de algn soporte externo al servicio tal como el protocolo NFS (Network File System o
Sistema de Archivos en Red).
Java provee una forma estndar para almacenar objetos en archivos, denominada Serialization.
Este mecanismo permite almacenar en un archivo uno o ms objetos junto con todas sus referencias.
Podra ser una alternativa vlida, siempre y cuando se pueda garantizar que exista memoria suficiente
para mantener el respositorio de objetos, y no se requiera acceso concurrente al repositorio (en este
caso, el archivo serializado). Esta forma de almacenamiento podra pensarse como una extensin del
conector de memoria, donde la sesin de trabajo se almacena en un archivo, al momento de cerrase la
sesin.
Este modelo no requiere de mucho trabajo extra, ya que el nico requerimiento que Java
impone para que un objeto puede ser serializado, es que el mismo implemente la interfase:
java.io.Serializable. Dicha interfase sigue el patrn de diseo Marker Interface [GrandM01] o interfase
marcadora. En este patrn, la interfase marcadora, que no declara mtodos ni atributos, determina que
la clase que la implementa, cumple con una condicin lgica (implementarla representa verdadero). En el
caso de Serialization, una clase que implemente Serializable, indica que el mecanismo de Serialization
debe considerar los objetos de dicha clase durante el proceso de serializacin.
En conclusin, si slo se necesita la funcionalidad del conector de memoria con persistencia
durable, Serialization es una buena alternativa.

PERSISTENCIA MEDIANTE UNA BASE DE DATOS RELACIONAL


Una forma de hacer un repositorio accesible en forma remota y concurrente, es mediante una
base de datos. Las bases de datos ms difundidas son las relacionales.
PSS est basado en SQL3, que es una extensin al modelo relacional soportado por el SQL
tradicional. El problema que surge al utilizar una base de datos relacional, es que lo que se quiere

93

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

almacenar en este caso, no son datos relacionales, sino un modelo de objetos. Se requiere una
transformacin bidireccional entre los objetos y el modelo relacional de tablas y registros.
Las bases de datos relacionales utilizan el lenguaje de consulta SQL. Las consultas deben
realizarse sobre un modelo que las soporte. Dicho modelo deber ser generado por el compilador y ms
especficamente, por la contribucin del conector persistente relacional al compilador. Si bien el lenguaje
de consultas es generalmente estndar, para todas las bases de datos, el lenguaje de definicin del
modelo (DDL o Data Definition Language) no lo es. Esto implica que no slo se deber construir un
conector para bases de datos relacionales, sino que el conector deber considerar cual es la base de
datos que se quiere utilizar.
Dado que el compilador ser quien defina el modelo relacional a utilizar, se requiere entonces
que dicho modelo sea creado en la base de datos propiamente dicha. Hasta que no est creado el
modelo, no se podr utilizar el servicio de persistencia con el conector. Se agrega entonces un paso
posterior a la compilacin, para poder utilizar el servicio de persistencia.
Existen herramientas o bibliotecas que simplifican el uso de bases de datos relacionales para la
persistencia de objetos. Tal es el caso de: Hibernate [KingG01], Castor[Castor01], Toplink[Toplink01],
JDO [RoodsR01], entre otras. Son denominadas genricamente ORM (Object-relation Mapping) o mapeo
de objeto-relacin.
En estos modelos, por lo general, una instancia de una clase particular representa un registro en
una o ms tablas, dependiendo de la jerarqua de la clase. Cada atributo persistente de la clase est
representado por una o ms columnas en una tabla. Todas ofrecen un mecanismo de consulta de alto
nivel, que termina generando consultas SQL con las que se interacta con la base de datos. De esta
forma, el usuario no est obligado a tratar en forma directa con SQL. Algunas de estas herramientas
resuelven las diferencias de sintaxis particular de DDL para cada base de datos mediante mecanismos de
extensin por el usuario y otras slo funcionan con algunas bases de datos fijas. La relacin entre el
modelo de objetos y el modelo relacional, el mapeo de objetos, est definida, por lo general, en una
configuracin en forma de archivo XML, aunque algunas de ellas soportan este mapeo a travs de
anotaciones en las clases Java [Annotations01].
Algunas herramientas como Hibernate o Toplink, soportan persistencia transparente, de forma
tal que no imponen restricciones o requerimientos sobre las clases que se pueden persistir. A este tipo de
persistencia se lo llama genricamente POJO (Plain Old Java Objects o Viejos y simples objetos Java)
dado que cualquier objeto comn Java puede ser persistido. JDO, en cambio, requiere de un poscompilador, que modifica las clases generadas por el compilador para que puedan ser persistidas.
O bien mediante el uso de alguna herramienta como las mencionadas, o mediante la
construccin de otra herramienta, un conector para una base de datos relacional es perfectamente
viable.
El principal problema del uso de una base de datos relacional, es tener que coexistir con dos
modelos distintos, pero que representan lo mismo [NewardT01]. Es necesario crear otro modelo
(relacional) anlogo al modelo de objetos. Si se cambia el modelo de objetos, se debe cambiar el modelo
relacional, cada vez que se guarda un objeto se debe traducir al modelo relacional y cuando se lee del
modelo relacional se debe volver a transformar en objetos.
Otro punto a considerar es que el modelo en la base de datos relacional es visible al usuario, esto
expone los detalles de la implementacin del conector. Lo que tambin podra fomentar que el usuario
interactu con el modelo relacional directamente, creando as una dependencia con la implementacin

94

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

del conector. Esta dependecia de la implementacin viola las polticas de CORBA y de la especifcacin del
servicio de estado persistence.

PERSISTENCIA MEDIANTE UNA BASE DE DATOS ORIENTADA A OBJETOS


Si lo que se quiere guardar son objetos: por qu no guardar objetos directamente? Por qu es
necesario transformar los objetos a otro modelo? Por qu no simplemente utilizar una base de datos
orientada a objetos?
Cuando se comparan las bases de datos orientadas a objetos con las relacionales, comnmente
se realiza la siguiente analoga:
Si la base de datos fuera un garaje, y los datos fueran un auto, en una base de datos orientada a
objetos simplemente se estaciona el auto, mientras que en una base de datos relacional cada vez que se
quiere estacionar el auto, se requiere desarmarlo es sus piezas elementales. [CKA01]
En el contexto del servicio de persistencia, son mnimos los requerimientos que se tiene sobre
una base de datos orientada a objetos. Bsicamente, que permita almacenar objetos y para luego poder
buscarlos. Los requerimientos particulares del modelo de objetos que propone el servicio, tales como los
almacenes y objetos almacenados, junto con sus identificadores en forma de array de bytes, son
agregados al modelo de objetos de Java y no tienen porque estar soportados por una base de datos
orientada a objetos.
En conclusin se requiere: una base de datos que soporte una cantidad de objetos no tan
grande, consultas no tan avanzadas, junto con acceso remoto y que sea de uso libre. Esta base de datos
debe soportar el modelo de objetos Java, correr en diversos entornos (tal como lo hace Java),
preferiblemente estar desarrollada en Java, para no estar ligado a una plataforma especfica.
No son muchas las bases de datos orientadas a objetos que cumplen con estos requerimientos.
La nica que cumple con todos ellos es: DB4O [DB4O01]. Existe otra base que cumple parcialmente con
estos requerimientos llamada Cach [Cache01], pero no posee una licencia de cdigo abierto y solamente
est disponible para algunas plataformas como Windows y Linux.
Considerando las dos alternativas de base de datos, he optado por utilizar DB4O.
DB4O
DB4O o Data Base For Objects, sus siglas en ingls, que significan Base de datos para objetos. Se
trata de una base de datos orientada a objetos nativa, dado que no est implementada sobre una base de
datos relacional. Est desarrollada con licencia de cdigo abierto de tipo GPL (GNU General Public
License).
Existen dos versiones, una para Java, y otra para .NET. Ambas permiten ser incrustadas en el
sistema que las use. Esto hace que no imponga ningn requerimiento adicional a mi servicio de
persistencia, ms all de la propia biblioteca que ser incrustada en el servicio. Soporta acceso remoto,
transacciones y consultas avanzadas.
ACCESO A LA BASE DE DATOS
El acceso a la base de datos se realiza mediante la clase com.db4o.Db4o. Esta clase hace las
veces de fbrica o factory [Gamma01], de conexiones a la base de datos. Todas las operaciones son
realizadas mediante mtodos estticos en dicha clase.

95

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class db4o

Db4o

+
+
+
+
+
+
+

configure() : Configuration
licensedTo(String) : void
main(String[]) : void
openClient(String, int, String, String) : ObjectContainer
openFile(String) : ObjectContainer
openServer(String, int) : ObjectServer
version() : String

interface
ObjectContainer

opens

starts
opens
interface
ObjectServer
+
+
+
+

close() : boolean
ext() : ExtObjectServer
grantAccess(String, String) : void
openClient() : ObjectContainer

+
+
+
+
+
+
+
+
+
+
+
+
+

activate(Object, int) : void


close() : boolean
commit() : void
deactivate(Object, int) : void
delete(Object) : void
ext() : ExtObjectContainer
get(Object) : ObjectSet
query() : Query
query(Class) : ObjectSet
query(Predicate) : ObjectSet
query(Predicate, QueryComparator) : ObjectSet
rollback() : void
set(Object) : void

DISEO DEL SERVICIO 12 - MODELO DE DB4O

El mtodo openFile abre una conexin directa a un archivo que representa la base de datos. Esta
forma de conexin no admite interaccin remota con la base datos. Para permitir que clientes remotos
accedan a la base de datos, se debe iniciar un proceso servidor, representado por la interfase:
com.db4o.ObjectServer.
El mtodo openServer de la clase Db4o crea una instancia de servidor, que escuchar en el
puerto indicado, permitiendo conexiones a la base de datos que represente el archivo indicado, tanto
locales como remotas. Para obtener acceso local a la base de datos, la interfase ObjectServer, provee el
mtodo openClient.
La nica diferencia entre el acceso local y remoto, es cmo se establece la conexin. Una vez
establecida la conexin, no existe diferencia alguna para el usuario. La conexin est representada por la
interfase: com.db4o.ObjectContainer. Esta interfase provee mtodos para almacenar, buscar y eliminar
objetos.
GUARDANDO OBJETOS
Para indicarle a la base de datos que un objeto debe ser almacenado, ObjectContainer provee el
mtodo set, que recibe como parmetro el objeto a almacenar. Cada vez que se llame a este mtodo con
un nuevo objeto, o sea que no fue obtenido de la base de datos mediante una consulta, se estar
almacenando un nuevo objeto.
Durante la vida de la conexin, la identidad del objeto est garantizada nicamente por la
instancia del objeto. Si se llama a set, con el mismo objeto dos veces, la segunda vez, se le indicar a la
base de datos que actualice el estado del objeto previamente almacenado.
RECUPERANDO OBJETOS
Se proveen diferentes mecanismos para recuperar objetos de la base de datos en funcin de la
complejidad de la consulta.
La forma ms simple, se la denomina Consulta por Ejemplo o QBE (Query By Example). La idea
es crear un objeto prototipo, con los atributos de aquellos objetos que se quieren recuperar, llamando
al mtodo get de ObjectContainer. Dicha operacin devolver una instancia de la interfase ResultSet, que
es un conjunto de resultados. Para todo objeto dentro del conjunto resultado, se cumple que los

96

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

atributos del objeto prototipo son iguales a los del objeto del conjunto. La condicin evala aquellos
atributos del objeto prototipo que tienen un valor distinto del valor por defecto del tipo de atributo. Se
entiende por valor por defecto, al valor que asigna la mquina virtual de Java al inicializar un atributo de
dicho tipo. Por ejemplo, para un atributo de tipo int, el valor por defecto es 0, mientras que para un
atributo de tipo java.lang.Integer, el valor es null. Este tipo de consultas slo permiten concatenar
condiciones por positivo, donde todos los atributos del objeto prototipo deben coincidir con los
resultados.
Para realizar consultas mas avanzadas, se provee otro mecanismo llamado Consultas Nativas o
NQ (Native Query). Se las denomina nativas, porque permite realizar consultas a la base de datos
mediante condiciones escritas en el lenguaje de programacin, en este caso Java [CookWR01]. El
principal beneficio de este tipo de consultas, es que estn escritas en el mismo lenguaje. Lo que implica
que son compiladas, haciendo que los cambios en el modelo produzcan un error de compilacin cuando
la consulta no los refleja. A su vez, evitan introducir un nuevo lenguaje para expresar la consulta, tal como
en el caso de realizarse consultas SQL sobre una base de datos relacional, para obtener resultados que
luego sern traducidos a objetos. Las consultas nativas estn representadas por la clase
com.db4o.query.Predicate (predicado).
Para realizar una consulta, tan slo se requiere sobrescribir el mtodo match de la clase
Predicate, que recibe como parmetro un objeto, el cual ser comparado mediante las condiciones que
determine el predicado. En el ejemplo siguiente, se muestra un predicado en el que la condicin evala
que las personas tengan un nombre igual a Pablo o PABLO.
Predicate personasConNombrePablo = new Predicate<Persona>() {
public boolean match(Persona persona) {
return persona.getName().equals("Pablo") || persona.getName().equals("PABLO");
}
};
Esta forma de realizar consultas es muy atractiva en aquellos casos en los que la consulta est
completamente definida, pero qu pasa en aquellos casos en los que la consulta se define en tiempo de
ejecucin, en funcin de diferentes parmetros?, donde se deben realizar consultas dinmicas. En estos
casos, se provee una interfaz ms avanzada para la construccin de consultas dinmicas, basada en otro
proyecto de cdigo abierto llamado S.O.D.A (Simple Object Database Access o acceso simple de objetos
en base de datos) [SODA01].
SODA trata de proveer una interfase orientada a objetos, que permite construir consultas
dinmicas. Tratando as de minimizar el uso de cadenas de caracteres para realizar consultas, y maximizar
las ventajas que el paradigma de objetos provee, como reutilizacin y encapsulamiento.
Las consultas estn representadas por la interfase com.db4o.query.Query y son creadas por el
ObjectContainer. El mtodo descend de Query, permite navegar los atributos de los objetos, de forma tal
de estableces restricciones (Constraint) sobre ellos. La interfase Constraint representa una restriccin
que se aplica sobre un atributo de los objetos. El mtodo constraint de Query recibe el valor del atributo
y alguna de las operaciones de Constraint determina el tipo de restriccin que se aplica sobre el par
atributo-valor. Por ejemplo, el mtodo greater (mayor) representa que el atributo navegado deber ser
mayor que el valor utilizado como parmetro en la llamada a constraint (la cual cre originalmente el
objeto Constraint).

97

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class db4o query


interface

Serializable
interface

Constraint

QueryComparator
+

+
+
+
+
+
+
+
+
+
+
+
+

compare(first :Object, second :Object) : int

sorts by
creates

interface

and(with :Constraint) : Constraint


contains() : Constraint
endsWith(caseSensitive :boolean) : Constraint
equal() : Constraint
getObject() : Object
greater() : Constraint
identity() : Constraint
like() : Constraint
not() : Constraint
or(with :Constraint) : Constraint
smaller() : Constraint
startsWith(caseSensitive :boolean) : Constraint

Query
+
+
+
+
+
+
+

constrain(constraint :Object) : Constraint


constraints() : Constraints
descend(fieldName :String) : Query
execute() : ObjectSet
orderAscending() : Query
orderDescending() : Query
sortBy(comparator :QueryComparator) : Query

interface
Constraints
+

toArray() : Constraint[]

DISEO DEL SERVICIO 13 - MODELO DE CONSULTAS S.O.D.A

La interfase Constraint tambin permite construir condiciones ms complejas de bsqueda, del


tipo (condicion1 o condicion2) y condicion3, mediante el uso de los mtodos or y and.
El ejemplo de la consulta anterior, donde se buscaba personas con nombre Pablo o PABLO, se
escribira:
Query cPersonas = objectContainer.query();
cPersonas.constrain(Persona.class);
cPersonas.descend("nombre").constrain("Pablo").or(
cPersonas.descend("nombre").constrain("Pablo")
);
ObjectSet personasConNombrePablo = cPersonas.execute();
ELIMINANDO OBJETOS
Cualquier objeto que est almacenado en la base de datos puede ser eliminado mediante el
mtodo delete de la interfase ObjectContainer. Eliminar un objeto no implica que sus referencias sern
eliminadas. Cuando un objeto tiene como atributos otros objetos (que no sean de tipo nativo o
java.lang.String), el manejo del ciclo de vida de las referencias debe ser indicado por el usuario. Esto
obedece a motivos de performance y de semntica de las referencias (cundo un objeto se considera
parte de otro y cundo es slo una referencia?).
MANEJO DE REFERENCIAS
Las operaciones de borrado como las de actualizacin, no se propagan en forma automtica a los
objetos referenciados (salvo por los objetos que sean de tipos nativos del lenguaje). Aunque en el caso de
la insercin la propagacin se hace en forma automtica. Si se tiene un objeto que tiene como atributo a
otro objeto, cuando se modifica un atributo del objeto referenciado y se llama al mtodo set para el
objeto padre, la base de datos no registrar los cambios en el objeto hijo en forma automtica, lo mismo
ocurre con el mtodo delete. Para que as se haga, se le debe indicar explcitamente en la configuracin
de la base, cuales operaciones deben propagarse para cada clase en particular.

98

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

La configuracin de la base se controla por medio del interfase: com.db4o.comfig.Configuration,


que se obtiene llamando al mtodo configure, de Db4o.
class db4o Configuration
interface
ObjectClass
interface
Configuration
+
+
+
+
+
+
+
+
+
+
+
+

activationDepth(int) : void
objectClass(Object) : ObjectClass
setOut(PrintStream) : void
singleThreadedClient(boolean) : void
testConstructors(boolean) : void
timeoutClientSocket(int) : void
timeoutPingClients(int) : void
timeoutServerSocket(int) : void
unicode(boolean) : void
updateDepth(int) : void
weakReferenceCollectionInterval(int) : void
weakReferences(boolean) : void

access

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

callConstructor(boolean) : void
cascadeOnActivate(boolean) : void
cascadeOnDelete(boolean) : void
cascadeOnUpdate(boolean) : void
compare(ObjectAttribute) : void
enableReplication(boolean) : void
generateUUIDs(boolean) : void
generateVersionNumbers(boolean) : void
maximumActivationDepth(int) : void
minimumActivationDepth(int) : void
objectField(String) : ObjectField
persistStaticFieldValues() : void
readAs(Object) : void
rename(String) : void
storeTransientFields(boolean) : void
translate(ObjectTranslator) : void
updateDepth(int) : void

interface
ObjectField
access

+
+
+
+
+
+

cascadeOnActivate(boolean) : void
cascadeOnDelete(boolean) : void
cascadeOnUpdate(boolean) : void
indexed(boolean) : void
queryEvaluation(boolean) : void
rename(String) : void

DISEO DEL SERVICIO 14 - CONFIGURACIN DE DB4O

La configuracin se puede realizar a nivel global de la base de datos desde la interfase


Configuration, a nivel de clase desde la interfase ObjectClass, y a nivel de atributo por medio de la
interfase ObjectField. Los mtodos cascadeOnXXX, indican que la operacin XXX ser propagada a las
referencias. El mtodo updateDepth de ObjectClass permite indicar hasta que nivel las referencias sern
actualizadas cuando se actualice un objeto. Como mencion anteriormente, por defecto se actualizan las
referencias nativas, lo que representa el nivel 1.

C ONECTOR PERSISTENTE CON SOPORTE DE DB4O


Para el conector con soporte persistente, el repositorio est representado por una base de datos
creada con DB4O.

REGISTRO DEL C ONECTOR


La primer parte del conector est dada por su contribucin al compilador. Para ello, agrega a la
configuracin del servicio, las lneas que indican cual es la clase que implementa el TargetCompiler del
conector, que en este caso es PersistentTargetCompiler, junto con el archivo de configuracin de las
plantillas de cdigo.
registered=persistent
persistent=ar.uba.fi.pmi.corba.pss.psdl.compiler.persistent.PersistentTargetCompiler
persistent.templateProperties=psdl_persistent_templates.properties

El servicio de persistencia necesita adems, de una configuracin para soportar este conector.
Por esto, este conector agrega al archivo de configuracin del servicio, la lnea que indica la clase que ser
responsable de procesar el registro del conector, que en este caso es: PersistentConnector.
PSSPMIConnector.ar.uba.fi.pmi.corba.pss.connector.PersistentConnector=Persistent

FUNCIONAMIENTO
Las sesiones que crea el conector estarn representadas por la clase PersistenSession. Una
sesin se conecta a un DataStore por medio de la interfase DataStoreConnection. Existen dos clases

99

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

concretas que implementan dicha interfase: LocalDataStoreConnection y RemoteDataStoreConnection.


La primera y ms simple, es una conexin a un repositorio local representado por un archivo. La segunda
forma de conexin permite acceder a un repositorio remoto existente en otra mquina.
class Persistent Connection
interface
interface
+
+
+
+
+

ObjectContainerFactory
+

create() : ObjectContainer

realize

DataStoreConnection
close() : void
createQuery() : Query
doAttomicOperation(operation) : void
flush(object, introspectionLevel) : void
getContainer() : ObjectContainer

interface
AttomicDataStoreOperation
+ doOperation(container) : void

-factory

-connection

realize
DataStore
+
+
+
+
+
+

AbstractDataStoreConnection

connectionClosed(connection) : void
create() : ObjectContainer
DataStore(fileName)
DataStore(fileName, user, password, port)
openConnection() : DataStoreConnection
shoutDown() : void

+
+
+
+
+
+

AbstractDataStoreConnection(factory)
close() : void
createQuery() : Query
doAttomicOperation(operation) : void
flush(object, introspectionLevel) : void
getContainer() : ObjectContainer

CommonSessionBase
PersistentSession
+
+
+
+

createQuery(operation) : Query
destroy(storageObject) : void
doAttomicOperation(purpose, operation) : void
exist(storageObject) : boolean

-server

LocalDataStoreConnection
+
+

RemoteDataStoreConnection

close() : void
LocalDataStoreConnection(server)

Rem oteDataStoreConnection(host, port, userName, password)

DISEO DEL SERVICIO 15 - CONEXIN PARA ACCESO A LA BASE DE DATOS

Cuando se crea una sesin, sta recibe como parmetro un objeto que implementa
DataStoreConnection, que ser provisto por el conector. El conector se vale de las clases
SessionParameterBuilder y SessionParametersExtractor, para recibir e identificar los parmetros
(representados por la clase Parameter), que definen el tipo de conexin que debe crear.
La interfase DataStoreConnection permite que la sesin sea completamente independiente del
tipo de conexin que se utilice, dado que todas las operaciones contra el DataStore se realizan a travs
de dicha interfase.
R ELACIN CON DB4O
La conexin que tiene asociada una sesin, permite acceder al ObjectContainer de DB4O, que
ser utilizado internamente para almacenar y recuperar los objetos. El hecho de que el conector utilice
DB4O para mantener el estado est oculto a los ojos del usuario final del servicio. Esto se debe a que un
usuario final siempre interactuar con las interfases provistas por el servicio de CORBA, sin tener que
lidiar nunca con mis implementaciones de ellas, ni con sus detalles.
O BJETOS CON ES TADO COMPAR TIDO
Para acceder a un almacn registrado en el conector, ser necesario considerar algunos
problemas que no se presentaban en el conector de memoria. Existe una diferencia fundamental entre el
conector de memoria y el persistente, si bien todo objeto tiene estado (definido por sus atributos), en el
conector persistente, los objetos pueden ser compartidos por mltiples sesiones. Esta caracterstica hace
que se deba tener particular cuidado en como se accede a estos objetos en forma concurrente.
El repositorio en s mismo, tiene atributos que definen un estado que est compartido por todas
las sesiones que lo acceden. El estado est definido fundamentalmente por tres atributos: cuales

100

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

almacenes fueron creados en el repositorio, cuales objetos almacenados fueron creados en los
almacenes del repositorio y una secuencia. La secuencia permite obtener un identificador global dentro
del repositorio, que es asignado a los objetos almacenados al momento de su creacin.
I DENTIFICADORES
El conector persistente se basa en el mecanismo general propuesto por el servicio para identificar
los objetos, mediante la clase: PersistentStorageObjectIdentifier, que implementa la interfase
StorageObjectIdentifier.
Como mencion anteriormente, el modelo de objetos de Java no provee el concepto de
identificador, por esto DB4O no recomienda el uso de identificadores y no provee mecanismos para su
generacin automtica. Las bases de datos relacionales proveen mecanismos eficientes para la
generacin de secuencias de nmeros, como pueden ser tipos de datos autoincrementados. Estos
mecanismos soportan acceso concurrente y transaccional a las secuencias de forma tal que dos o ms
operaciones concurrentes obtengan identificadores distintos.
El modelo general del servicio de persistencia provee una clase que permite generar secuencias
de bytes, ByteArraySequencer. El conector persistente debe garantizar el acceso concurrente y
transaccional a dicha clase para proveer identificadores vlidos.
La forma ms simple de garantizar el acceso concurrente, es serializar el acceso a la operacin
next del objeto secuencia. Esto se logra comnmente mediante el uso de un semforo [Conc01]. Un
semforo es una construccin que garantiza el acceso nico a un recurso o segmento de cdigo, en este
caso a la secuencia. Cuando uno o ms usuarios quieren acceder en forma simultnea a un recurso, el
semforo slo permitir el paso de uno de ellos, bloqueando a los siguientes, hasta que el usuario actual
del recurso lo libere. En Java, los semforos estn encapsulados dentro del lenguaje, cada objeto tiene un
atributo (no visible al usuario) que representa un semforo. Este semforo se utiliza mediante la palabra
clave synchronized, que indica que slo un Thread podr ejecutar el cdigo dentro del bloque
sincronizado.
La clase ByteArraySequencer garantiza el acceso concurrente a ella sincronizando el acceso al
mtodo next. Pero slo sern sincronizados los Threads que se ejecuten dentro de la misma mquina
virtual y sobre la misma instancia de objeto.
Para crear un objeto, se requieren dos identificadores provistos por dos secuencias distintas, el
primero es la secuencia global de identificadores del repositorio y el segundo la secuencia para la familia
de objetos almacenados a la que pertenezca el objeto. Esto ltimo implica que las secuencias sern
compartidas por distintas conexiones a un mismo repositorio y dichas conexiones pueden ser incluso
realizadas desde otras mquinas. Por esto el mecanismo original de sincronizacin de las secuencia es
insuficiente en este escenario.
O PERACIONES ATMICAS
Para garantizar la atomicidad de este tipo de operaciones (generacin de identificadores y otras),
proveo una interfase llamada AtomicDataStoreOperation. Esta interfase representa una operacin que
podr ser realizada en forma atmica en un DataStore. Una operacin atmica es aquella que slo tiene
dos posibles resultados. Exitoso en cuyo caso el contexto queda modificado y fallido, en donde el
contexto queda en el mismo estado que antes de realizar la operacin. El objetivo de esta interfase es
permitir operaciones que no alteren el contexto actual, sino que hagan uso de informacin obtenida
como resultado de la operacin.

101

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

class content
interface

ContentLocator

persistent::AtomicDataStoreOperation
+

doOperation(contai ner) : void

locate(container, template) : I
C:extends Obj ect

#locator

IdentifiedContent
real ize
I:extends IdentifiedContent
AtomicDataStoreOverContentOperation
+
#
+
#
#
#

AtomicDataStoreOverContentOperation(initi al)
commitBeforeUnlocking() : boolean
doOperation(container) : void
getInitial Content() : I
getWaiteTimeOut() : int
operate(container, restored, blocked) : boolean

#
#
+
+
+
+
+
+
+
+

assertInitialized() : void
assertNotInitialzed() : void
getContent() : C
getId() : String
IdentifiedContent()
IdentifiedContent(id, content)
isInitialized() : boolean
setContent(content) : void
setId(id) : void
toString() : Stri ng

ByteArraySequencerContent
ByteArraySequencerOperation
+
+
#

ByteArraySequencerOperation(id)
getValue() : byte[]
operate(container, restored, blocked) : boolean

+
+
+
+

ByteArraySequencerContent()
ByteArraySequencerContent(id)
ByteArraySequencerContent(id, content)
next() : byte[]

DISEO DEL SERVICIO 16 - GENERACIN ATOMICA DE IDENTIFICADORES

El diagrama que se muestra arriba, esquematiza las clases involucradas en la generacin de un


nuevo identificador a partir de una secuencia. La interfase DataStoreConexion provee el mtodo
doAtomicOperation, que recibe como parmetro una operacin a realizar. Toda operacin se realiza en
un nuevo contenedor de objetos (no sobre el contenedor que utiliza la sesin), que es provisto por un
objeto de tipo ObjectContainerFactory.
Existe una clase concreta llamada ByteArraySequencerOperation, que hereda de la clase base
AtomicDataStoreOverContentOperation, que provee la funcionalidad necesaria para que pueda
realizarse la operacin en forma atmica. La idea general, es realizar una operacin sobre un contenido
inicial que puede o no estar almacenado en el repositorio. La clase ContentLocator es la encargada de
ubicar el contenido en el repositorio, en base a un objeto prototipo. Este prototipo se utiliza para realizar
un tipo de consulta por ejemplo. El contenido ser siempre un objeto que implemente la interfase:
IdentifiedContent, que bsicamente permite que un objeto sea identificado por una secuencia de
caracteres.
DB4O provee semforos con soporte nativo de la base de datos que garantizan concurrencia
entre los distintos clientes. Los semforos se indetifican por una secuencia de caracteres. Para acceder a
los semaforos se utiliza la intefase ExtObjectContainer de DB4O.
public boolean setSemaphore(String name, int waitMilliSeconds);
public void releaseSemaphore(String name);
Al inicio de la operacin, la clase AtomicDataStoreOverContentOperation iniciar un semforo
mediante el mtodo setSemaphore con el identificador del contenido a utilizar. De esta forma cualquier
otra operacin que utilice el mismo contenido (secuencia), deber esperar que la operacin en curso
libere el semforo mediante la operacin releaseSemaphore. Una vez obtenido el semforo, se tratar de

102

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

ubicar el contenido con el ContentLocator, si el contenido no existe, se crear para ser almacenado en el
contendor. Sobre el contenido se realiza la operacin necesaria, mediante el mtodo operate de la
operacin. Se almacena el resultado como atributo del objeto, luego se finaliza la operacin liberando el
semforo y se cierra la conexin.
Esta forma de ejecucin garantiza que una nica operacin pueda ser realizada sobre el mismo
repositorio y sobre el mismo contenido en forma concurrente. Las operaciones son genricas y pueden
ser aplicadas a cualquier proceso que requiera acceso exclusivo sobre un contenido del repositorio.
Esta forma de garantizar acceso concurrente, se denomina genericamente bloqueo pesimista
[RoySeif01] dado que se realiza el bloqueo del semforo cada vez que se quiere acceder al recurso
compartido. En un esquema optimista se tiene la premisa que la mayora de las operaciones no
interferirn entre ellas, por lo que no es necesario realizar un bloqueo inicialmente. De todas formas, se
tiene que garantizar que en el caso de que las operaciones interfieran, los resultados sern correctos. En
este caso no se deberan tener dos identificadores iguales en distintas operaciones. En el esquema del
identificador global, es altamente probable que las operaciones interfieran entre s, dado que existe un
nico identificador global por repositorio. Y por otro lado, se entiende que el servicio de estado
persistence no tendr una cantidad masiva de conexiones remotas concurrentes, por lo que no es tan
crtico que el tiempo consumido por la operacin de creacin sea mnimo. Adems el bloqueo optimista
es ms complicado de implementar, es por esto y lo anteriormente dicho que consider al bloqueo
pesimista como la mejor opcin para este caso.
A LMACENES
Este conector tambin sigue el esquema de delegacin propuesto inicialmente
Todo almacn de objetos que utilice este conector debe implementar
PersistentStorageHome. Esta interfase permite que el conector implemente el mismo
delegacin que el conector de memoria, extendiendo a la interfase base
ExtendedStorageHome.

por el servicio.
la interfase:
mecanismo de
del servicio:

class General Schema


ExtendedStorageHome

AbstractTargetCompiler

interface

persistent::PersistentTargetCompiler

persistent::PersistentStorageHome
+
+

create(PersistentStorageHome, PersistentStorageHomeKeySet) : SO
find_by_spec(PersistentStorageHome, StorageObjectSpec) : SO

StorageHomeKeySet
persistent::PersistentStorageHomeKeySet
+

validate(String, PersistentStorageHome) : void

realize
ConnectorBase

realize
connector::PersistentConnector

AbstractRootStorageHome
persistent::
PersistentRootStorageHome
{leaf}

+
+

getConnection(PersistentSession, Parameter[]) : DataStoreConnection


PersistentConnector()
BaseStorageObjectIdentifier

AbstractChildStorageHome

persitent::PersistentStorageObj ectIdentifier

persistent::PersistentStorageHomeBase
+
+
+

create(PersistentStorageHome, PersistentStorageHomeKeySet) : SO
find_by_spec(PersistentStorageHome, StorageObjectSpec) : SO
PersistentStorageHomeBase()
CommonSessionBase

+
+
+
+
+
+

createConstraint(Query) : Constraint
getLong_pid() : Long
getLong_short_pid() : Long
PersistentStorageObjectIdentifier(PersistentStorageHome)
PersistentStorageObjectIdentifier(byte[], byte[], PersistentStorageHome)
PersistentStorageObjectIdentifier(byte[], byte[], String, String)

persistent::PersistentSession

+
+
+
+

persistent::SpecToConstraintTransformer

createQuery(String) : Query
destroy(StorageObject) : void
doAtomicOperation(String, AtomicDataStoreOperation) : void
exist(StorageObject) : boolean

transform(StorageObjectSpec) : Constraint

DISEO DEL SERVICIO 17 - ESQUEMA GENERAL DEL CONECTOR PERSISTENTE

103

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Existen
dos
implementaciones
base
de
dicha
interfase,
la
primera
es
PersistentStorageHomeBase que es utilizada como clase base por el generador de cdigo del conector.
Todo almacn generado por el compilador heredar directa o indirectamente de esta clase. La otra
implementacin es PersistentRootStorageHome, que representa a la familia de almacenes para un tipo
de objeto almacenado que no tenga un supertipo.
El nico estado de los almacenes que se mantiene en los repositorios es la secuencia que
permite generar identificadores para la familia. Cada conexin a un repositorio tendr sus propias
instancias de los almacenes, pero todas ellas compartirn los mismos juegos de secuencias mediante
objetos de tipo ByteArraySequencerOperation, que utilizarn secuencias identificadas por los
identificadores de las familias de almacenes. De manera anloga, cada sesin que se conecte a un
repositorio tendr como atributo una operacin atmica que permitir generar identificadores globales
para el repositorio. Esta operacin utilizar un identificador especial reservado para la secuencia global.
O PERACIONES DE CONSULTA
Las operaciones de consultas se realizan utilizando una de las interfases que provee DB4O para tal
efecto. Dado que el usuario final no conoce esta interfase, ser necesario que el compilador genere el
cdigo necesario para construir las consultas para el servicio.
Las consultas que debe generar el compilador estn definidas principalmente por las operaciones
de bsqueda que se deriven de la definicin PSDL compilada. Estas consultas son dinmicas en el sentido
de que varan en funcin de la jerarqua de objetos que presenten los almacenes. Por esto, no pueden ser
generadas en su totalidad por el compilador, ya que ste slo tiene una vista parcial del esquema, que
est dada por el archivo PSDL que est procesando.
En consecuencia, es solamente en tiempo de ejecucin donde se pueden conocer todos los
parmetros necesarios para construir las consultas requeridas. Esto implica que el conector deber
proveer al compilador un mecanismo lo suficientemente amplio como para generar las consultas en
tiempo de ejecucin.
Las consultas requeridas, siguiendo el esquema general propuesto en el servicio, son las basadas
en las especificaciones de los objetos (StorageObjectSpec). Con relativamente poco trabajo, se puede
traducir una especificacin de objeto en una consulta de DB4O, representada por la clase Constraint. La
clase SpecToConstraintTransformer est encargada de esta tarea. Toma una especificacin de objeto,
itera sobre todos los atributos de la especificacin agregando una clusula (Constraint) por cada atributo
que defina la especificacin.
Este mecanismo es lo suficientemente genrico como para que el compilador se encargue de
agregar las entradas necesarias en las clases generadas, como para construir especificaciones vlidas y en
base a ellas construir las consultas necesarias por el servicio.
C REACIN DE OBJETOS ALMACENADOS
Los mecanismos de construccin de objetos almacenados son los mismos, tanto para este
conector como para el conector de memoria, ya que ambos siguen el esquema de delegacin propuesto
por el servicio. La diferencia radica en los mecanismos que se utilizan para la generacin de
identificadores (antes descripta) y para la validacin de las claves.
El mecanismo general para la validacin se dispara cuando se construye un objeto y se basa en la
clase StorageHomeKeySet. Dicha clase es extendida por el conector persistente, mediante
PersistentStorageHomeKeySet, en donde se delega la validacin en una consulta generada a partir de
todas las claves que se definan en la especificacin. La consulta se genera utilizando la clase

104

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

SpecToConstraintTransformer. El conjunto de claves que incluya la especificacin determinarn la forma


de consulta.
A CCES O REMOTO AL REP OSITORIO
El tipo de repositorio y como se accede al mismo no es parte de la especificacin del servicio,
por lo que toda implicacin derivada de permitir este tipo de acceso no est contemplada en el servicio.
Como ya mencion anteriormente, el modo de acceso est definido por los parmetros de
entrada que recibe el conector cuando crea la sesin. Dado que mi repositorio est representado por una
base de datos DB4O, el acceso remoto se basa en el modelo cliente / servidor que esta base de objetos
provee. Todo repositorio en DB4O, se almacena en un archivo administrado por la base de datos.
La primera implicacin, es que para acceder en forma remota se requiere que exista un servidor
corriendo en la mquina donde est almacenado el repositorio. O sea, para que un cliente pueda acceder
al repositorio remoto, el proceso servidor deber estar operativo.
Para resolver esta primera implicacin he tomado una poltica simple, cualquier servicio de
persistencia que se ejecute es un potencial servidor, cualquier repositorio que sea utilizado por algn
servicio de persistencia, podr ser accedido en forma remota con tan slo unos parmetros al momento
de inicio de la sesin. El nico requerimiento para que se mantenga activo el servidor es que el proceso
donde se cre la sesin se mantenga activo. El conector persistente es el encargado de mantener activos
a los servidores locales existentes.
La clase ar.uba.fi.pmi.corba.pss.catalog.persistent.DataStore representa un repositorio local. El
conector lleva el registro de todos los DataStore creados desde que se inicializ el conector. Cuando se
crea una nueva conexin a un DataStore, slo se crea un DataStore, si es la primera vez que se accedi a
ese DataStore, en caso contrario se le solicita al ya existente una nueva conexin. El DataStore hace
adems las veces de servidor, cuando el mismo es construido con la informacin necesaria: un puerto
donde escuchar por conexiones, un usuario y una clave para garantizar el acceso.
deployment Deployment Model
mquina2
CPU2
PMIPSS2
mquina1
use
Repositorio1 - DB4O
remoto
Cliente2
local
remoto

mquina3

use
CPU1

PMIPSS1

Repositorio3 - DB4O
local

use

PMIPSS3
CPU3
use

Cliente1

Cliente3

DISEO DEL SERVICIO 18 - ACCESO REMOTO A LOS REPOSITORIOS

105

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

La segunda implicacin es muy importante al utilizar un modelo cliente / servidor, en el cual un


proceso hace las veces de cliente y otro de servidor. Para que ambos procesos puedan compartir objetos
del mismo tipo, ambos deben compartir el mismo espacio de clases, es decir que tanto el cliente como el
servidor debern tener disponibles en tiempo de ejecucin las mismas clases de objetos que sern
almacenadas y recuperadas del repositorio. Esta segunda implicacin est resuelta por la primera, ya que
es el servicio de persistencia mismo quien hace las veces de cliente y servidor. Para que el servicio pueda
funcionar como tal requiere tener disponibles las clases que representan los objetos almacenados junto
con sus almacenes.
El grfico 18 muestra un escenario real posible, donde existen 2 repositorios ubicados en dos
mquinas distintas. Hay tres clientes que acceden a estos repositorios, por medio de mi conector
persistente. El repositorio 2 es accedido en forma local y remota por dos conectores, uno ubicado en la
misma mquina donde est el repositorio (acceso local) y otro ubicado en otra mquina. En todos los
casos los clientes no se modifican por hacer uso del acceso remoto o local.
T RANSACCIONES
Como se describi anteriormente, el servicio de estado persistente soporta transacciones a
travs del servicio de transacciones de CORBA [TS01]. El conector persistente tiene soporte para
transacciones a travs de la base de datos que utiliza DB4O.
DB4O soporta todas las caractersticas que definen las transacciones, llamadas propiedades
ACID, de sus siglas en ingls: Atomicity, Consistency, Isolation, Durability [GrayReuter01]. Atomicity o
Atomicidad implica que todas las operaciones que se ejecutan dentro del contexto de una transaccin,
son realizadas en su totalidad cuando la transaccin es exitosa y cuando falla ninguna es realizada. Todas
las operaciones se pueden ver como una unidad atmica, todas o ninguna. Consistency o Consistencia
implica que la ejecucin de la transaccin deja la base de datos en un estado consistente, o sea no existen
estados intermedios dentro de una transaccin para operaciones que se realicen fuera del contexto de la
transaccin. Isolation o Aislamiento implica que cada transaccin ve a la base de datos como si fuera la
nica transaccin que se ejecuta en forma simultanea, o sea la base bloquear operaciones de
modificacin concurrente, de forma tal que se ejecuten secuencialmente. Y finalmente, Durability o
Durabilidad implica que una vez ejecutada la transaccin en forma exitosa, los cambios en la base son
permanentes y las prximas transacciones podrn verlos.
El tipo de transaccin que se quiera ejecutar depender de la transaccin generada por el
servicio de transacciones. Cuando se accede al servicio de estado persistente, sin hacer uso del servicio de
transacciones, todas las operaciones que se ejecuten dentro del contexto de una misma sesin sern
demarcadas automticamente dentro del contexto de una transaccin. De todas formas PSS permite el
uso de sesiones sin soporte de transacciones mediante algunas operaciones explicitas en ella, como por
ejemplo las operacin flush y refresh. Estas operaciones tienen el objeto de operar sobre el sistema de
cache que implemente el conector. La primer operacin debera forzar la realizacin de los cambios y la
segunda refrescar el estado de la sesin actual. Para este conector he optado por traducir la operacin de
flush en un commit sobre la transaccin actual, haciendo persistentes todos los cambios realizados hasta
ese instante. En DB4O, la operacin de commit hace persistentes los cambios e inmediatamente abre
otra transaccin sobre la que se puede seguir trabajando. La operacin close sobre un ObjectContainer,
fuerza automticamente un commit. En el caso de la operacin refresh, la especificacin misma indica
que sera extremadamente raro que un usuario final necesite llamar a este mtodo y carece de sentido en
el uso normal de DB4O.
Este manejo de transacciones, sin hacer uso del servicio de transacciones, es una buena solucin
de compromiso para los posibles usos que se le pueden dar al servicio de persistencia. No se trata de
reemplazar una base de datos orientada a objetos con el servicio de persistencia, sino de proveer una

106

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

solucin acotada para mantener el estado de un servant, que generalmente tendr pocos objetos para
persistir e interactuar.

CONSTRUCCIONES RESULTANTES DEL TRABAJO


Se construy un compilador de lenguaje PSDL. El compilador consta dos partes principalmente
o
o

Un parser que fue construido mediante Javacc y JJtree


Un generador de cdigo fuente. El cdigo fuente generado depende de la
implementacin del servicio de persistencia que se defina.

El compilador usa un sistema generador de cdigo fuente que constru para este trabajo. Utiliza
un modelo de clases y plantillas de cdigo. Adems constru un intrprete de clases que permite generar
esqueletos de clases e interfases en base a un objeto real dado. Estas dos construcciones pueden ser
utilizadas en cualquier otro trabajo que pueda o no estar relacionado con ste. Las plantillas se traducen a
cdigo fuente utilizando la biblioteca Jexl que permite incrustar secciones dinmicas en las plantillas que
se evalan en base a un contexto provisto por mi generador de cdigo fuente.
Se construyeron dos implementaciones de conectores para mi servicio de estado persistente de
CORBA:
o
o

Una implementacin que guarda los objetos en memoria


Otra implementacin que utiliza una base de datos orientada a objetos, DB4O, para
persistir estos objetos.

Todas las construcciones realizadas, incluyendo el compilador, cuentan con pruebas unitarias,
para garantizar el funcionamiento de cada una de las partes. Estas pruebas permiten que las
construcciones puedan ser mejoradas y completadas, asegurando que lo construido siga funcionando de
la forma esperada. Las pruebas unitarias se realizaron utilizando la biblioteca JUnit.
Algunas de estas pruebas unitarias requieren compilar y validar su resultado en tiempo de
ejecucin, lo que equivale a compilar cdigo fuente Java en tiempo de ejecucin. Para realizar esta tarea
he utilizado un framework llamado Janino, que permite utilizar clases compiladas en tiempo de ejecucin
a partir de su cdigo fuente (generado en este caso por el compilador).
Tanto el compilador como los conectores, utilizan internamente algunas bibliotecas de Jakarta
Commons como Loggings y Collections. Jakarta Commons es un proyecto de Apache que tiene el
propsito de construir componentes de software reutilizables en todo tipo de aplicaciones Java.
El cdigo fuente fue desarrollado utilizando el IDE Eclipse y la versin 5 de Java. El cdigo fuente
contiene ms de 300 clases que corresponden al generador de cdigo fuente, al compilador, al servicio de
estado persistente y a los dos conectores. Adems se elaboraron ms de 100 pruebas unitarias para todas
las funcionalidades construidas.
Al final de esta seccin se encuentra una lista con las referencias utilizadas en el trabajo.

107

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

UN EJEMPLO CONCRETO
A continuacin voy a presentar un ejemplo simple, mostrando el cdigo generado por el
compilador para el conector persistente, y demostrando cmo este cdigo es utilizado en el contexto de
una aplicacin CORBA.

C DIGO PSDL
El cdigo PSDL representa una definicin de un objeto almacenado abstracto, un almacn
abstracto para este objeto, junto con sus respectivas implementaciones.
abstract storagetype Persona {
state string nombre;
state string apellido;
state long nroDocumento;
string nombreCompleto();
};
abstract storagehome PersonaHome of Persona {
key nroDocumento;
factory crear(nombre, apellido, nroDocumento);
};
storagetype PersonaBase implements Persona { };
storagehome PersonaHomeBase of PersonaBase implements PersonaHome {
};
En este ejemplo el objeto almacenado es Persona, su almacn es PersonaHome, y PersonaBase es
su implementacin, mientras que PersonaHomeBase es la implementacin del almacn. Persona tiene
tres atributos: nombre, apellido y nmero de documento, junto con una operacin de usuario llamada
nombreCompleto. El almacn de la persona define una clave nica en base al nmero de documento de
la persona. Y expone una operacin de fbrica llamada crear, que permite construir personas con
nombre, apellido y nmero de documento en una sola operacin.

R ESULTADO DE LA COMPILACIN DEL CDIGO PSDL


Al compilar un archivo PSDL que contenga el cdigo mostrado anteriormente, se obtiene la
siguiente lista de archivos:
Persona.java: interfase que define el objeto almacenado abstracto Persona.
PersonaBase.java: clase concreta que implementa a la interfase Persona.
PersonaHome.java: interfase que define el almacn abstracto de la Persona.
PersonaHomeBase.java: clase que implementa el almacn abstracto de la Persona.
PersonaHomeHelper.java, PersonaHomeHolder.java, PersonaHomeOperations.java,
_PersonaHomeLocalBase.java: Estos ltimos archivos son generados de acuerdo con la especificacin
CORBA. Toda interfase IDL tiene separadas sus operaciones en otra interfase, adems debe tener sus
respectivas clases Holder, Helper. El ltimo archivo es tambin requerido por la especificacin de CORBA,
y representa una clase que permite obtener los identificadores IDL de la interfase CORBA, que son
utilizados para ubicar la interfase en un registro.

108

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Para el caso de este ejemplo me voy a focalizar slo en los cuatro primeros archivos, que son los
ms importantes a los efectos prcticos del servicio de persistencia.

P ERSONA
El cuadro de texto siguiente representa una versin simplificada del cdigo fuente de la interfase
generada por el compilador: Persona. Se han eliminado parte de los comentarios para reducir el tamao.
En el cdigo fuente, se muestra que la interfase hereda de la interfase StorageObject de PSS, adems,
cada uno de los estados tiene sus mtodos para lectura y escritura, y la operacin de usuario
nombreCompleto.
Tanto los comentarios de inicio del archivo como los comentarios de la interfase y cada uno de los
mtodos son generados en base a las plantillas de cdigo configuradas en el compilador.

/**
* .
* <b>F.I.U.B.A.</b>
* ..
* <a href='mailto:pilardi@fi.uba.ar'>Pablo Maximiliano Ilardi</a>
*
* Persona.java: was generated by PMI-PSDL Compiler Version 1.0
* .
*/
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
import org.omg.CosPersistentState.StorageObject;
/**
* ..
* @author PMI-PSDL Compiler Version 1.0 - persistent
*/
public interface Persona extends StorageObject {
public abstract String nombre();
public abstract void nombre(String s);
public abstract String apellido();
public abstract void apellido(String s);
public abstract long nroDocumento();
public abstract void nroDocumento(long l);
public String nombreCompleto();
}

P ERSONA HOME
Las primeras operaciones permiten ubicar a una Persona por la clave definida por el nmero de
documento. El ltimo mtodo representa la operacin de fbrica, que permite crear Personas por sus
atributos.

109

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
.
/**
* ....
* @author PMI-PSDL Compiler Version 1.0 - persistent
*/
public interface PersonaHome extends PersonaHomeOperations, LocalInterface, IDLEntity,
StorageHomeBase {
}
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;

public interface PersonaHomeOperations extends StorageHomeBaseOperations {


public Persona find_by_nroDocumento(long nroDocumento) throws NotFound;
public byte[] find_ref_by_nroDocumento(long nroDocumento);
public Persona crear(String nombre, String apellido, long nroDocumento);
}

P ERSONA B ASE
.
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
.
public abstract class PersonaBase implements Persona, StorageObject, ExtendedStorageObject {
private static final long serialVersionUID = -1737034293L;
private StorageObjectIdentifier identifier;
private long nroDocumento;
private String apellido;
private String nombre;
public PersonaBase() { }
public final long nroDocumento() { return this.nroDocumento; }
public final void nroDocumento(long l) { this.nroDocumento = l; }
public final String apellido() { return this.apellido; }
public final void apellido(String s) { this.apellido = s; }
public final String nombre() { return this.nombre; }
public final void nombre(String s) { this.nombre = s; }
public final byte[] get_pid() { return this.get_identifier().get_pid(); }
public final byte[] get_short_pid() { return this.get_identifier().get_short_pid(); }
public final StorageHomeBase get_storage_home() {
return this.get_identifier().get_storage_home();
}
public final void destroy_object() {
((ExtendedStorageHome) this.get_storage_home()).destroy(this);
}

public final boolean object_exists() {


return ((ExtendedStorageHome) this.get_storage_home()).exist(this);
}
..

110

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

public final boolean is_initialized() {


return this.identifier != null;
}
public final synchronized void initialize(
StorageObjectIdentifier identifier, StorageObjectSpec specification) {
if (this.is_initialized()) {
throw new PERSIST_STORE(
"The storage object " + this.identifier + ", was already been initialized");
}
this.identifier = identifier;
this.after_initialize(specification);
}
public final StorageObjectIdentifier get_identifier() {
if (!this.is_initialized()) {
throw new IllegalStateException("The storageobject " + this + " has not been initialized");
}
return this.identifier;
}
protected void after_initialize(StorageObjectSpec specification) {
if (specification.hasValue("nroDocumento")) {
this.nroDocumento = specification.get_long("nroDocumento");
}
if (specification.hasValue("apellido")) {
this.apellido = specification.get_string("apellido");
}
if (specification.hasValue("nombre")) {
this.nombre = specification.get_string("nombre");
}
}
}
Al segmento de cdigo anterior tambin se le han eliminado los comentarios. Algunas
caractersticas a resaltar de esta clase son: que representa un objeto almacenado concreto que
implementa una definicin abstracta (Persona), esta clase es la primera en una jerarqua y no requiere
que herede de otra clase que no sea la clase Object en Java. En Java es importante no forzar la herencia
de alguna clase, dado que slo se soporta herencia de una nica clase. Desde el punto de vista de la
persistencia transparente, si bien no es ideal requerir implementar interfases, como StorageObject o
ExtendedStorageObject, el forzar la herencia de alguna clase impondra una limitacin mucho ms
grande al modelo que el usuario final pueda definir.
Otra caracterstica importante es que muchos mtodos estn declarados como final, esto implica
que no pueden ser redefinidos en subclases de esta clase. Esta caracterstica se debe en algunos casos al
uso del patrn de diseo template method [Gamma01] (como en el caso del mtodo initialize), y en otros
casos para asegurar el correcto funcionamiento de algunas operaciones como las de lectura/escritura de
las propiedades persistentes.
El mtodo after_initialize muestra como los objetos son inicializados a partir de una
especificacin, en este caso, se trata de inicializar las tres propiedades persistentes del objeto
almacenado.
Como la operacin de usuario nombreCompleto no est definida por el compilador, la clase est
declarada como abstracta.

111

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

P ERSON H OME B ASE


Como el almacn fue compilado para el conector persistente, esta clase hereda del almacn
persistente PersistentStorageHomeBase y slo implementa el almacn abstracto de la persona,
PersonaHome.
PersonaHomeBase representa adems, el primer almacn de la jerarqua. Esto se refleja en el
mtodo initialize, donde se indica que el almacn debe ser inicializado como raz (root) de la jerarqua.
Las operaciones de bsqueda find_by_nroDocumento, se traducen en la construccin de las
especificaciones con los valores de las claves que estn definidas en el almacn, en este caso es el
nmero de documento.
La operacin de fbrica crear se limita a crear una especificacin con los valores de los atributos
del objeto almacenado a crear, para luego delegar la construccin efectiva en un mtodo de la
superclase.
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
public class PersonaHomeBase extends PersistentStorageHomeBase implements PersonaHome {

public PersonaHomeBase() {}
public Persona crear(String nombre, String apellido, long nroDocumento) {
StorageObjectSpec spec = this.newSpec();
spec.set_string("nombre", nombre);
spec.set_string("apellido", apellido);
spec.set_long("nroDocumento", nroDocumento);
return (Persona)this.create(spec);
}
public Persona find_by_nroDocumento(long nroDocumento) throws NotFound {
StorageObjectSpec spec = this.newSpec();
spec.set_long("nroDocumento", nroDocumento);
return (Persona)this.find_by_spec(spec);
}
public byte[] find_ref_by_nroDocumento(long nroDocumento) {}
protected void collectKeys(StorageHomeKeySet keys) {
super.collectKeys(keys);
StorageHomeKeyBuilder keynroDocumento = keys.keyBuilder("nroDocumento");
keynroDocumento.with("nroDocumento");
keynroDocumento.build();
}

public StorageHomeBase initialize(Session session, String registered_id) throws NotFound {


return this.initializeRootHome((PersistentSession)session, registered_id,
"PSDL:ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple/PersonaBase:1.0");
}
}

P ERSONA B ASE I MPL


Cuando los objetos almacenados o los almacenes definen operaciones de usuario, el usuario es
responsable de proveer la implementacin para dichas operaciones. La clase PersonaBaseImpl solamente
se limita a implementar el mtodo nombreCompleto.

112

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

public class PersonaBaseImpl extends PersonaBase {


/**
* @see ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple.Persona#nombreCompleto()
*/
public String nombreCompleto() {
return this.apellido() + ", " + this.nombre();
}
}
En este caso, la operacin simplemente concatena el apellido y nombre de la persona.

U SO DEL MODELO EN UNA APLICACIN CORBA


Hasta este punto se mostr el modelo PSDL, ahora se ver como una aplicacin CORBA puede
hacer uso de este modelo de trabajo propuesto por el servicio de estado persistente, PSS.
Toda aplicacin CORBA est compuesta por objetos que proveen servicios llamados servants
definidos en lenguaje IDL y por objetos cliente que hacen uso de los servants. Los clientes acceden a los
servants mediante la ORB, quien provee referencias de los servants, de forma tal que los clientes siempre
tratan con objetos que implementan la interfase IDL expuesta por el servant y no con el objeto real que
provee el servicio.
En este ejemplo, existe un servant que provee servicios para acceder a personas, definidas
mediante el modelo PSDL. El servant es una instancia de la interfase RegistroPersona, definida en el
siguiente segmento de cdigo IDL.
exception PersonaNoExiste {};
exception PersonaYaExiste {};
interface RegistroPersona {
void crearPersona(in string nombre, in string apellido, in long nroDocumento)
raises (PersonaYaExiste);
void eliminarPersona(in long nroDocumento)
raises (PersonaNoExiste);
string nombreCompleto(in long nroDocumento) raises (PersonaNoExiste);
void cerrarRegistro ();
};
El servant RegistroPersona permite tres operaciones bsicas sobre las personas: creacin,
eliminacin y consulta del nombre completo de la persona (mtodo expuesto por el objeto almacenado
Persona definido en PSDL).
Las personas son creadas por el mtodo crearPersona, cuyos parmetros identifican a la persona
y son los siguientes: nombre, apellido y nmero de documento. Para eliminar a una Persona se debe
llamar al mtodo eliminarPersona, con un parmetro que indica el nmero de documento que identifica
a la Persona. Finalmente, para obtener el nombre completo de una Persona, se debe llamar al mtodo
nombreCompleto con el nmero de documento de la Persona a consultar.
El siguiente grfico muestra la interaccin de las partes, cliente y servidor. La clase
ServidorPersonas representa el proceso servidor, donde se instancia al servant, que en este caso, es la
clase RegistroPersonasImpl, que implementa las operaciones de la interfase definida inicialmente,
RegistroPersona.

113

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

El cliente est representado por la clase ConsultaPersonas. Esta clase accede al registro
mediante una referencia obtenida de la ORB. El acceso a la ORB, tanto para el cliente como para el
servidor, est centralizado en la clase ORBAccessor. Esta clase es simplemente una utilidad provista por
m, que permite centralizar todas las operaciones que requieran interaccin con la ORB, como acceso a
las referencias iniciales, al servicio de persistencia o a la creacin de la ORB.
Este modelo de aplicacin deja muy clara la separacin entre el dominio de la aplicacin CORBA
y el del servicio de persistencia. Todas las operaciones del registro de personas no estn ligadas a los
objetos utilizados por el servicio de persistencia, esto se debe a que dichos objetos son privados, o sea
locales al servant y no pueden ser exportados por la ORB a otra mquina. Los objetos que define el
servicio de persistencia pasan a ser detalles de implementacin del servant y desde el punto de vista de
un cliente del servant no existen.

obj ect Ej emploCORBAPSS


i nterface
RegistroPersonaOperations
+
+
+
+

Servant

cerrarRegistro() : void
crearPersona(String, String, int) : void
eliminarPersona(int) : void
nombreCompleto(i nt) : String

RegistroPersonaPOA

IDLEntity
Object

RegistroPersonaImpl
utils::ORBAccessor

i nterface

+
+
+
#
+
+

RegistroPersona
-registro

cliente
ConsultaPersonas
#
+
+
+
+

atenderConsultas() : voi d
ConsultaPersonas(String[])
l eerEntrada() : Stri ng
main(String[]) : void
presentarMenu() : i nt

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

activateRootPOAManager() : void
getDynAnyFactory() : DynAnyFactory
getNameService() : NamingContextExt
getOrb() : ORB
getPersistentStateServi ce() : ConnectorRegistry
getRootPOA() : POA
isIni tialized() : boolean
object_to_string(org.omg.CORBA.Object) : String
ORBAccessor()
ORBAccessor(String[])
ORBAccessor(String[], Properties)
readObject(String) : org.omg.CORBA.Object
shoutDown(bool ean) : void
string_to_object(String) : org.omg.CORBA.Obj ect
writeObject(org.omg.CORBA.Object, String) : voi d

servidor
Serv idorPersonas
+
+

cerrarRegistro() : voi d
crearPersona(String, String, int) : void
eliminarPersona(i nt) : void
getPersona(i nt) : Persona
nombreCompleto(i nt) : String
RegistroPersonaImpl(ORBAccessor, PersonaHome)

-home
IDLEntity
PersonaHomeOperati ons
StorageHomeBase
LocalInterface
interface
PersonaHome

accede
creacin

StorageObject
interface
Persona
+
+
+
+
+
+
+

apel lido() : String


apel lido(String) : void
nombre() : Stri ng
nombre(String) : void
nombreCompleto() : String
nroDocumento() : long
nroDocumento(long) : void

mai n(String[]) : void


ServidorPersonas(String[])

DISEO DEL SERVICIO 19 - APLICACIN CORBA CON ACCESSO A PSS

A continuacin voy a mostrar el segmento de cdigo que da inicio al proceso servidor.

114

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

// Se accede al registro de conectores


ConnectorRegistry registry = server.getPersistentStateService();
// Se obtiene el conector persistente
Connector connector = registry.find_connector("Persistent");
// Se registra en el conector la clase PersonaBaseImpl
connector.register_storage_object_factory(
PSDLUtils.getRepositoryID(PersonaBase.class), PersonaBaseImpl.class);
// Se registra el almacn por defecto
final String idAlmacenPersonas = PSDLUtils.getRepositoryID(PersonaHomeBase.class);
connector.register_storage_home_factory(idAlmacenPersonas, PersonaHomeBase.class);
// Se crean los parmetros para utilizar el archivo registroPersonas.db como
// base de datos para la sesin a crear
Parameter[] parameters = new SessionParameterBuilder()
.withFileName("c:\\registroPersonas.db").build(server.getOrb());
// Se crea una sesin
Session mySession = connector.create_basic_session(READ_WRITE.value, parameters);
// Ahora se obtiene el almacn de personas de la sesin
PersonaHome almacenPersonas =
(PersonaHome) mySession.find_storage_home(idAlmacenPersonas);
// Ahora se crea el registro de personas CORBA
RegistroPersonaImpl registro = new RegistroPersonaImpl(server, almacenPersonas);
// Se activa el servant, para que se pueda acceder por otros procesos
server.getRootPOA().activate_object(registro);
Este segmento de cdigo corresponde a la clase ServidorPersonas y muestra la interaccin entre
el servant y el servicio de persistencia. El objeto server representa una instancia de la clase ORBAccessor,
la primera lnea de cdigo obtiene una referencia al registro de conectores como una referencia inicial a
la ORB. Las siguientes lneas inicializan al conector persistente, que es el conector identificado por
Persistent, con las clases que representan el dominio del servicio de persistencia. Estas clases son: el
almacn de personas PersonaHome y el objeto almacenado Persona. Las siguientes lneas estn
dedicadas a la construccin de la sesin de trabajo con el servicio. La clase SessionParameterBuilder
permite construir los parmetros necesarios para crear la sesin de trabajo basada en el archivo
registroPersonas.db, que ser utilizado por DB4O, como almacn de la base de datos que soporte a la
sesin. Finalmente, las ltimas lneas permiten la inicializacin del servant RegistroPersonaImpl con una
referencia al almacn de personas, que es utilizado para delegar todas las operaciones con personas.
Si se quisiera compartir la base de datos que da soporte al repositorio con otras instancias del
servicio de persistencia, tan slo sera necesario agregar ms parmetros al mtodo que crea la sesin de
trabajo.
Parameter[] parameters = new SessionParameterBuilder()
.withFileName("c:\\registroPersonas.db")
.withUserName("pablo")
.withUserPassword("test")
.withPort(12300)
.build(server.getOrb());

En el caso de los parmetros mostrados en el cuadro anterior, se habilita al repositorio para su


acceso remoto por el puerto 12300, mediante un usuario con nombre pablo, y clave test.

115

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

Parameter[] parameters = new SessionParameterBuilder()


.withHostName("192.168.133.100")
.withUserName("pablo")
.withUserPassword("test")
.withPort(12300)
.build(server.getOrb());

Otra instancia del servicio de persistencia que quiera acceder al mismo repositorio creado
anteriormente, deber utilizar parmetros como los mostrados en el cuadro anterior. Se asume que la
direccin de Internet, donde se cre el repositorio inicialmente es 192.168.133.100.

116

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

REFERENCIAS
PSS01 Persistence State Service V2.0 OMG 2002. http://www.omg.org/cgi-bin/doc?formal/0209-06
TS01 - Transaction Service Specification, OMG
2003.http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
CORBA01 Common Object Request Broker Architecture, Core Specification OMG.
http://www.omg.org/technology/documents/corba_spec_catalog.htm
JVMTI01 Java Virtual Machine Tool
http://java.sun.com/j2se/1.5.0/docs/guide/jvmti

2004.

JVMI01 Java Virtual Machine Instrumentation SUN Java 5


http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/Instrumentation.html

2004.

IDL2Java

IDL

to

Java Language

Mapping

interface

Specification.

SUN

Java

http://www.omg.org/cgi-

bin/doc?formal/02-08-05
CorbaJava00 CORBA Technology and the Java (TM) 2 Platform Standard Edition.
http://java.sun.com/j2se/1.5.0/docs/guide/idl/corba.html
Garshol00 BNF and EBNF: What are they and how do they work?, Lars Marius Garshol.
http://www.garshol.priv.no/download/text/bnf.html
CooperRice00 Engineering A Compiler, Keith Cooper - Rice University, Houston, Texas; Linda
Torczon - Rice University, Houston, Texas http://www.cs.rice.edu/~keith/
Javacc00 Java Compiler Compiler [tm] (JavaCC [tm]) - The Java Parser Generator.
https://javacc.dev.java.net/
JavaccTu00 The JavaCC Tutorial, Theodore S. Norvell http://www.engr.mun.ca/~theo/JavaCCTutorial/
Crenshaw00 Let's Build a Compiler, by Jack Crenshaw http://compilers.iecc.com/crenshaw/
Dasgupta00 Algorithms, S. Dasgupta, C. H. Papadimitriou, and U. V. Vazirani. July 18, 2006.
Gamma01 Design Patterns: Elements of Reusable Object-Oriented Software - Addison-Wesley
Professional Computing Series - by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
January 15, 1995.
BM0 Meyer, Bertrand. Object-Oriented Software Construction. Prentice Hall, 1997. ISBN 013-629155-4.
GrandM01 Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd
Edition, Volume 1, by Mark Grand. Wiley; September 17, 2002. ISBN-10: 0471227293.
KingG01 Hibernate in Action, Christian Bauer, Gavin King; Manning, 2005. ISBN: 1932394-15-X.
http://www.hibernate.org
RoodsR01 Java Data Objects, Robin M. Roods; Addison-Wesley, 2003. ISBN 0-321-12380-8.
http://java.sun.com/javaee/technologies/jdo

117

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

ReverbelF01 Persistence in Distributed Object Systems: ORB/ODBMS Integration, Francisco


Reverbel. Ph.D. Dissertation Presented to the Computer Science Department of the University of
New Mexico. April 1996.
NewardT01 Avoiding the Quagmire Offering solutions to the problems of Object/RelationalMapping by Ted Neward. May 21th, 2007. http://www.odbms.org/experts.html#article12
CookWR01 Native Queries for Persistent Objects. A Design White Paper. William R. Cook.
Department of Computer Sciences, The University of Texas. Febraury 15th,
2006.http://www.cs.utexas.edu/users/wcook/papers/NativeQueries/NativeQueries8-23-05.pdf
Castor01 Castor Open Source data binding framework for Java. http://www.castor.org
Toplink01 Oracle TopLink, Oracle Fusion Middleware
http://www.oracle.com/technology/products/ias/toplink/index.html

family

of

products.

CKA01 - Surviving Object-Oriented Projects, By Alistair Cockburn, Dec 22, 1997, Addison Wesley
Professional. Part of The Agile Software Development Series.
DBO401 Database for Objects. http://www.db4o.com/about/productinformation
SODA01 Simple Object Database Access. http://sodaquery.sourceforge.net
Cache01 InterSystems Cach high-performance object database.
http://www.intersystems.com/cache/index.html
Annotations01 Java 5.0 Annotations.
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
Conc01 The origin of concurrent programming: from semaphores to remote procedure calls
book contents. ISBN:0-387-95401-5, Center for Science and Technology, Syracuse University,
Syracuse, NY. Edsger W. Dijkstra, Per Brinch Hansen, C. A. R. Hoare
RoySeif01 Concepts, Techniques, and Models of Computer Programming, by Peter Van Roy and
Seif Haridi. The MIT Press Cambridge, Massachusetts London, England. ISBN 0-262-22069-5
GrayReuter01 - Transaction Processing: Concepts and Techniques by Jim Gray, Andreas Reuter ,
1993 Morgan Kaufmann. ISBN 1558601902
DEVQTC01 Developing Quality Technical Information. A handbook for Writers and Editors.
Second Edition. G. Hargis, M. Carey, A. Hernandez, P. Hughes, D. Longo, S. Rouiller, E. Wide. ISBN
0-13-1477490.

118

PSS-PMI Mi servicio de estado persistente

Pablo M. Ilardi

REFERENCIAS A BIBLIOTECAS
Jakarta Commons http://commons.apache.org/
Jakarta Commons Logging http://commons.apache.org/logging/
Jakarta Commons Collections http://commons.apache.org/collections/
Jakarta Commons Jexl http://commons.apache.org/jexl/
Hibernate http://www.hibernate.org/
JDO http://java.sun.com/jdo/
Db4o Database For Objects , http://www.db4o.com/
Javacc Java Compiler Compiler, https://javacc.dev.java.net/
JJTree https://javacc.dev.java.net/doc/JJTree.html
Junit http://www.junit.org/
Janino An Embedded Java Compiler, http://www.janino.net/
Eclipse http://www.eclipse.org/

119

120

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

COMPARACIN CON OTRAS IMPLEMENTACIONES DEL SERVICIO DE ESTADO


PERSISTENTE DE CORBA
Servicios a Comparar ..............................................................................................123
OpenORB ............................................................................................................123
OpenCCM ............................................................................................................124
Puntos de Comparacin ..........................................................................................124
Comparacin entre OpenORB, OpenCCM y mi servicio ..........................................125
Compatibilidad con el estndar ...........................................................................125
Nivel de dependencia con la ORB ........................................................................127
Conectores disponibles y caractersticas de los mismos .......................................127
Requerimientos y facilidad de uso .......................................................................127
Extensibilidad para la creacin de nuevos conectores..........................................128
Conclusiones ...........................................................................................................128
Referencias .............................................................................................................130

121

122

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

ado que PSS no es uno de los servicios CORBA ms difundidos, existen pocas implementaciones,
y especialmente en Java. Cuando se habla de una implementacin de CORBA, generalmente se
est hablando de implementaciones de la ORB. Todas las implementaciones proveen adems de
la ORB, implementaciones de los servicios bsicos, como puede ser el NameService y algunas en
particular ofrecen implementaciones del PSS.
Mi proyecto no contempla la creacin de una ORB, ya que hay muchas implementaciones de
ella, sino se propone integrar el servicio con, idealmente, cualquier implementacin de la ORB en Java.
He probado mi servicio, con dos implementaciones de ORB: la de SUN para Java que trae la mquina
virtual y la ORB de JacORB [JACORB01]. JacORB es una implementacin en cdigo abierto del
Departamento de Ciencias de la Computacin de la Universidad de Freie en Berln, Alemania.
Ninguna de las dos ORBs con las que he probado mi servicio, tienen implementaciones de PSS, y
por ende, constituyeron un buen escenario para integrar mi servicio con ellas.

SERVICIOS A COMPARAR
De las pocas implementaciones existentes, para realizar la comparacin he elegido las dos ms
representativas: OpenORB [OPENORB01] y OpenCCM [OPENCCM01].

OPENORB
OpenORB (u ORB abierta) es una implementacin de la ORB de CORBA, basada en una ORB
anterior, escrita totalmente en Java, y llamada JavaORB (que actualmente se encuentra discontinuada).
Esta ORB fue construida por el grupo de personas llamado Distributed Object Group (Grupo de Objetos
Distribuidos) [DOG01], que se dedica a proveer tecnologa CORBA de cdigo abierto. Uno de los servicios
que provee OpenORB es el servicio de estado persistente que utilizar para la comparacin. Segn la
documentacin de este servicio, provee una implementacin totalmente compatible con la especificacin
PSS de CORBA.
OpenORB provee tres conectores para el servicio: conector de memoria sin soporte
transaccional, otro conector con soporte de archivos donde se almacena el estado persistente con
soporte transaccional y un tercer conector que utiliza una base de datos relacional para almacenar el
estado persistente del repositorio. Este ltimo conector requiere un proveedor de base de datos
relacional, que se encuentra fuera del control del servicio. Al tratarse de una dependencia no controlada
por el servicio, la aplicacin CORBA requiere tener configurada una base de datos relacional para poder
utilizar esta implementacin del servicio.
Segn la documentacin, este servicio requiere utilizar su propia implementacin de ORB y su
servicio de Transacciones OTS, tambin provisto por este grupo.
El servicio provee un compilador PSDL, que se invoca mediante un script por lnea de comandos.
El servicio no soporta persistencia transparente, slo se puede utilizar el servicio mediante una definicin
PSDL compilada por su propio compilador.
La configuracin se realiza a travs del mecanismo de configuracin de la ORB provista por
OpenORB, lo que lo hace completamente dependiente de ella. Esta configuracin tambin incluye los
parmetros de uso de los conectores de base de datos relacional y de archivos, dejando sin uso a los
parmetros de construccin de la sesin.
En cuando a las posibilidades de extensin, la documentacin slo trata la interaccin con el
servicio por un usuario del mismo. De todas formas, el cdigo fuente es libre y se lo puede analizar. El
compilador de PSDL que utiliza, est basado en el compilador de OpenORB para el que est definido el

123

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

servicio. Para agregar un nuevo conector es necesario modificar el cdigo del servicio, ya que ste no
provee configuracin alguna que permita un comportamiento dinmico del compilador. El compilador
slo genera cdigo para sus tres conectores. De manera anloga, el servicio tampoco soporta registro
dinmico de conectores, lo que obliga a modificar el cdigo para agregar un nuevo conector.

OPENCCM
OpenCCM tambin surge de JavaORB, pero no se trata de una implementacin de ORB, sino de
una implementacin del modelo de componentes de CORBA [CCM01]. Una parte de CCM es la ORB que
se utiliza internamente y en este caso se trata de JacORB. Al tratarse de un contenedor de componentes,
de acuerdo a la especificacin de CORBA, es posible tambin combinarlo con el servicio de estado
persistente PSS. OpenCCM provee su propia implementacin de PSS.
Este servicio provee dos conectores de funcionalidades similares. El primero es un conector que
utiliza al framework Hibernate [KingG01] para almacenar el estado en una base de datos relacional.
Hibernate es una herramienta de mapeo de objetos a bases de datos relacionales. El otro conector utiliza
a la API de SUN, para persistencia de objetos llamada JDO (Java Database Object) [RoodsR01]. Si bien el
servicio provee dos conectores, se debe definir en tiempo de compilacin del servicio cual conector se
utilizar, lo que deja en la prctica un nico conector posible en tiempo de ejecucin. El servicio est muy
acoplado a la implementacin de la ORB y al contenedor de componentes. No me fue posible configurar
el conector de Hibernate en mis pruebas, slo logr hacerlo funcionar con JDO.
Tanto JDO como Hibernate requieren del uso de una base de datos relacional. De todas formas
Hibernate provee herramientas para utilizar una base de datos incrustada en el proceso donde se lo
utilice, como por ejemplo HypersonicSQL [HSQLDB01] que est realizada completamente en Java.
La posibilidad de extensin est dada en el momento de compilacin del servicio, pero est muy
acoplada al modelo de construccin de componentes y servicios que provee OpenCCM.

PUNTOS DE COMPARACIN
Las caractersticas que he comparado con estas dos implementaciones del servicio son:
1. Compatibilidad con el estndar
Se evala el grado en que se respetan los requerimientos impuestos por el estndar con respecto
a los requerimientos del mismo, tales como claves mltiples, construcciones de PSDL, generacin de
cdigo Java, funcionalidades del compilador, etc.
2. Nivel de dependencia con la ORB
Se evala la dependencia de la implementacin del servicio con respecto a la ORB para la que se
promueve su utilizacin.
3. Conectores disponibles y caractersticas de los mismos
Este punto es quizs, el ms importante desde la perspectiva de un usuario del servicio. Se
evalan los conectores que provee el servicio, sus requerimientos y funcionalidades que proveen.
4. Requerimientos y facilidad de uso
Otro punto importante para un usuario final son los requerimientos que impone el uso de un
determinado servicio o conector, y los conocimientos y recursos de los cuales debe disponer un nuevo
usuario.
5. Extensibilidad para la creacin de nuevos conectores
Finalmente este punto trata de evaluar las posibilidades y limitaciones para la extensin del
servicio, ya sea mediante un nuevo conector o modificando el servicio.

124

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

COMPARACIN ENTRE OPENORB, O PENCCM Y MI SERVICIO


COMPATIBILIDAD CON EL ESTNDAR
Uno de los puntos destacados de la especificacin de CORBA es la unicidad de interfases entre
distintas implementaciones del servicio. Esto implica que todos los servicios debern generar el mismo
cdigo para las mismas definiciones abstractas compiladas.
OpenORB, genera cdigo de interfases incompatible con la especificacin, dado que no respeta
el mapeo de las referencias. De acuerdo a la especificacin, el mapeo de Java define que las referencias
se deben traducir a byte[] y para C++, a clases llamadas EntidadRef, donde Entidad es el tipo del objeto
almacenado. En OpenORB, las referencias se traducen en clases EntidadRef, es decir que utilizaron el
mapeo de C++ en Java. Al definir una clase particular para la representacin de las referencias, da como
resultado que el cdigo generado por su compilador sea muy distinto al esperado por la especificacin.
// En OpenORB
public void adress( org.objectweb.openccm.pss.demo1.AddressRef arg );
// En mi compilador
public abstract void adress(byte[] br);

OpenCCM, tampoco respeta las interfases. De acuerdo a la especificacin, las interfases que
representen objetos almacenados debern heredar de la interfase StorageObject de CORBA. Sin embargo
en
OpenCCM,
heredan
de
una
interfase
definida
por
ellos:
org.objectweb.openccm.pss.runtime.common.api.StorageObject, que a su vez hereda de
StorageObject. Dicha interfase agrega un mtodo inicialize, que es utilizado para indicarle al objeto el
almacn al que pertenece.
// En OpenCCM
public interface Person extends
org.objectweb.openccm.pss.runtime.common.api.StorageObject
// En mi compilador
import org.omg.CosPersistentState.StorageObject;
public interface Person extends StorageObject

En cuanto a la generacin de almacenes abstractos, OpenORB y mi compilador generan cdigo


muy similar, pero OpenCCM genera cdigo totalmente incompatible con CORBA.
// En OpenCCM
public interface PersonHome
extends org.omg.CosPersistentState.StorageHomeBase
// En mi compilador (similar en OpenORB)
public interface PersonHome extends PersonHomeOperations,
StorageHomeBase

LocalInterface,

IDLEntity,

OpenCCM no genera interfases para las operaciones del almacn. Todas las operaciones estn
declaradas dentro de la misma interfase del almacn. Tampoco genera las clases de utilidad como Holder
y Helper que requiere CORBA para una interfase. OpenCCM no genera interfases CORBA vlidas.
Considero que es un problema importante que no se respete el estndar a nivel de interfase,
dado que expone la implementacin de un servicio CORBA al usuario del mismo, sin permitir un
intercambio directo de implementaciones entre distintos proveedores del servicio. La independencia de
la implementacin es una de las caractersticas ms importantes de las especificaciones CORBA.

125

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

En cuanto al compilador, tanto OpenCCM como OpenORB, proveen soporte de preprocesador,


que permite darle directivas al procesador de cdigo. Por ejemplo, se puede definir un mdulo con un
nombre simple para traducirlo en Java a un paquete ms complejo con varios niveles de nombre. En el
caso de mi compilador, slo soporta la directiva al preprocesador para incluir archivos externos en el
proceso de compilacin.
Una caracterstica que slo posee mi compilador, es la optimizacin de los nombres de clase
utilizados. En Java se puede referenciar a una clase por su nombre completo (incluyendo el paquete), o
por su nombre importando el nombre completo en el archivo, si es que la clase se encuentra definida en
otro paquete Java. Si la misma clase se utiliza en muchos lugares del cdigo, es recomendable importarlo,
para poder referenciarla simplemente con su nombre en todos esos lugares. Mi compilador genera
cdigo optimizado, importando las clases utilizadas cuando sea necesario y slo utiliza el nombre
completo de la clase cuando exista otra clase utilizada en el mismo archivo pero definida en otro paquete.
En el caso de OpenORB y OpenCCM, se utiliza el nombre completo siempre, incluso cuando la clase
referenciada se encuentra dentro del mismo paquete Java.
// En OpenORB o OpenCCM
public org.objectweb.openccm.pss.demo1.Address adress();
public void adress( org.objectweb.openccm.pss.demo1.Address arg );
// En mi compilador
public abstract Address adress();
public abstract void adress(Address b);
Tanto en el caso de OpenORB como OpenCCM, sus respectivos compiladores generan cdigo
para las construcciones IDL definidas en el archivo PSDL compilado, mi compilador no lo hace, tan solo las
ignora.
En cuanto a la generacin de clases concretas, si bien queda fuera del alcance de la
especificacin, existen algunas caractersticas importantes. Mi compilador y el de OpenORB generan
objetos almacenados que slo implementan interfases, mientras que OpenCCM obliga a heredar de una
clase interna del conector. Adems OpenCCM tambin obliga a implementar una interfase de JDO,
exponiendo totalmente los detalles de la implementacin del conector, que en este caso logra la
persistencia por medio de JDO. En el caso de OpenORB, se implementan interfases propias del conector,
mientras que el caso de mi servicio solo se implementa una interfase definida por el servicio, ocultado los
detalles del conector que se est utilizando.
// En OpenCCM
public abstract class ST_Person
extends org.objectweb.openccm.pss.runtime.jdo.lib.StorageObjectBase
implements org.objectweb.openccm.pss.demo1.Person,
javax.jdo.InstanceCallbacks
// En OpenORB
public abstract class ST_Person implements
org.objectweb.openccm.pss.demo1.Person,
org.openorb.pss.connector.memory.PersistentObject
// En mi compilador
public abstract class ST_Person implements
Person, StorageObject, ExtendedStorageObject
Como resultado de esta comparacin, se puede decir que tanto OpenORB como OpenCCM
generan interfases incompatibles con la especificacin CORBA por los motivos expuestos. De todas
formas, OpenCCM tiene un mayor grado de incompatibilidad al exponer interfases propias de su

126

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

implementacin e ignorar la definicin de interfases para almacenes. Mi compilador est en desventaja al


no generar construcciones IDL, aunque genera cdigo ms optimizado para las construcciones PSDL y
compatible con la especificacin CORBA.

NIVEL DE DEPENDENCIA CON LA ORB


OpenORB requiere la configuracin del servicio por los mismos mecanismos que usa para
configurar su implementacin de ORB. Esto implica que slo se puede utilizar el servicio con esta
configuracin, y por ende, con una implementacin particular de la ORB. A nivel de cdigo fuente, es
tambin dependiente de la implementacin de la ORB. Esto se debe principalmente a que se reutilizaron
muchas utilidades / funcionalidades entre los distintos servicios que esta ORB provee.
En cuanto a OpenCCM, la documentacin menciona explcitamente que se requiere de
OpenCCM para que el servicio funcione correctamente.
En conclusin, mi servicio es el nico que soporta distintas ORBs. La dependencia de una ORB en
el contexto de la implementacin completa de una ORB, no es necesariamente una mala cualidad, dado
que la dependencia permite un grado ms alto de reutilizacin de componentes entre servicios. Por
ejemplo, es una gran ventaja no tener que volver a implementar el compilador desde cero para cada
lenguaje que requiera cada servicio, si el compilador IDL de la ORB permite extensiones al lenguaje, tal
como PSDL.

CONECTORES DISPONIBLES Y CARACTERSTICAS DE LOS MISMOS


El servicio de OpenORB es el que provee mayor nmero de conectores, tres conectores. El
conector de memoria es equivalente a mi conector de memoria con las mismas funcionalidades. Tanto el
conector de archivos, como el de base de datos, proveen integracin con el servicio de transacciones.
Ninguno de los dos conectores hace referencia a acceso remoto al repositorio.
OpenCCM provee solo dos conectores con las mismas funcionalidades, la nica diferencia entre
ellos, es la biblioteca que utilizan para persistir los objetos almacenados. De todas formas, el servicio
solamente funciona con uno de los conectores por vez, debido a la configuracin que requiere la ORB
para habilitarlos. OpenCCM provee integracin con su implementacin del servicio de transacciones de
CORBA. Al igual que OpenCCM, tampoco hace referencia al acceso remoto del repositorio.
Analizando el cdigo fuente de OpenORB, se deduce que no tiene soporte para compartir el
repositorio entre ms de un servicio. No implementa ningn mecanismo para la generacin de
identificadores, que contemple otro proceso adems del propio. Para la generacin de identificadores
utiliza la hora de la mquina en la cual se est ejecutando el proceso que genera el identificador nico.
En el caso de OpenCCM, se utilizan los mecanismos que proveen tanto Hibernate como JDO para
la generacin de identificadores, mediante alguna traduccin a los identificadores que requiere el servicio
de estado persistente. Estos mecanismos se basan en la generacin de identificadores mediante una
secuencia o algn valor auto incrementado que provea la base de datos relacional que se utilice en
conjunto con el servicio.

REQUERIMIENTOS Y FACILIDAD DE USO


En el caso de OpenORB, tanto el conector de memoria como el de archivos, no tienen
requerimientos adicionales, slo se debe configurar el servicio. En el caso del conector de base de datos
relacional, se requiere tener una base datos operativa para poder utilizar el servicio.
OpenCCM requiere de una configuracin adicional para poder utilizar el servicio. Primero se
debe identificar el tipo de conector que ser utilizado y luego, tanto para el caso del conector de JDO

127

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

como para el de Hibernate, es necesario crear y administrar la base datos con la cual se utilizar el
servicio, antes de poder utilizar el servicio mismo.
Tanto OpenORB como OpenCCM requieren de la intervencin explcita del usuario para poder
utilizar el conector de base de datos relacional. El usuario debe agregar tambin el driver de conexin
para la base datos que decida utilizar.
En el caso de mi servicio, no se requiere ninguna configuracin adicional para que funcione el
servicio o los conectores. Solamente requiere los parmetros necesarios para la creacin de la sesin de
trabajo. A diferencia de los otros dos servicios, mis conectores no exponen los detalles de
implementacion de los mismos para su configuracin. Cuando se utiliza el conector para DB4O, el usuario
no sabe realmente cmo y con qu se estn persistiendo los objetos.

EXTENSIBILIDAD PARA LA CREACIN DE NUEVOS CONECTORES


OpenORB no prev la existencia de nuevos conectores. Su registro de conectores debe conocer
los tipos de conectores que provee el servicio. Para agregar nuevos conectores es necesario modificar el
cdigo fuente del servicio y recompilarlo.
OpenCCM tiene muy bien desacoplado el concepto de interfase e implementacin. Se puede
configurar mediante modificaciones al script que compila el servicio indicndole el tipo de conector que
se utilizar. El proceso de compilacin buscar un directorio para la interfase y otro para la
implementacin con el nombre del conector configurado. De todas formas, esta configuracin est muy
ligada al proceso de compilacin ya que no se realiza en tiempo de ejecucin.
Mi servicio de persistencia es el nico que provee una configuracin en tiempo de ejecucin de
los conectores que estarn disponibles. Para agregar un nuevo conector no se requiere recompilar el
servicio, sino solamente compilar el nuevo conector y agregar las lneas de configuracin para el servicio.
El registro de conectores est completamente desacoplado de las implementaciones de conectores.

CONCLUSIONES
Un punto que est fuera de la comparacin es la cantidad de personas involucradas en el
proyecto. Tanto en OpenORB como OpenCCM, los proyectos estn constituidos por mltiples personas y
adems, al contar con el soporte de una ORB, tienen muchas utilidades que se puede reutilizar en el
servicio. En mi caso se trat de un proyecto de una nica persona.
Desde el punto de vista de la extensibilidad creo que mi servcio es el ms apto de los tres, dado
que es el que permite mayor grado de configuracin sin recompilar y tambin es el nico que no expone
detalles de implementacin de los conectores. Mi compilador de PSDL est en desventaja al no generar
cdigo fuente para las construcciones IDL, esta debe ser la primer tarea a encarar en un trabajo futuro
sobre el servicio. Implementar la integracin con algn servicio de transacciones de CORBA (TTS) tambin
es una caracterstica que sera importante agregar. Desde el punto de vista funcional los tres servicios
proveen funcionalidades similares (salvo por la integracion con TTS). En relacin a la correctitud de los
requerimientos de la especificacin, creo que mi servicio es el ms apto, ya que es el nico que segn mi
interpretacin del estndar, lo respeta. La independencia de la ORB es un objetivo propio de mi trabajo y
no tiene porque estar soportado por otros servicios.
Ninguna de las implementaciones del servicio que he analizado, tanto en Java como en C++,
incluyendo la ma, proveen soporte para persistencia transparente. Esto creo que se debe principalmente
a que no est bien resuelto por la especificacin, y en el modelo de trabajo de CORBA es comn requerir
de un compilador de un lenguaje genrico a un lenguaje concreto.

128

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

Finalmente, el acceso remoto al repositorio es tambin una caracteristica que est fuera del
alcance de la especificacin y que en las otras implementaciones del servicio est solo resuelta
parcialmente por el uso de una base de datos relacional.
La forma de accesso remoto propuesta tiene como desventaja que no permite independecia de
la ubicacin, ya que depende directamente de la ubicacin donde se cre el repositorio. De todas
formas, la ubicacin del repositorio es slo necesaria al momento de crear la sesin de trabajo y es ste el
nico punto donde est expuesta. Este grado de desacoplamiento de la ubicacin permite migrar el
repositorio en forma manual y relativamente sencilla, poniendo la ubicacin fsica del repositorio en una
configuracin externa a la aplicacin.
A continuacin expongo una tabla comparativa entre las distintas caractersticas analizadas y los
tres servicios de estado persistente comparados.

Caracterstica \ Servicio

OpenORB

Respeta el estandar
No
Depende de una ORB
Si
Candidad de Conectores
3
Complejidad de Uso
Media
Requiere adicionales
BDR + Driver
Extensibilidad
Baja
Soporte de transacciones
Corba TSS
Compilador
IDL + PSDL
Persistencia Transparente
No
Acceso Remoto
No
Expone implementacin Si, x BD Relacional
Candidad de Personas
+3

OpenCCM

PMI-PSS

No
Si
2(uno x vez)
Alta
BDR + Driver
Media
Corba TSS
IDL + PSDL
No
x BD Relacional
Si, x BD Relacional y JDO
Consorcio de Software

Si
No
2
Baja
No
Alta
Solo x DB4O
PSDL
No
x Conector Persistente
No
1(Yo)

COMPARACIONES 1 - TABLA COMPARATIVA

129

Comparacin con otras implementaciones del servicio de estado persistente

Pablo M. Ilardi

REFERENCIAS
JACORB01 JacORB: Software Engineering and Systems Software Group, at the CS department of
Freie Universitt Berlin, Germany. www.jacorb.org
OPENORB01 The Community OpenORB, www.openorb.org
DOG01 Distributed Object Group. dog.team.free.fr
OPENCCM01 OpenCCM
openccm.objectweb.org

The

Open

CORBA

Component

Model

Platform.

CCM01 CORBA Component Model (CCM) Specification, OMG.


http://www.omg.org/technology/documents/formal/components.htm
KingG01 Hibernate in Action, Christian Bauer, Gavin King; Manning, 2005. ISBN: 1932394-15-X.
http://www.hibernate.org
RoodsR01 Java Data Objects, Robin M. Roods; Addison-Wesley, 2003.ISBN 0-321-12380-8.
http://java.sun.com/javaee/technologies/jdo
HSQLDB01 HSQLDB a relational database engine written in Java, with a JDBC driver, supporting a
large subset of ANSI-92 SQL. hsqldb.sourceforge.net

130

Trabajos Adicionales

Pablo M. Ilardi

TRABAJOS ADICIONALES
PSS tiene algunas limitaciones en su modelo que podran ser incorporadas en un futuro. La
principal es la posibilidad de hacer consultas complejas. La nica alternativa de consultas que se plantea
en PSS es mediante consultas por las claves de los objetos en los almacenes. Existen situaciones reales en
las que se quieren realizar consultas ms avanzadas sobre los objetos, por atributos que no son parte de
la clave necesariamente o por condiciones complejas. Este tipo de consultas estn bien resueltas en la API
de SODA en la que se basa uno de los modos de consulta de DB40.
Existe otra limitacin importante de PSS, que es el manejo de colecciones. En PSS la nica forma
de manejar una coleccin como atributo / estado de un objeto almacenado, es mediante un array de
objetos almacenados, lo que se logra mediante una definicin IDL de un arreglo de objetos almacenados.
Si bien es suficiente para almacenar ms de un objeto como estado, el lenguaje Java provee posibilidades
mucho ms avanzadas para el manejo de colecciones, tales como colecciones con semntica de conjuntos
o colecciones indexadas. El tratar con un array plano de objetos hace que se requiera la construccin de
operaciones que ya estn definidas en el lenguaje en forma nativa para poder utilizarlas con el modelo de
PSS. Esta limitacin concretamente se debe a que PSS es una especificacin multilenguaje,
particularmente para Java y C++. Esto requiere que las funcionalidades provistas deban ser soportadas
por todos los lenguajes de forma relativamente simple y en el caso de C++, los arrays son las nicas
construcciones nativas que se soportan para el manejo de colecciones.
Mi implementacin en particular requiere agregar al compilador de PSS la posibilidad de generar
construcciones IDL para permitir interactuar a los objetos almacenados con ellas, por ejemplo, mediante
atributos / estados que sean tipos definidos en IDL directamente.
De acuerdo a la especificacin PSS, existen dos caractersticas opcionales, que son persistencia
transparente y soporte transaccional. Si se provee persistencia transparente, se dice que el servicio es: "a
compliant Persistent State Service implementation with transparent persistence support", o una
implementacin del servicio de estado persistente compatible con soporte de persistencia transparente.
Y si provee soporte transaccional es: a compliant Persistent State Service implementation with
transaction support o una implementacin del servicio de estado persistente compatible con soporte de
transacciones. Mi servicio no provee ninguna de estas dos caractersticas adicionales, por lo que son
buenos candidatos de futuros trabajos.

131

132

ndice de Grficos

Pablo M. Ilardi

NDICE DE GRFICOS
FUNCIONAMIENTO DEL SERVICIO DE ESTADO P ERSISTENTE
Grfico 1 - Interaccin con la ORB _______________________________________________________
Grfico 2 - MODELO LGICO ___________________________________________________________
Grfico 3 - Sesin para acceder al DataStore _______________________________________________
Grfico 4 - Herencia Diamante de interfases en CORBA ______________________________________
Grfico 5 - Tipos y Modelo de Herencia en PSS _____________________________________________
Grfico 6 - Acceso al servicio ___________________________________________________________

33
34
34
35
36
37

COMPILADOR
Compilador 1 - Proceso de Compilacin ___________________________________________________
Compilador 2 - Primer Paso ____________________________________________________________
Compilador 3 - Javacc ________________________________________________________________
Compilador 4 - Diagrama general del Compilador___________________________________________
Compilador 5 - Fases del compilador _____________________________________________________
Compilador 6 - Nodos de rbol__________________________________________________________
Compilador 7 - Primera Fase ___________________________________________________________
Compilador 8 - Exepciones de Validacin __________________________________________________
Compilador 9 - Tres Partes _____________________________________________________________
Compilador 10 - Qu generar ___________________________________________________________
Compilador 11 - Generacin de archivos __________________________________________________
Compilador 12 - Cmo generarlo ________________________________________________________

53
54
56
58
60
63
64
68
69
70
71
72

DISEO DEL SERVICIO DE ESTADO P ERSISTENTE


Diseo del Servicio 1 - Configuracin de la ORB_____________________________________________ 76
Diseo del Servicio 2 - Conectores _______________________________________________________ 78
Diseo del Servicio 3 - PSDLUtils_________________________________________________________ 79
Diseo del Servicio 4 - Parameters _______________________________________________________ 80
Diseo del Servicio 5 - Conector y Sesiones ________________________________________________ 82
Diseo del Servicio 6 - Modelo base de almacenes __________________________________________ 83
Diseo del Servicio 7 - DElegacin _______________________________________________________ 84
Diseo del Servicio 8 - Objetos Alamacenados ______________________________________________ 85
Diseo del Servicio 9 - Restricciones de Claves ______________________________________________ 89
Diseo del Servicio 10 - Esquema General del Conector Temporal ______________________________ 90
Diseo del Servicio 11 - Generacin de identificadores _______________________________________ 91
Diseo del Servicio 12 - Modelo de DB4O _________________________________________________ 96
Diseo del Servicio 13 - Modelo de consultas S.O.D.A ________________________________________ 98
Diseo del Servicio 14 - Configuracin de DB4O ____________________________________________ 99
Diseo del Servicio 15 - Conexin para acceso a la base de datos ______________________________ 100
Diseo del Servicio 16 - Generacin atomica de identificadores _______________________________ 102
Diseo del Servicio 17 - Esquema general del conector persistente_____________________________ 103
Diseo del Servicio 18 - Acceso remoto a los repositorios ____________________________________ 105
Diseo del Servicio 19 - Aplicacin CORBA con accesso a PSS _________________________________ 114

COMPARACIN CON OTRAS IMPLEMENTACIONES DE PSS


Comparaciones 1 - Tabla comparativa___________________________________________________ 129

133

134

Glosario

Pablo M. Ilardi

GLOSARIO
POO Programacin Orientada a Objetos u OOP Object Oriented Programming.
API Application programming interface o interfase de programacin de aplicaciones
IDE Integrated Development Environment o entorno de desarrollo integrado.
CORBA Common Object Request Broker Arquitecture o Arquitectura Comn para el Agente de Pedidos a
Objetos.
OMG Object Management Group o Grupo de Administracin de Objetos
OMA Object Management Architecture o Arquitectura para la Administracin de Objetos
ORB Object Request Broker o Agente de Pedidos a Objetos
Servant entidad programada en un lenguaje, que implementa uno o ms objetos CORBA. Se dice que
los servants, encarnan los objetos, porque proveen los cuerpos o implementaciones de los mismos. Los
servants, existen dentro del contexto de una aplicacin servidora. Dentro de un lenguaje de
programacin orientado a objetos, se trata de una instancia de un tipo de objeto.
IDL Interface Definition Language o Lenguaje de Definicin de Interfases. Lenguaje genrico de
definiciones utilizado por CORBA para permitir interconectar objetos implementados en diferentes
interfases.
PSS Persistent State Service o Servicio de Estado Persistente, servicio de CORBA para permitir almacenar
objetos en forma persistente para los servants.
RDBMS Relational Dabase Management System o Sistema de Administracin de Base de Datos
Relacional.
SQL Structured Query Language o Lenguaje Estructurado de Consultas utilizado para realizar consultas
en bases de datos Relacionales.
SQL3 Extensin al ANSI-SQL tambin llamado SQL 1999 que introdujo conceptos de los lenguajes
orientados a objetos.
OODBMS Object Oriented Dabase Management System o Sistemas de Administracin de Bases de
Datos Orientadas a Objetos
TS Transaction Service o Servicio de Transacciones de CORBA para realizar operaciones en contextos
trasaccionales.
PSDL Persistent State Definition Language o Lenguaje de Definiciones de Estado Persistente
Bytecode Cdigo de bytes utilizado internamente por la mquina virtual de Java.
Sistema Distribuido conjunto de computadoras independientes que se presentan al usuario del sistema
cmo una nica computadora. Desde la perspectiva de hardware, las mquinas o computadoras son
autnomas, y pero desde el punto de vista del software, el sistema se ve por el usuario como un todo.
BOA Basic Object Adapter o Adaptador Bsico de Objetos, especificacin descontinuada de CORBA que
permita invocar operaciones remotas definidas en lenguaje C ubicadas en diferentes ORBs.

135

Glosario

Pablo M. Ilardi

POA Portable Object Adapter o Adaptador Portable de Objetos, especificacin de CORBA que sucedi a
BOA y permiti ejecutar operaciones remotas ubicadas en diferentes ORBs e implementadas en cualquier
lenguaje.
OR - Object Reference o Referencia a Objeto, identifica un objeto CORBA, en forma unvoca. Le permite a
CORBA, identificar, ubicar y direccionar al objeto. Para los clientes, son entidades opacas que no pueden
ser modificadas ni creadas por ellos, las utilizan para dirigir los pedidos a los objetos. Identifican un nico
objeto CORBA.
GIOP General Inter ORB Protocol o Protocolo General Inter ORB, definicin abstracta de un protocolo
que permiti interconectar diferentes implementaciones de la ORB.
TCP/IP Transmission Control Protocol / Internet Protocolo, conjunto de protocolos, el primero sobre la
capa de transporte y el segundo sobre la capa de red, utilizados para comunicarse en Internet y la
mayora de las redes comerciales.
IIOP Internet Inter ORB Protocol o Protocolo Inter ORB sobre Internet, implementacin de GIOP
mapeada sobre TCP.
IOR Interoperable Object Reference o Referencia Interoperable a Objeto, referencia a objeto que es
entendible por todas las implementaciones de GIOP.
CCM CORBA Component Model o Modelo de Componentes de CORBA, nueva especificacin de CORBA
que promueve la construccin de sistemas mediante un modelo de componentes que extiende a las
interfases de CORBA.
RFP Request For Proposal o Pedido de Propuesta, consiste en el llamado a entidades a participar en la
creacin de una nueva especificacin.
POS Persistent Object Service o Servicio de Objetos Persistentes, especificacin descontinuada de
CORBA que fue reemplazada por PSS, utilizada para permitir persistir objetos en el entorno de una ORB.
StorageObject (PSS) Objeto almacenado, todo objeto que est definido en PSDL se define como "objeto
almacenado".
StorageHome (PSS) Almacn de PSDL donde se "almacenan" objetos de una familia definida por un tipo
base.
Singleton Patrn de diseo que define a un objeto del que slo puede existir una nica instancia en
forma simultnea.
Connector (PSS) Interfase que representa la implementacin del servicio de persistencia, mediante ella
se realizan las operaciones inciales sobre el servicio. Se obtiene una instancia invocando a un mtodo del
registro que devuelva la implementacin segn el tipo de conector solicitado.
ConnectorRegistry (PSS) "interfase/clase" que representa el registro de conectores de PSS, permite
obtener referencias a las implementaciones del servicio de persistencia (Conectores). El registro se
obtiene llamando al mtodo resolve_initial_references(PSS) de la ORB.
CatalogBase (PSS) Es un repositorio donde se encuentran los almacenes y objetos persistidos,
tcnicamente representa lo mismo que una sesin. Esta clase es abstracta, existen dos extensiones a la
misma, que son una sesin y un pool de sesiones. Toda instancia de home, sabe a qu catalogo
pertenece.

136

Glosario

Pablo M. Ilardi

TransactionalSession (PSS) Implementacin transaccional de una sesin.


SessionPool (PSS) Implementacin alternativa de CatalogBase, cuando se requiere trabajar con Pools
de conexiones.
CosPersistentState (PSS) es el nombre del mdulo (en C++ namespace) de servicio de estado
persistente.
NotFound (PSS) es una excepcin que es lanzada cuando se realiza una bsqueda para la que no se
obtiene el resultado esperado.
StorageType (PSS) es un string que define el tipo persistido, es la puerta de entrada al conector, para
obtener referencias a almacenes.
Pid (PSS) el pid de un objeto almacenado identifica unvocamente a un objeto dentro de un repositorio.
ShortPid (PSS) el short pid de cualquier objeto almacenado, identifica unvocamente a cualquier objeto
dentro de un mismo almacn.
Factory Method Patrn de diseo que permite centralizar la creacin de objetos en un mtodo en
funcin de los parmetros y estado del objeto que implemente el mtodo.
JVMTI JVM Tool Interface o Interfase de Herramientas para la Mquina Virtual, que permite configurar
agentes que podrn interceptar puntos de control utilizados para la creacin de objetos y carga de las
clases.
BNF Backus-Naur form, notacin para la definicin gramatical de lenguajes.
EBNF Extended Backus-Naur form, extensin a la notacin BNF que simplifica las definiciones recursivas.
BSD Berkely Software Distribution licencia de uso de software de tipo libre.
Backtracking Algoritmo que permite encontrar una solucin a un problema evaluando todas las posibles
soluciones.
Javacc Java Compile Compiler.
JJTree Pre procesador de Javacc utilizado para la generacin de rboles.
Builder Patrn de diseo que permite delegar en un objeto la construccin de otro objeto encapsulando
los detalles de la construccin en el builder.
Template Method Patrn de diseo que permite generalizar un algoritmo o comportamiento en un
mtodo de un objeto base, para luego ser adaptado o personalizado por subclases.
Marker Interface Patrn de diseo que permite marcar clases para definir que la misma cumple o no
con una caracterstica.
ORM Object Relation Mapping o Mapeo de Objeto - Relacin, definicin que se adapta a toda tcnica
de mapeo de objetos en un modelo relacional.
JDO Java Database Object, API de SUN para mapear un modelo de objetos en lenguaje Java a bases de
datos relacionales.
J2EE Java2 Enterprise Edition o Edicin empresarial de Java2.

137

Glosario

Pablo M. Ilardi

DDL Data Definition Language o Lenguaje de Definicin de Datos utilizado en las bases de datos
Relacionales.
DB4O Dabase For Objects o Base de Datos para Objetos
SODA Simple Object Data Base Access o Acceso Simple a Bases de Datos de Objetos.
JacORB Implementacin en Java de la ORB del Departamento de Ciencias de la Computacin de la
Universidad de Freie en Berln, Alemania.

138

También podría gustarte