Lenguaje para Definir Interacción entre Componentes: Caso ...

70
Lenguaje para Definir Interacción entre Componentes: Caso de Requerimientos No Funcionales en Gaita Tesis de Maestría en Ingeniería de Sistemas y Computación Presentado por: Gerson Johan Samaniego Rodríguez Asesora: Profesor Asociado: PhD. Rubby Casallas Universidad de los Andes Facultad de Ingeniería Departamento de Ingeniería de Sistemas y Computación Maestría en Ingeniería de Sistemas y Computación Julio, 2008

Transcript of Lenguaje para Definir Interacción entre Componentes: Caso ...

Page 1: Lenguaje para Definir Interacción entre Componentes: Caso ...

Lenguaje para Definir Interacción entre Componentes: Caso de Requerimientos No Funcionales en Gaita

Tesis de Maestría en Ingeniería de Sistemas y Computación

Presentado por:

Gerson Johan Samaniego Rodríguez

Asesora:

Profesor Asociado: PhD. Rubby Casallas

Universidad de los Andes Facultad de Ingeniería

Departamento de Ingeniería de Sistemas y Computación Maestría en Ingeniería de Sistemas y Computación

Julio, 2008

Page 2: Lenguaje para Definir Interacción entre Componentes: Caso ...

1

Lenguaje para Definir Interacción entre Componentes: Caso de Requerimientos No Funcionales en Gaita

Aprobado por:

_____________________________ Rubby Casallas Gutierrez _____________________________ Jorge Alberto Villalobos _____________________________ Víctor Hugo García Fecha de aprobación____________

Page 3: Lenguaje para Definir Interacción entre Componentes: Caso ...

2

CONTENIDO

1  Introducción.................................................................................................................... 5 

1.1  Resumen................................................................................................................... 5 1.2  Contexto................................................................................................................... 6 

1.2.1  Desarrollo de Software Basado en Componentes............................................. 6 1.2.2  Requerimientos No Funcionales....................................................................... 7 1.2.3  Desarrollo de Software orientado por Aspectos ............................................... 8 

1.3  Organización del Documento .................................................................................. 9 2  Descripción del Problema............................................................................................. 10 3  Objetivos....................................................................................................................... 12 4  Estado del Arte ............................................................................................................. 13 

4.1  Modelos de Componentes...................................................................................... 13 4.1.1  Enterprise Java Beans (EJB) .......................................................................... 13 4.1.2  CCM – CORBA Component Model .............................................................. 15 4.1.3  Fractal ............................................................................................................. 18 4.1.4  Arquitectura de Servicios Componentes (SCA)............................................. 20 

4.2  Gaita....................................................................................................................... 21 4.2.1  Componentes .................................................................................................. 22 4.2.2  Conectores ...................................................................................................... 22 4.2.3  Nodos.............................................................................................................. 22 4.2.4  Instancias de los elementos del modelo.......................................................... 22 4.2.5  Composición de Componentes ....................................................................... 23 4.2.6  Puntos de extensión ........................................................................................ 24 4.2.7  Niveles de Abstracción................................................................................... 24 4.2.8  Creación de componentes Gaita ..................................................................... 24 4.2.9  Identificación de los elementos del modelo ................................................... 25 4.2.10  Ciclo de Vida en Gaita ................................................................................... 26 4.2.11  Implementación de referencia: GaitaS V0 Engine ......................................... 27 4.2.12  Elementos que intervienen en el ciclo de vida ............................................... 28 4.2.13  Clientes de Gaita............................................................................................. 29 

4.3  AspectJ................................................................................................................... 29 4.4.  Trabajos Relacionados ........................................................................................... 31 

4.4.1  Componentes estándares para representar RNFs............................................ 32 4.4.2  Composición de componentes funcionales con servicios no funcionales ...... 32 4.4.3  Describiendo y usando aspectos no funcionales en CBA............................... 33 4.4.4  Aspect J2EE.................................................................................................... 34 4.4.5  Composición transparente y dinámica de aspectos ........................................ 35 4.4.6  FAC ................................................................................................................ 35 

5  Propuesta de Solución .................................................................................................. 37 5.1  Descripción General............................................................................................... 37 5.2  Lenguaje de Interacción: ISL................................................................................. 39 

5.2.1  Cuantificación basada en meta-data ............................................................... 40 5.2.2  Ejemplo Logging ............................................................................................ 40 5.2.3  Elementos del lenguaje................................................................................... 41 5.2.4  Tipos de interacción........................................................................................ 42 

Page 4: Lenguaje para Definir Interacción entre Componentes: Caso ...

3

5.2.5  Mediadores ..................................................................................................... 43 5.2.6  Ejemplo Sencillo de Seguridad ...................................................................... 45 

5.3  Resumen de la solución ......................................................................................... 47 6  Especificación del ISL.................................................................................................. 48 

6.1  Sintaxis y Semántica .............................................................................................. 48 6.1.1  Sintaxis Abstracta ........................................................................................... 48 6.1.2  Sintaxis Concreta............................................................................................ 49 6.1.3  Semántica del ISL........................................................................................... 50 

6.2  Especificación y uso de las propiedades................................................................ 52 6.2.1  Especificación................................................................................................. 53 6.2.2  Uso de la propiedad ........................................................................................ 53 

7  Motor de Interacción .................................................................................................... 55 8  Validación..................................................................................................................... 57 

8.1  Ciclo de Vida ......................................................................................................... 57 8.1.1  Componente no funcional ciclo de vida ......................................................... 58 8.1.2  Composición no funcional.............................................................................. 58 8.1.3  Propiedades en el ciclo de vida ...................................................................... 59 8.1.4  Interacción en el ISL....................................................................................... 60 8.1.5  Adaptación de clientes del componente ......................................................... 61 

8.2  Seguridad ............................................................................................................... 62 8.2.1  Introducción a JAAS ...................................................................................... 62 8.2.2  Componente No Funcional de Seguridad....................................................... 62 

9  Conclusiones................................................................................................................. 66 9.1  Aportes................................................................................................................... 66 9.2  Conclusiones .......................................................................................................... 66 9.3  Trabajo Futuro ....................................................................................................... 67 

Referencias ........................................................................................................................... 68 

Page 5: Lenguaje para Definir Interacción entre Componentes: Caso ...

4

LISTA DE FIGURAS

Figura 1: Aplicación Basada en Componentes............................................................... 6 Figura 2: Componente y sus interfaces ........................................................................... 7 Figura 3: Modelo Contenedor ............................................................................................ 8 Figura 4: Modelo Contenedor EJB.................................................................................. 13 Figura 5: Componente en CCM. Tomada de [12] ........................................................ 16 Figura 6: Arquitectura del Modelo Contenedor en CORBA [12] ................................ 17 Figura 7: Vista externa de un Componente Fractal [4] ................................................ 19 Figura 8: Vista interna de un Componente Fractal....................................................... 20 Figura 9: Arquitectura de Servicios Componentes [35] ............................................... 20 Figura 10: Componente en Gaita-S ................................................................................ 22 Figura 11: Conector en Gaita........................................................................................... 22 Figura 12: Instancia de componente en Gaita .............................................................. 23 Figura 13: Componente compuesto en Gaita-C ........................................................... 23 Figura 14: Gateways y Adaptadores en la red Gaita ................................................... 24 Figura 15: Instancias y Servicios Gaita .......................................................................... 27 Figura 16: Arquitectura de GaitaS V0 Engine ............................................................... 27 Figura 17: RNFs como componentes [22] ..................................................................... 32 Figura 18: Gaita-NF [12] ................................................................................................... 33 Figura 19: Contenedor por componente [7]................................................................... 34 Figura 20: Ejemplo del Aspecto Transacción en FAC [16] ......................................... 36 Figura 21: Composición con Componentes No funcionales....................................... 37 Figura 22: Ejecución de métodos sobre el nuevo componente CF’ .......................... 38 Figura 23: Mediador de la interacción ............................................................................ 39 Figura 24: Ejemplo de interacción y propiedades ........................................................ 40 Figura 25: Interacción básica........................................................................................... 42 Figura 26: Interacción básica + secuencia .................................................................... 42 Figura 27: Interacción compleja ...................................................................................... 43 Figura 28: Tipos de mediadores...................................................................................... 44 Figura 29: Componente final con seguridad ................................................................. 46 Figura 30: Resumen de la solución ................................................................................ 47 Figura 31: Motor de Interacción....................................................................................... 55 Figura 32: Generación de la red de componentes ....................................................... 56 Figura 33: Creación del Componente Compuesto ....................................................... 56 Figura 34: Múltiples manejadores de ciclo de vida ...................................................... 58 Figura 35: Componente con ciclo de vida ..................................................................... 59 Figura 36: Cliente externo del componente compuesto .............................................. 61 Figura 37: Interface del CNF de seguridad ................................................................... 63 Figura 38: Elementos que conforman el CNF de seguridad....................................... 63 Figura 39: Componente Final con Seguridad ............................................................... 65 

Page 6: Lenguaje para Definir Interacción entre Componentes: Caso ...

5

1 Introducción Este primer capítulo busca introducir al lector en los diferentes temas necesarios para afrontar la problemática y solución planteadas en éste trabajo. Empieza con un resumen del trabajo de tesis, seguido de un contexto de información básica e informal necesaria para continuar.

1.1 Resumen El paradigma de desarrollo de software basado en componentes (CBSE – Component Based Software Engineering) pretende mejorar varios aspectos de las aplicaciones como calidad, reutilización, mantenibilidad, etc. El CBSE parte de la descomposición de los sistemas en módulos independientes que se encapsulan en unidades llamadas componentes. Los componentes tienen interfaces bien definidas mediante las cuales se comunican unos con otros, y pueden componerse para formar componentes más grades o la misma aplicación. Generalmente son caracterizados y definidos en modelos de componentes.

Uno de los objetivos que busca el CBSE, es que se puedan integrar en una aplicación tanto componentes propios como de terceros, e inclusive, creados con diferentes tecnologías. Un escenario muy común se presenta cuando dos componentes “que no se conocen” se deben poner a interactuar, pero sin tener que modificar ninguno de ellos. El presente trabajo plantea la expresión de la interacción entre componentes de forma externa a ellos mediante un lenguaje de dominio específico orientado por aspectos llamado ISL (Interaction Specification Language).

El lenguaje es usado para solucionar el problema de incluir manejo de Requerimientos No Funcionales (RNF) en modelos de componentes. Incluir dicho manejo en una aplicación, de forma sencilla para el desarrollador, es una de las características que debería ofrecer el modelo. Lograr que el desarrollador se centre en el diseño e implementación de la lógica funcional permite obtener mejores resultados en las aplicaciones.

La estrategia para agregar soporte a RNFs, busca cumplir con algunas de las premisas del CBSE comúnmente establecidas, apoyándose en los principios y técnicas del Desarrollo de Software Orientado por Aspectos (AOSD). El AOSD busca separar las funcionalidades que cruzan toda la aplicación (Por ejemplo, algunos RNFs como: transacciones, seguridad, logging, etc.) y representarlas en unidades independientes llamadas Aspectos.

Una vez separadas las funcionalidades se deben encapsular en componentes, es decir, tanto la lógica funcional de la aplicación como los aspectos no funcionales deben ser componentes. Los componentes funcionales (CF) y los no funcionales (CNF) se componen para crear nuevos componentes que ofrecen los dos tipos de funcionalidades. Para poder unir un CF con un CNF es necesario

Page 7: Lenguaje para Definir Interacción entre Componentes: Caso ...

6

expresar la forma en que interactúan. La interacción la resuelve un nuevo componente mediador que cumple la función de interceptar las peticiones al CF para agregar la lógica no funcional que ofrece el CNF.

La interacción es expresada de forma externa a los componentes (usando sólo sus interfaces) mediante el lenguaje propuesto. El lenguaje permite definir los puntos exactos sobre el CF que se quieren interceptar para agregar la lógica no funcional.

La validación de la propuesta se realiza sobre el modelo de componentes Gaita [34], del grupo de Construcción de Software de la Universidad de los Andes.

1.2 Contexto

1.2.1 Desarrollo de Software Basado en Componentes

Las necesidades de los clientes en términos de software son cada día más complejas y cambiantes. Las tecnologías y metodologías de desarrollo deben evolucionar para suplir dichas necesidades. El desarrollo de software basado en componentes (CBSE) surge como un paradigma para crear aplicaciones con mayor calidad y de fácil mantenimiento [14]. Las aplicaciones deben ser descompuestas primero en módulos independientes que agrupen funcionalidades parecidas o afines. Posteriormente los módulos identificados se encapsulan en unidades de código llamadas componentes los cuales se comunican unos con otros por medio de sus interfaces o puertos [6].

La idea del CBSE en ingeniería del software al igual que en otras áreas (por ejemplo, en la electrónica donde se crean productos a partir del ensamble de partes), es la de poder crear aplicaciones a partir de componentes estándar propios o de terceros, o poder crear nuevos componentes a partir de la composición de otros ya existentes. Una aplicación basada en componentes (CBA) está formada por componentes ensamblados por sus interfaces.

Figura 1: Aplicación Basada en Componentes

Un componente es una pieza de código pre-elaborado que expone su funcionalidad a través de interfaces [3]. Su objetivo principal es la separación de código en unidades auto-contenidas para promover la reutilización. Por ser independientes, simplifican las pruebas facilitando la evaluación de su funcionalidad individualmente y mejoran la calidad de las aplicaciones [6].

Page 8: Lenguaje para Definir Interacción entre Componentes: Caso ...

7

Figura 2: Componente y sus interfaces

Los componentes son definidos en un Modelo de Componentes. El modelo define su estructura externa e interna y les da uniformidad [12]. En la actualidad existe una gran cantidad de modelos de componentes, entre los más comunes están: CCM [18], EJB [29], .Net [15], Fractal [4], SCA [35] etc.

Un componente debe cumplir con las siguientes premisas [3]: Auto-contenido: no depende de otros para realizar su función. Encapsulamiento: es accesible sólo a través de sus interfaces. Composición: se puede componer con otros para formar nuevos

componentes. Reutilización: se puede reutilizar en diferentes aplicaciones y en diferentes

composiciones. Independencia del contexto: se puede reutilizar en diferentes contextos Independencia de plataforma: no de pende plataforma en

hardware/software. Los modelos de componentes actuales buscan cumplir con esas premisas. Modelos como CCM y Fractal se acercan mucho al objetivo, pero al tratar de cumplir con todas las características, se vuelven muy complejos y de difícil implementación y utilización. Otros modelos más dependientes de lenguaje y contexto son EJB y .Net, los cuales funcionan para plataformas y ambientes más específicos. SCA (Service Component Architecture) [35] es una iniciativa reciente propuesta como un estándar por el consorcio OASIS [36], que busca integrar SOA (Arquitecturas Orientadas a Servicios) y CBSE en un modelo en el que los componentes ofrecen servicios.

1.2.2 Requerimientos No Funcionales

Los Requerimientos No Funcionales (RNF) son un conjunto de necesidades comúnmente identificadas en las aplicaciones actuales, que generalmente son ortogonales su funcionalidad, es decir, están presentes en varios puntos de la aplicación [12]. Estos requerimientos están presentes en la ejecución del software pero no tienen que ver con la lógica funcional o de negocio de la aplicación, y aparecen como necesidades tecnológicas, imposiciones externas o atributos de calidad esperados del software. Ejemplos de ellos son: Seguridad, Manejo de Transacciones, Persistencia, Disponibilidad, Escalabilidad, etc.

Page 9: Lenguaje para Definir Interacción entre Componentes: Caso ...

8

Un modelo de componentes además de resolver las necesidades básicas en términos de funcionalidad, debe ofrecer herramientas para manejar RNFs. Generalmente los modelos soportan RNFs mediante Middlewares o Frameworks que ofrecen los servicios no funcionales consumibles por los componentes de negocio creados por el desarrollador.

En los modelos componente-contenedor, los componentes viven en un contenedor, el cual ofrece los servicios no funcionales. Estos servicios pueden ser utilizados por el desarrollador de manera declarativa facilitando así el desarrollo de las aplicaciones [23].

Contenedor

C

C

C

Persistencia Manejo de Recursos

Concurrencia Transacciones Seguridad

Clustering

...

C

Figura 3: Modelo Contenedor

En otros modelos de componentes, los RNF son expresados como capas de control que se pueden extender como en Fractal [4], o definidos en un lenguaje de aspectos, por ejemplo: AspectJ2EE [31] para los EJBs o FAC [16] para Fractal.

1.2.3 Desarrollo de Software orientado por Aspectos

El Desarrollo de Software Orientado por Aspectos (AOSD) también conocido como Programación Orientada a Aspectos (AOP) nace como una técnica que tiene como objetivo permitir el aislamiento, la composición y eficaz reutilización de código transversal presente en una aplicación [13]. Código transversal es aquel que aparece en varios puntos del programa y representa requerimientos ortogonales, que en AOSD se conocen como “cross-cutting concerns”. Una vez aislado dicho código, es modularizado en una unidad llamada Aspecto. Una gran cantidad de RNFs pueden ser implementados como Aspectos.

Los aspectos deben integrarse con los programas, y para ello se usan los lenguajes orientados a aspectos. Estos lenguajes permiten mediante diferentes técnicas definir tanto el aspecto, cómo los puntos exactos del código donde se desea interferir para agregar la lógica del mismo. En otras palabras, buscan resolver el problema de los RNFs modificando la secuencia normal de ejecución de un programa para agregar la lógica no funcional [2]. La secuencia de ejecución se modifica con base en condiciones específicas del entorno de ejecución: si una condición se cumple, se ejecutan las acciones necesarias [24].

Page 10: Lenguaje para Definir Interacción entre Componentes: Caso ...

9

En AOSD se usan diferentes formas de cuantificación (formas de especificar las condiciones [24]), la principal de ellas está asociada a la invocación de métodos: poder ejecutar acciones cuando un método de una clase es invocado. De ésta forma se puede interceptar la secuencia del programa y ejecutar instrucciones antes o después del método, o reemplazar por completo su ejecución.

Al proceso de unir los aspectos con el código fuente se le conoce como entretejido o “weaving”. En éste proceso se pueden generar elementos intermedios que colaboran en la interacción, y se puede también modificar directamente el código objeto de la aplicación.

Un lenguaje orientado a aspectos muy conocido es AspectJ, creado en los laboratorios de Xerox PARC por el equipo del profesor Gregor Kiczales [13] uno de los coautores de la AOP. AspectJ es una extensión del lenguaje Java, y actualmente forma parte de los proyectos de la fundación Eclipse [33].

1.3 Organización del Documento Seguido de la presente introducción, en el capítulo 2, se aborda la descripción del problema que intenta resolver el presente trabajo.

En el capítulo 3, se plantean unos objetivos generales y específicos, aclarando el alcance del trabajo sobre el problema planteado.

El capitulo 4, consta de dos secciones importantes. En la primera, se incluye un marco teórico sobre algunos de los modelos de componentes actuales, incluyendo a Gaita, el modelo sobre el que se valida la propuesta. Cada modelo se describe de forma corta y se enfatiza en la forma en que resuelve los RNFs. En la segunda sección, se incluyen los trabajos relacionados con el presente trabajo, mostrando cómo han venido evolucionando las diferentes propuestas.

En el capítulo 5, se incluyen los detalles de la estrategia de solución como: Modelamiento de RNFs, Composición, Interacción, Lenguaje de Interacción, Mediadores, etc.

En los capítulos 6 y 7, se incluye la respectiva validación de la propuesta, mostrando detalles de la implementación sobre Gaita y probando el modelo con la implementación de RNFs como: Ciclo de Vida, Login y Seguridad.

El capítulo 8 presenta en forma de resumen el aporte del presente trabajo, las conclusiones y el trabajo futuro.

Page 11: Lenguaje para Definir Interacción entre Componentes: Caso ...

10

2 Descripción del Problema La aparición de Internet cambió el foco de los sistemas informáticos. Empresarialmente, son pocas las aplicaciones desktop (de escritorio) que se desarrollan, a menos que se requieran específicamente. Los negocios de una empresa dependen de datos que casi nunca están centralizados, y se necesita que esos datos puedan ser consultados y manipulados por clientes internos y externos vía un navegador de Internet. Las nuevas aplicaciones requieren nuevas funcionalidades que deben resolver los desarrolladores. Aparecen Requerimientos No funcionales (RNF) del Software que no tienen nada que ver con el proceso de negocio de la empresa sino con limitaciones e imposiciones externas. Saltan a la vista requerimientos como el control de la seguridad, la escalabilidad de la aplicación, alta disponibilidad, etc.

Seguridad: Autenticación (que el cliente sea quien dice ser), autorización (que el cliente tenga los permisos para ejecutar tareas específicas - roles), datos seguros en la red (que los datos puedan viajar seguros por la red – SSL).

La escalabilidad tiene que ver con que la aplicación mantenga su rendimiento y tiempos de respuesta aun cuando el número de clientes conectados crece.

La alta disponibilidad hace referencia al tiempo que una aplicación puede estar fuera de servicio. Generalmente, una aplicación nunca debería caerse.

Los anteriores son algunos ejemplos de las nuevas tareas que debe tener en cuenta un desarrollador en la actualidad. Esos RNF son muy comunes en las aplicaciones actuales, y la idea es que los resuelva el modelo de componentes para abstraer al desarrollador final de su complejidad. A nivel de componentes podemos identificar otros RNF más puntuales:

Manejo del ciclo de vida: es una de las características básicas que debería suplir un modelo. Manejar el ciclo de vida implica básicamente crear, mantener y destruir los componentes. Pero en el anejo del ciclo de vida se pueden también abordar ciertos puntos de otros RNF como: concurrencia, rendimiento, escalabilidad y persistencia.

Transacciones: son importantes en cualquier aplicación y su control implica gran complejidad especialmente cuando son distribuidas.

La persistencia de los datos de la aplicación (objetos/componentes) en diferentes medios, como archivos, bases de datos, etc.

Una de las formas más comunes para resolver los RNF es usando un contenedor de componentes. Modelos como: EJB [29], CORBA Component Model (CCM) [29] y Microsoft .NET [15], separan los requerimientos funcionales de los

Page 12: Lenguaje para Definir Interacción entre Componentes: Caso ...

11

requerimientos no funcionales dejando el manejo de los últimos a al contenedor. Este, simplifica el desarrollo de aplicaciones permitiendo a los desarrolladores usar los RNFs de forma declarativa, es decir, mediante información adicional al código (meta-data) indican qué lógica no funcional desean aplicar a sus componentes y de qué forma.

El modelo de componentes Fractal [4] propone el manejo de los RNFs agregando una membrana o capa de control a cada componente. Se puede ver dicha membrana como si cada componente tuviese su propio contenedor. Para escribir código en la membrana con la lógica no funcional, se implementan diferentes interfaces de control ofrecidas por el modelo. Fractal sólo se define una metodología para el desarrollo uniforme de los elementos, y el desarrollador debe realizar la implementación de dichas interfaces.

Los modelos de componentes más difundidos en la actualidad son orientados al contenedor y son generalmente aceptados, aun así, se han identificado varios problemas con el tipo de solución [12][31][17]:

Los RNF ofrecidos por el contenedor no siempre satisfacen las necesidades de los componentes.

No cumplen con algunas premisas del CBSE: son dependientes de contexto (por depender del contenedor) y en varios casos dependientes de lenguaje y plataforma.

La lógica no funcional queda cableada en el contenedor y en muchas ocasiones no se puede extender.

La forma en que se modela el dominio no funcional no es explicita haciendo así menos comprensible el diseño de la aplicación.

El Desarrollo de Software Orientado por Aspectos (AOSD) es un paradigma relativamente reciente que pretende soportar la separación de competencias asociadas con requerimientos no funcionales transversales a todo el sistema [2]. AOSD resuelve los RNF permitiendo mayor separación de responsabilidades, eliminando el acoplamiento y mejorando la reutilización. AOSD nace como AOP, para ser aplicada sobre el modelo de objetos, pero puede ser usada también en programación procedural y en otros ámbitos.

Actualmente se usan técnicas de AOSD para incluir el manejo de los RNFs en los modelos de componentes, ejemplos: AspectJ2EE [31], FAC [16], JAC [17], etc. Las técnicas más recientes mezclan los Aspectos y los componentes, encapsulando los primeros en los segundos, según el concepto introducido por Pedro Clemente (ACBSE = Aspectos + CBSE) [21][19].

Este trabajo presenta una propuesta, que busca cumplir las premisas del CBSE basada en composición de componentes y AOSD. La propuesta ofrece además una metodología para abstraer al desarrollador final de la lógica no funcional. La implementación y validación se hacen sobre el modelo de componentes Gaita [34], el cual sólo soporta el RNF de distribución y un manejo de ciclo de vida básico.

Page 13: Lenguaje para Definir Interacción entre Componentes: Caso ...

12

3 Objetivos 1.4 General Incluir soporte a Requerimientos No Funcionales en el modelo de componentes Gaita teniendo en cuenta algunas de las premisas que debe cumplir un componente según el CBSE, ellas son: autocontenido, reutilizable, accesible sólo a través de su Interface, independiente del contexto y soporte a composición.

1.5 Específicos 1. Utilizar sólo elementos del modelo para expresar la solución. La solución

puede utilizar: componentes Gaita (simples o compuestos) y conectores.

2. No modificar estructuralmente Gaita. No agregar ni quitar elementos que rompan con los principios de Gaita.

3. No modificar la implementación interna de los componentes en el intento de aplicarles manejo no funcional. Sólo usar sus interfaces para no romper el encapsulamiento.

4. La solución debe poder extenderse, para manejar RNFs dependiendo de las necesidades especificas de las aplicaciones.

5. Separar las preocupaciones funcionales de las no funcionales, garantizando la reutilización de las dos.

Page 14: Lenguaje para Definir Interacción entre Componentes: Caso ...

13

4 Estado del Arte 4.1 Modelos de Componentes En ésta sección, se incluye una breve descripción de algunos de los modelos de de componentes más relevantes en la actualidad, mostrando principalmente la forma en que resuelven los RNFs.

4.1.1 Enterprise Java Beans (EJB)

Enterprise JavaBeans [29] es un API que forma parte del grupo de tecnologías JEE (arquitectura de referencia para construir aplicaciones empresariales). Actualmente la especificación EJB está en la versión 3.0, la cual incluye grandes mejoras que hacen mucho más fácil el trabajo para el desarrollador en comparación con la versión anterior (2.x). En ésta síntesis, se hablará indistintamente de esas versiones, a menos que el caso lo amerite.

Los EJBs son componentes que viven en un Contenedor, el cual se encarga de ofrecer un entorno compartido de ejecución y prestar la lógica no funcional a dichos componentes (Seguridad, Ciclo de Vida, Transacciones, Persistencia, Concurrencia, etc.). La especificación propone un modelo de componentes distribuidos que viven del lado del servidor [23]: Servidor de Aplicaciones (Application Server - AS), donde se busca abstraer al desarrollador de los problemas generales de una aplicación empresarial (RNF) para centrarse en el desarrollo de la lógica de negocio en sí.

Figura 4: Modelo Contenedor EJB

Page 15: Lenguaje para Definir Interacción entre Componentes: Caso ...

14

Existen tres tipos de componentes: los EJBs de Sesión, EJBs de Entidad y EJBs Manejados dirigidos por mensajes.

EJBs de Sesión (Session Bean): pensados para modelar los procesos de negocio que representan puntos críticos donde podría ser necesaria la intervención del contenedor. Comúnmente representan las fachadas de los módulos de la aplicación, pues son puntos de control generales, pero también pueden ser usados cada vez que se necesiten manejos más robustos que impliquen control de concurrencia, seguridad, transacciones, etc. donde el Contenedor pueda intervenir. Existen dos tipos de EJBs de Sesión:

o Stateless Session Bean (Sin estado): son accedidos

concurrentemente y garantizan los valores de variables de instancia sólo en la invocación de los métodos.

o Stateful Session Bean (Con estado): garantizan instancias únicas a cada cliente.

EJBs de Entidad (Entitys): son usados para representar las Entidades del

Negocio (Ej. Cliente, Cuenta, Empresa, etc.) o las entidades que contienen los datos, y objetivo principal es la persistencia de dichos datos. Existen también dos tipos:

o CMP (Container Management Persistence): el contenedor es el

encargado de controlar la persistencia y el desarrollador describe cómo a través de meta-data (descriptores XML o anotaciones sobre el código). La meta-data indica entre muchas cosas, el tipo de mapeo que se hace desde el Bean hacia la Base de Datos.

o BMP (Bean Management Persistence): la persistencia es controlada por el Bean, es decir, es implementada propiamente por el desarrollador.

EJBs dirigidos por mensajes (MDBs): son Beans que se acceden de forma

asíncrona a través de un sistema de mensajería como JMS (Java Messaging System).

Funcionamiento Un componente EJB es generalmente implementado por una clase tipo Bean de Java (Enterprise Bean Class). Los Beans implementan las interfaces (locales/remotas) de negocio que contienen los métodos ofrecidos por los componentes. En EJB 2.1, el Bean debe implementar algunas interfaces propias de la especificación las cuales obligan la implementación de métodos que son llamados por el Contenedor para administrar el Bean o para notificarle eventos de importancia.

Page 16: Lenguaje para Definir Interacción entre Componentes: Caso ...

15

En ejecución, cuando el componente se encuentra desplegado en el contenedor, se crea un interceptor del Bean llamado EJB Object. Un cliente que quiera usar un servicio de un componente, nunca invoca directamente los métodos sobre los Beans, las invocaciones son interceptadas por el Contenedor a través del EJB Object y delegadas finalmente a los Beans. El Contenedor intercepta las invocaciones precisamente para ejecutar tareas relacionadas con la gestión de los RNFs.

Interfaces Los componentes pueden ser accedidos local (desde dentro del contendor) o remotamente (fuera del contendor). Existe una interface para cada tipo de acceso, lo cual permite controlar las funcionalidades expuestas por el componente. Adicionalmente existe (en EJB 2.x) una Interface Home para el control del ciclo de vida del componente: creación, destrucción y búsqueda. El Contenedor crea objetos Home para cada EJB los cuales pueden ser localizados por los clientes y a través de ellos obtener las referencias a los EJBs. Descriptores de Despliegue Los descriptores de distribución o instalación (deployment descriptor) tienen la meta-data adicional mediante la cual se describen los componentes ante el contenedor, y del tipo de lógica no funcional que estos van a consumir. En la versión 3.0 de EJB, los descriptores se han disminuido gracias a que se pueden incluir en forma de anotaciones a las clases. Las anotaciones son propias de Java 5 [30].

4.1.2 CCM – CORBA Component Model

CCM es una de las especificaciones que hacen parte del catalogo CORBA 3.0 (Common Object Request Broker Architecture). CORBA es una arquitectura de objetos distribuidos heterogéneos (en lenguaje y plataforma) propuesta por el OMG (Object Management Group). CCM es la especificación que define el Modelo de Componentes en CORBA. Toda la documentación sobre CCM se extrajo del documento de la especificación disponible en [18].

La especificación incluye entre otras cosas: la semántica de los componentes; lenguaje para definir la implementación de componentes (CIDL); Framework de Implementación de Componentes (CIF), el cual define el modelo de programación para construir componentes; un modelo de contenedor, que describe como clientes CORBA pueden consumir servicios; cómo los componentes se empaquetan y distribuyen; y algunas definiciones de esquemas XML para describir componentes.

Un componente CORBA es una extensión y especialización de un objeto CORBA. Están definidos por un conjunto de características y de comportamientos que pueden ser descritos mediante un IDL (Interface Definition Language). Los

Page 17: Lenguaje para Definir Interacción entre Componentes: Caso ...

16

componentes son instanciados para crear componentes concretos con estado e identidad. Los componentes encapsulan su representación interna y su implementación. Niveles de Componentes Existen dos niveles de componentes: básicos y extendidos. Ambos son controlados por Homes (al igual que en los EJBs), pero difieren en las capacidades que pueden ofrecer. Un componente básico es un objeto CORBA convertido en componente, similar a los EJBs. Un componente extendido provee un conjunto más rico de funcionalidades. Puertos Los puertos son las interfaces por medio de las cuales elementos externos interactúan con el componente:

• Facetas: interfaces ofrecidas • Receptáculos: interfaces requeridas • Origen de Eventos: puntos de conexión que emiten eventos • Receptor de Eventos: puntos de conexión por los que el componente puede

escuchar eventos. • Atributos: valores con nombre que pueden ser expuestos y modificados

externamente. Definen la configuración del componente. Los componentes básicos solo pueden exponer atributos, los componentes extendidos pueden exponer cualquier tipo de puerto.

Figura 5: Componente en CCM. Tomada de [12]

Page 18: Lenguaje para Definir Interacción entre Componentes: Caso ...

17

Identidad de los Componentes Una instancia de componente se puede identificar por su referencia y por las referencias de cada una de las facetas. Los componentes pueden también ser asociados a una llave primaria asignada por un componente Home. El componente Home se encarga de asociar las llaves con las referencias en el momento en que crea las instancias. Componentes Home Los componentes Home actúan como manejadores de instancias de componentes específicos. Principalmente el Home maneja el ciclo de vida del componente y puede estar asociado a más de una instancia del componente. Modelo de Contenedor en CCM Al igual que en otros modelos basados en Contenedores, CCM define un entorno de ejecución en el que viven los Componentes CORBA. El Contenedor juega el papel de Servidor de Aplicaciones ofreciendo un conjunto de funcionalidades más robustas diseñadas para facilitar la creación de aplicaciones CORBA.

Figura 6: Arquitectura del Modelo Contenedor en CORBA [12]

En la figura 6 se puede notar que existen interfaces para consumir servicios del Contenedor (Services y Facilities) que implementan lógica No Funcional lista para usar. Y también existen Interfaces (Callbacks) mediante las cuales el contenedor notifica al componente de eventos que le pueden interesar.

Page 19: Lenguaje para Definir Interacción entre Componentes: Caso ...

18

4.1.3 Fractal

Fractal es un modelo de componentes modular, extensible e independiente de lenguaje de programación que puede ser usado para diseñar, implementar, distribuir y reconfigurar sistemas y aplicaciones. El objetivo de Fractal es disminuir los costos de desarrollo, distribución y mantenimiento de las aplicaciones software en general. La documentación de Fractal está disponible en [4]. Las siguientes son las características del modelo:

Recursividad: los componentes pueden unirse para crear componentes compuestos. Esta es la característica principal del modelo y por la cual se debe su nombre.

Reflectividad: se puede hacer introspección a los componentes. Compartimiento de Componentes: un componente puede ser incluido o

compartido por otros componentes. Componentes Enlazados: los componentes se comunican o conectan a

través de elementos conocidos como bindings. Los Bindings pueden incluir lógica de comunicación para el control de llamadas a procedimientos remotos (RPC).

Independencia del modelo de ejecución: teóricamente los componentes no dependen de un modelo de ejecución, por lo que podrían convivir con componentes de otros modelos que cumplan con ciertas características básicas de componentes.

Abierto: Se pueden agregar nuevas funcionalidades a los componentes por medio de la membrana de control.

Fractal enfrenta los objetivos con un modelo que no es muy grande y rígido, sino con un modelo flexible y extensible, con relaciones bien definidas que permiten que un componente específico decida si implementa o no las posibles opciones del modelo dependiendo de las características que quiere exponer.

Los componentes tienen tres niveles de control. Un primer nivel en el que el componente no ofrece ningún tipo de control a otros componentes. Un segundo nivel llamado de Introspección, en el que un componente ofrece una Interface estándar mediante la cual puede ser controlado externamente. Dicha Interface es parecida a la Interface IUnknown del modelo COM, mediante la cual, se pueden descubrir las demás interfaces del componente. Un tercer nivel llamado nivel de Configuración, en el que un Componente puede ofrecer interfaces para modificar su contenido: un componente puede estar formado por más de un sub-componente, y mediante las interfaces de control ofrecidas se puede decidir que componentes internos pueden ser controlados e incluso se puede modificar los bindings internos.

Fractal ofrece un pequeño Framework que se encarga de la instanciación de los componentes y ofrece también un conjunto de tipos simples para los componentes. Estos elementos, al igual que la mayoría en Fractal, son opcionales.

Page 20: Lenguaje para Definir Interacción entre Componentes: Caso ...

19

Elementos del modelo:

Componentes: son la base del modelo y representas entidades encapsuladas. Pueden ser simples o compuestos.

Interfaces: son los puertos de los componentes. Las interfaces son puntos

de acceso al componente y tienen dos roles: Cliente o Servidor. Las interfaces Servidor representan las funcionalidades expuestas y las interfaces Cliente las funcionalidades requeridas.

Bindings: son los mediadores de la interacción entre los componentes,

también son conocidos como conectores. Pueden representar enlaces simples para relacionar dependencia de componentes o pueden representar enlaces de composición. Los bindings pueden implementar lógica de invocación de objetos distribuidos en caso de que los componentes estén dispersos en una red.

Membrana: un componente está formado por una membrana más un

contenido. El contenido puede ser la implementación propia del componente o un subconjunto de componentes. La membrana es la capa lógica que se forma de las implementaciones de las interfaces de control. La membrana también es conocida como la capa de control o Controller. En la membrana suele alojarse toda la lógica No funcional del componente.

ADL: Con el propósito de lograr interoperabilidad entre los diferentes

lenguajes de programación Fractal ofrece un Lenguaje de Definición de Interfaces (IDL). Dicho lenguaje es también opcional y se debe usar cuando realmente se necesite. La idea de un lenguaje común permite la comunicación entre los diferentes lenguajes de programación.

De acuerdo al primer nivel de control o sin control, un componente en Fractal puede ser visto de la siguiente manera:

Figura 7: Vista externa de un Componente Fractal [4]

Los siguientes niveles de control del componente (Introspección y Configuración) permiten ver más hacia su contenido, es decir, muestran una vista interna del

Page 21: Lenguaje para Definir Interacción entre Componentes: Caso ...

20

componente en la que aparecen otros elementos como la Membrana y los diferentes tipos de bindings entre los sub-componentes:

Componente

InterfacesCliente

InterfacesServidor

Interfacesde Control

Membrana(Controlador)

SubComponente

SubComponente

ExportBinding Import

Binding

NormalBinding

Figura 8: Vista interna de un Componente Fractal

4.1.4 Arquitectura de Servicios Componentes (SCA)

SCA (Service Component Architecture) [35] es una especificación que describe un modelo para construir aplicaciones y sistemas usando arquitecturas orientadas a servicios (SOA). En éste caso, los servicios son implementados por componentes, bajo una premisa muy importante: la interface es genérica y las implementaciones pueden crearse con cualquier tecnología. La implementación puede estar escrita en diferentes lenguajes: Java, PHP, COBOL, C++, etc. o inclusive, lenguajes centrados en XML como: BPEL, XSLT, etc.

Figura 9: Arquitectura de Servicios Componentes [35]

Page 22: Lenguaje para Definir Interacción entre Componentes: Caso ...

21

Los componentes ofrecen los servicios a través de sus interfaces. Las interfaces requeridas reciben el nombre de Referencias. Los componentes pueden adicionalmente tener propiedades, similares a los atributos de los componentes CORBA. Los componentes se comunican unos con otros mediante Bindings, similar a los conectores en otros modelos. Se pueden crear componentes compuestos, es decir, formados en su interior por el ensamblaje de otros componentes.

En cuanto a los RNFs, SCA no detalla la forma en que se deben implementar ni ofrece un framework para su manejo. Inicialmente ofrece en su especificación, un conjunto de herramientas que permiten consumir los servicios de forma segura, según el Framework Policy. Dicha sub-especificación incluye detalles de las políticas de seguridad que se pueden aplicar a los servicios.

4.2 Gaita En ésta sección, se describe brevemente el modelo de componentes sobre el que se prueba nuestra solución. Gaita es un modelo de componentes distribuidos no jerárquicos que viven en una red de nodos. Gaita resuelve la localización de los servicios y sus instancias de forma transparente mediante la comunicación entre los nodos de la red y la consistencia de los elementos definida en el modelo [9][8].

Gaita-C [8] es la evolución del modelo Gaita-S [9], agregando soporte a composición de componentes. Los descriptores de Gaita-C permiten definir tanto componentes simples, cuya implementación es una clase Java, como componentes compuestos, donde la implementación es la composición de componentes predefinidos. En ésta síntesis, se habla de Gaita en general a menos que se especifique lo contrario. Los componentes simples son llamados servicios en Gaita-S, por lo tanto, se puede encontrar la palabra servicio en ésta sección, para referirse a componentes.

Según la especificación, el modelo está orientado por las siguientes características:

Simplicidad Mínimal: el modelo ofrece sólo elementos básicos que al extenderlos,

lograrían obtener funcionalidades más avanzadas Reflexivo: los elementos del modelo se pueden obtener en ejecución. Extensible: el modelo debe permitir la extensión sin modificar sus principios

básicos.

Page 23: Lenguaje para Definir Interacción entre Componentes: Caso ...

22

4.2.1 Componentes

Representan funcionalidades que pueden estar expresadas en términos de contratos ofrecidos (facetas), contratos requeridos (receptáculos) y un conjunto de fábricas que permiten instanciar el componente. La figura 9 muestra un ejemplo de componente:

ComponenteFacetas:InterfacesOfrecidas

Receptáculos:Interfaces

Requeridas

Figura 10: Componente en Gaita-S

4.2.2 Conectores

Los componentes en Gaita se comunican por medio de conectores. Un receptáculo de un componente espera poder ser resuelto por la faceta de otro. El Conector es el elemento encargado de unir el receptáculo y el componente. El conector puede encerrar la lógica de localización de los componentes requeridos, ocultando dicho trabajo al componente. De ésta forma, el componente tiene sólo la lógica que le corresponde.

ComponenteA

ComponenteB

Conector

Figura 11: Conector en Gaita

4.2.3 Nodos

Los componentes en Gaita viven en una Red de Nodos. Los nodos están interconectados y pueden interactuar. Cada Nodo tiene Componentes, Conectores e Instancias. Los nodos tienen nombres únicos en la red y son cerrados, es decir, todas las instancias en su interior pertenecen a los componentes o conectores instalados en el mismo nodo.

4.2.4 Instancias de los elementos del modelo

Al igual que en Programación Orientada a Objetos, donde existe la noción de clase e instancia de ella, en un modelo de componentes, también existe la noción de instancia del componente. Cada modelo define lo que representa la instancia del componente. En Gaita, las instancias de los componentes simples se forman

Page 24: Lenguaje para Definir Interacción entre Componentes: Caso ...

23

de la instancia de la clase que implementa las interfaces ofrecidas y de otros artefactos que genera el modelo (identificador único, registro, descriptor, etc.).

Componente

Faceta

Faceta

Receptáculo

Receptáculo

Receptáculo

Figura 12: Instancia de componente en Gaita

La figura 12 muestra la representación de una instancia de un componente. A diferencia del componente en fase de diseñó, la instancia es un rectángulo con bordes redondeados.

También existe la noción de instancia de un conector. Diferentes instancias de un conector permiten resolver de forma diferente los receptáculos del componente.

4.2.5 Composición de Componentes

Los componentes compuestos son aquellos que se forman ensamblando otros componentes. Al interior de un componente compuesto existe una red de sub-componentes relacionados entre sí para lograr la funcionalidad del componente más grande.

SubComponente

2

SubComponente

1ConectorDelegate

ComponenteConector

Subsumed

ConectorSubbinding

F1

F21

F11 R1

R2

R11

R12

R21

Figura 13: Componente compuesto en Gaita-C

En la figura 13, se muestra la implementación de un componente compuesto. Existen tres relaciones nuevas y tres tipos de conectores asociadas a ellas: Delegate, Subbinding y Subsumed. Una relación Delegate sirve para indicar qué facetas de los sub-componentes resuelven las facetas del componente compuesto: la faceta F1 del componente compuesto debe ser resuelta por la faceta F11 del sub-componente 1. La relación de Subsumed permite decidir qué receptáculos del componente compuesto equivalen a los receptáculos de los componentes internos: el receptáculo R1 equivale al receptáculo R11 y el receptáculo R2 equivale el receptáculo R21. La relación de Subbinding permite enlazar componentes internos: R12 es resuelto por F21.

Page 25: Lenguaje para Definir Interacción entre Componentes: Caso ...

24

En tiempo de ejecución, se crean instancias únicas de cada sub-componente por cada instancia nueva del componente compuesto. Lo mismo ocurre con los conectores internos, los cuales se especializan en encontrar las instancias apropiadas según la composición.

4.2.6 Puntos de extensión

El Modelo de Gaita soporta actualmente dos puntos de extensión: los Gateways y los Adaptadores. Los Gateways son responsables de la comunicación entre los nodos permitiendo la independencia de tecnología y protocolo. Un usuario de Gaita puede, siguiendo la especificación, crear un Gateway propio según sus necesidades. La implementación de referencia del Gateway está basada en RMI. Los Adaptadores (Adapters) permiten la conexión de los clientes externos a la red gaita, y al igual que los Gateways, permiten independencia de tecnología y protocolo.

Nodo2Nodo1

Servicio1 Servcio2

Gateway

Adapter Adapter

Cliente

Figura 14: Gateways y Adaptadores en la red Gaita

4.2.7 Niveles de Abstracción

En Gaita existen dos niveles de abstracción: Abstracto y Concreto. Los elementos abstractos agrupan funcionalidades generales, por lo tanto no se pueden instanciar, y más bien, sirven para agrupar y fabricar elementos concretos. Existen entonces elementos abstractos y concretos asociados a cada elemento base: AbstractService, AbstractConnector, ConcreteService y ConcreteConnector. Los componentes y conectores concretos se unen mediante un receptáculo específico representado con ReceptacleBinding.

4.2.8 Creación de componentes Gaita

Todo componente creado por un desarrollador cliente de Gaita debe incluir:

Interface del componente: es la Interface Java que representan una faceta del componente. Pueden existir varias por componente.

Page 26: Lenguaje para Definir Interacción entre Componentes: Caso ...

25

Implementación de la Interface del componente: el usuario debe proveer al menos una implementación (clase Java) de cada una de las interfaces del componente. Si existen varias implementaciones, la implementación usada es seleccionada por la fábrica del componente. Dichas clases, además de implementar la Interface del componente deben implementar una Interface del modelo (IServiceObject) mediante la cual Gaita realiza algunas tareas propias de la especificación como, notificar eventos o inyectar los receptáculos y nodos. IServiceObject, además identifica a la clase, como la que implementa el componente.

Fabrica del componente: para permitir múltiples implementaciones de una

faceta, un componente concreto no se asocia con una implementación específica sino con una fábrica, la cual se encarga de devolver la implementación más apropiada según las necesidades del contexto.

Descriptores: son archivos XML con meta-data que define el componente:

su nombre, facetas, receptáculos, conectores, la fábrica y una descripción basada en propiedades (nombre y valor). Los descriptores permiten describir los componentes simples y los compuestos. En Gaita-C existen tres descriptores adicionales llamados Descriptores de Composición: design.xml, deploy.xml y development.xml. Cada descriptor describe la composición en el tiempo indicado.

El siguiente es un ejemplo de descriptor (element.xml):

<?xml version="1.0" encoding="UTF-8"?> <gaita-s> <concrete-service name="ReverseLineService"> <facets> <facet type="uniandes.gaita.reversor.reverseline.IReverseLineService"/> </facets> <receptacles-bindings> <binding type="uniandes.gaita.reversor.reverseword.IReverseWordService" concrete-connector="ReverseWordConnector"/> </receptacles-bindings> <factory instantiator="uniandes.gaita.reversor.reverseline.ReverseLineFactory"/> </concrete-service> </gaita-s>

Los elementos del componente son empaquetados en un archivo .gaitar. El conector al igual que el componente, necesita de una clase que lo implemente, de una fábrica y de los descriptores. La implementación del conector debe, además de implementar la Interface del receptáculo (Interface del servicio requerido), implementar una Interface del modelo (IConnector), la cual juega el mismo papel de IServiceObject en el caso del componente.

4.2.9 Identificación de los elementos del modelo

En Gaita todos los elementos están identificados de forma única, todos tienen un GaitaId. El GaitaId está formado por el nombre del elemento, el nombre del nodo y

Page 27: Lenguaje para Definir Interacción entre Componentes: Caso ...

26

un tipo. Los tipos están predefinidos y pueden ser: SERVICE_INSTANCE, CONCRETE_SERVICE, CONCRETE_CONNECTOR, ABSTRACT_SERVICE, ABSTRACT_CONNECTOR, GAITA_NODE. Además de tener un identificador único, los elementos tienen descriptores (GaitaDescriptor) los cuales asocian al elemento con un conjunto de propiedades. Todos los elementos son almacenados en el nodo, y sus descriptores e identificadores son almacenados en un depósito (Registry) en el que se pueden localizar.

4.2.10 Ciclo de Vida en Gaita

En Gaita las instancias existen como elementos del modelo (ServiceInstance) y por lo tanto tienen una identificación (GaitaId) y junto con su descriptor (GaitaDescriptor) forman una pareja con la que se pueden encontrar en la red Gaita. Las instancias además tienen información del componente concreto al que pertenecen y de los enlaces con las instancias de los conectores concretos.

El elemento más importante de la ServiceInstance es la referencia que tiene al objeto de negocio que implementa el componente (ServiceObject). Dicha referencia es una instancia única de la clase que implementa el componente. Existe una instancia del ServiceObject por cada ServiceIntance.

Cuando el servicio “newInstance” es invocado sobre el nodo, un Instanciador termina creando la instancia (ServiceInstance) en el nodo sobre el que está instalado el componente. En el momento en que el Instanciador crea la ServiceInstance, se crea también la instancia de la implementación (ServiceObject) que devuelve la fábrica del componente y se le inyectan a dicha instancia las referencias a las instancias de los conectores concretos. El ServiceObject es asociado al ServiceIntance dando inicio al Ciclo de Vida. El final del ciclo de vida no está definido y las instancias mueren cuando muere el nodo.

El siguiente diagrama de clases simplificado muestra las relaciones de las instancias con los elementos del modelo.

Page 28: Lenguaje para Definir Interacción entre Componentes: Caso ...

27

GaitaCore GaitaClient

*

ServiceInstance

ConcreteService

ServiceFactory

ServiceInstantiator

ServiceObject

Figura 15: Instancias y Servicios Gaita

Se debe tener cuidado con la diferencia entre la instancia del componente (ServiceInstance) como elemento del modelo y la instancia propia del objeto que implementa el componente (ServiceObject). En la parte izquierda de la figura, se muestran los elementos (relativos a la instancia) del Core de Gaita que se crean asociados a los componentes. En la parte derecha, se encuentran las clases que conforman el componente visto desde el punto de vista de un desarrollador Gaita.

4.2.11 Implementación de referencia: GaitaS V0 Engine

Existe una implementación de referencia del GaitaS V0 creada con la versión 1.5 de Java. Dicha implementación es llamada GaitaS V0 Engine, nombre asignado por su autor (Pablo Barvo) [20]. La implementación está basada en OSGi como framework de componentes e incluye unas interfaces de administración basadas en JMX. La extensión de Gaita-S (S = Servicio) [9] para incluir composición se llama Gaita-C y fue creada por José Daniel Ramírez en su tesis de Maestría [8].

Dado que la especificación no propone una arquitectura, GaitaS Engine propone una arquitectura como la siguiente:

Figura 16: Arquitectura de GaitaS V0 Engine

Page 29: Lenguaje para Definir Interacción entre Componentes: Caso ...

28

A continuación se describen algunos de los elementos: GaitaNode: componente encargado de prestar las principales funcionalidades a los clientes tanto externos como internos. Presta servicios de búsqueda de componentes, creación de instancias, brusquedad de instancias e invocación de métodos. GaitaCore: contiene los elementos base del modelo Gaita. Entre otros: AbstractService, AbstractConnector, ConcreteService, GaitaId, GaitaException, GaitaDescriptor, etc. GaitaEngine: exporta los componentes del nodo por medio de adaptadores. Es el encargado de la instalación e instalación de los mismos. Framework de Distribución: se encarga de la localización e instanciación de componentes remotos. Se encarga también de instalar y cargar los gateways. GaitaInstantiator: elemento encargado de crear las instancias en los nodos. Contiene toda la lógica de instanciación de componentes concretos, incluyendo la instanciación de los conectores necesarios para resolver sus receptáculos. GaitaEditor: editor que permite la reflexión de los elementos del modelo Gaita. Implementa tanto los servicios de edición como los servicios de importación y exportación de elementos e interfaces. Deployer: sabe leer y guardar archivos autocontenidos: gaitar. Permite exportación e importación de servicios y conectores de otro Nodo Gaita o de un editor.

4.2.12 Elementos que intervienen en el ciclo de vida

El inicio del Ciclo de Vida está asociado a la creación de la ServiceInstance. La secuencia inicia en el conector cuando éste se da cuenta de que no existe ninguna instancia para un componente dado. El conector hace la solicitud al nodo, quien delega la creación de la instancia al Framework de Distribución en caso de que el Componente Concreto no se encuentre en el nodo local, o al Instanciador en caso contrario. Si la petición se delega al Framework de Distribución, en últimas, llega a un Instanciador en otro nodo.

Luego de que el componente es instanciado puede ser accedido por clientes mediante la invocación de sus métodos. Nuevamente el conector es el encargado de iniciar la invocación a través de un servicio del nodo. Por medio del GaitaId de la instancia del componente (ServiceInstance) y de la firma (Signature) del método a invocar, el conector solicita al nodo la invocación del método. Igualmente, el nodo decide si invocar directamente el método sobre el objeto del componente (ServiceObject) o delegar la invocación al Framework de Distribución, dependiendo de la ubicación del componente concreto.

Page 30: Lenguaje para Definir Interacción entre Componentes: Caso ...

29

4.2.13 Clientes de Gaita

Existen dos clientes de un componente Gaita: un cliente interno y un cliente externo. Un cliente interno puede ser cualquier elemento del modelo que vive en un nodo de la red Gaita, el ejemplo de cliente interno más común es el conector de un componente. El segundo cliente, el cliente externo, es toda aplicación que vive fuera de la red Gaita (generalmente en una JVM diferente) y que consume los servicios de la red.

Los clientes Gaita, sin importar su tipo, consumen los servicios de los componentes con la ayuda de las funcionalidades que ofrecen los nodos (buscar instancias, buscar componentes, invocar métodos de un componente, etc.). Un cliente Gaita nunca tiene una referencia directa de una ServiceInstance ni de un ServiceObject. En lugar de una referencia a una instancia especifica, el cliente tiene una referencia de su GaitaId. Cuando el cliente quiere invocar un método de un componente, solicita dicha invocación al nodo, indicando la firma del método y el GaitaId de la instancia sobre la cual quiere invocar el método.

Actualmente los clientes externos usan proxies dinámicos generados a partir de la Interface del componente, los cuales almacenan el id del nodo y el id de la instancia del componente para poder hacer las invocaciones al nodo cuando se invoca cualquier método del componente.

4.3 AspectJ AspectJ [5] es una extensión orientada a aspectos del lenguaje Java. Permite modularizar las funcionalidades que cruzan (ortogonales) toda la aplicación (cross-cutting concerns) y representarlas en unidades llamadas Aspectos.

AspectJ al igual que la mayoría de los lenguajes AOP se basa en los siguientes conceptos:

JoinPoint: son puntos bien definidos que se pueden interceptar en el flujo del programa, por ejemplo, el llamado a un método, la instanciación de una clase, etc.

Pointcut: permiten seleccionar o filtrar JoinPoints. Mediante patrones o expresiones, permiten referenciar uno o varios JoinPoints. Por ejemplo, el pointcut: pointcut setter: call(public * Person.set*(..))

Selecciona los JoinPoints alcanzados cuando se invoca un método “set” de la clase “Person” definido como público, y que no importe ni su tipo de retorno ni sus parámetros.

Advice: junto con los pointcuts, definen el punto exacto a interferir (Antes, después o reemplazo) más las instrucciones (cuerpo en código java) a ejecutar cuando el JoinPoint sea alcanzado. Ejemplo en AspectJ utilizando el pointcut “setter”:

Page 31: Lenguaje para Definir Interacción entre Componentes: Caso ...

30

before() : setter(){

System.out.println("Setter invocado"); } El advice anterior imprime el mensaje justo “antes” de la ejecución de los métodos seleccionados por el pointcut.

Declaraciones Inter-type: declaraciones que permiten modificar las clases o su jerarquía, agregando métodos, atributos, o cambiando las relaciones de herencia entre ellas. Permiten modificar el código objeto en tiempos de compilación y ejecución.

Aspectos: encierran los pointcuts, advices y declaraciones InterType en una unidad modular que implementa la preocupación ortogonal. Se define de forma parecida a una clase, permitiendo agregarle atributos, métodos, constructores y clases internas. En el momento del entretejido, el aspecto es convertido en una clase, con métodos adicionales generados para resolver la interacción entre el aspecto y el código objetivo.

Tipos de Advices

Before: se ejecutan entes del JoinPoint After returning: se ejecutan después de que termine la ejecución del

JoinPoint sin que ocurra una excepción. After throwing: se ejecutan después de que termine la ejecución del

JoinPoint cuando ha ocurrido una excepción. After: se ejecuta después de le ejecución del JoinPoint sin importar si

ocurre o no excepción. Around: reemplaza la ejecución del JoinPoint y puede o no ejecutar éste.

Tipos de Poincuts

Call: permite interceptar la invocación de métodos o constructores agregando el código del advice de forma externa.

Execution: permite interceptar la invocación de métodos o constructores agregando el código del advice dentro del método.

Staticinitialization: añade el código del advice en la inicialización de clases estáticas.

Get/Set: permiten interceptar métodos getters y setters. Handler: permiten capturar excepciones ocurridas en el JoinPoint. Initialization: permite interceptar la creación de instancia de una clase.

Page 32: Lenguaje para Definir Interacción entre Componentes: Caso ...

31

Ejemplo A continuación se muestra un ejemplo sencillo de aspecto, que permite traceo o logging en la ejecución del código. Es decir, permite escribir mensajes mediante algún sistema de log en la ejecución de los métodos de un programa.

aspect simpleLogger {

pointcut tracedCall() : call(public * *(..)); before(): tracedCall() {

logger.info("Entering: " + thisJoinPoint.toString()); }

}

El pointcut “tracedCall”, permite seleccionar los JoinPoints alcanzados cuando se invoca cualquier método público de cualquier clase, cualquier tipo de retorno y cualesquiera parámetros en cantidad y tipo. El advice de tipo “before” permite ejecutar el código de su cuerpo cuando se alcanza algún JoinPoint seleccionado por “tracedCall”. thisJoinPoint es una palabra reservada de AspectJ que se incluye para hacer referencia al JoinPoint actual. Existen otras palabras reservadas que se pueden incluir en el cuerpo del advice, una muy importante es “proceed”, la cual permite invocar la ejecución del método objetivo en un advice de tipo “around”.

4.4. Trabajos Relacionados En ésta sección se incluyen algunos trabajos que se han desarrollado bajo el mismo contexto del presente, para mostrar cómo han evolucionado las propuestas basadas en CBSE y AOSD.

Soluciones para incluir manejo de RNFs diferentes al modelo contenedor surgen con Gregor Kiczales [13] y la AOP. Luego, Siobhán Clarke [27] propone la solución mediante su patrón de composición: una solución parecida a AOP que pretende modelar el aspecto no fucnional mediante plantillas de UML y diagramas de secuencia. Las soluciones anteriores estan orientadas al modelo de objetos y no al de componentes.

Usando composición de componetnes y basandose en los principios del CBSE, Rickard Andersson y Henrik Grankvist [22] proponen la encapsulación de los RNF en componentes para su posterior integración en el sistema completo. Una idea parecida muestra Katalina Marcos [12] en su trabajo: Composición de componentes funcionales con servicios no funcionales. Katalina también propone la encapsulación de los RNFs en componentes y mediante composición, la aplicación de la lógica no funcional a otros componentes. Marcos se basa en el trabajo de Clarke (patrón de composición) para expresar la composición.

Aparecen soluciones que integran CBSE y AOSD como: AspectJ2EE [31], “Transparent and Dynamic Aspect Composition”[1], “Describing and Using Non Functional Aspects in Component Based Applications” [7], FAC [16], etc.

Page 33: Lenguaje para Definir Interacción entre Componentes: Caso ...

32

4.4.1 Componentes estándares para representar RNFs

Rickard Andersson y Henrik Grankvist [22] en su trabajo de tesis titulado “Using Standar Components for Non-Functional Requirements” proponen encapsular los RNFs en componentes del modelo (NFCs). Posteriormente, los NFCs se integran con los componentes funcionales (S’) y otros componentes auxiliares llamados Agentes, para formar el sistema:

Figura 17: RNFs como componentes [22]

Los Agentes son elementos que permiten crear arquitecturas flexibles mediante técnicas de adaptabilidad y extensibilidad. El nombre agente en software se puede tomar como elemento auxiliar o intermediario. Una arquitectura de agentes se basa en eventos, reglas y adaptadores. En ésta solución, los agentes permiten expresar las propiedades propias de cada RNF que le permiten a un NFC interactuar con el sistema S’.

4.4.2 Composición de componentes funcionales con servicios no

funcionales

Un trabajo parecido al de Andersson y Grankvist propone Katalina Marcos [12] en su tesis de maestría. Katalina también propone representar los RNFs como CNFs (Componentes No Funcionales), pero a diferencia de los primeros, Katalina no integra los CNFs con el sistema, en su lugar, compone los CNFs con componentes funcionales (CFs) y obtiene nuevos componentes compuestos que ofrecen la lógica funcional y no funcional al tiempo. Katalina validó su propuesta sobre una de las primeras versiones del modelo de componentes Gaita cuya implementación se llamaba Seneca. A su implementación de RNFs sobre Gaita la llamó Gaita-NF.

Page 34: Lenguaje para Definir Interacción entre Componentes: Caso ...

33

Figura 18: Gaita-NF [12]

En la imagen, cuando se quiere aplicar lógica no funcional a un componente funcional (C), se compone éste con los servicios no funcionales (SNF1 y SNF2) para obtener un nuevo componente que incluye los dos tipos de lógica. Para expresar la forma en que se relacionan los componentes, se usa un modelo de interacción.

El modelo de interacción es expresado mediante patrones de composición [27]. Los patrones de composición permiten modelar la forma en que un aspecto no funcional se relaciona con los objetos funcionales, basándose en plantillas UML y diagramas de secuencia. Clarke [27] propone el patrón de composición en un modelo de objetos y Katalina lo adapta para modelos de componentes.

En el modelo de Katalina el componente objetivo (funcional) es modificado en el momento de hacer la composición. Como se puede notar en la figura 17, al componente C le aparece un nuevo receptáculo para interactuar con el SNF1. De la misma manera, al componente funcional pueden agregársele nuevas interfaces si es necesario. Se puede decir que el modelo rompe el encapsulamiento del componente funcional, y éste no puede usarse en su estado original.

Con respecto al patrón de composición, se puede decir que no ha tenido la misma popularidad que las técnicas basadas en AOP. Posterior a su publicación inicial, el autor publicó un artículo para mostrar cómo se podía pasar de las plantillas UML a AspectJ [26]. Por otra parte, Katalina no pudo generar los componentes completos debido a problemas al interpretar el código XMI de los diagramas de secuencia [12].

4.4.3 Describiendo y usando aspectos no funcionales en CBA

Frédéric Duclos, Jacky Estublier y Philippe Morat proponen la integración del modelo contenedor y AOP [7]. La idea se basa en representar los RNF como aspectos de AOP que se integran con los componentes funcionales encerrando éstos últimos a modo de contenedor. Es como si cada componente funcional

Page 35: Lenguaje para Definir Interacción entre Componentes: Caso ...

34

tuviese su propio contenedor (idea parecida a la membrana de Fractal). El trabajo pretende extender el modelo Contenedor para soportar servicios no funcionales definidos por el usuario.

Figura 19: Contenedor por componente [7]

La propuesta utiliza dos lenguajes para su implementación: Un lenguaje para definir los aspectos sólo a nivel de los advices (Aspect Definition Language) y un lenguaje de usuario para aplicar los aspectos definidos a los componentes funcionales (Aspect User Languaje). Mediante los dos lenguajes se logran dos niveles de definición: con el primer lenguaje se definen los aspectos que pueden ser reutilizados en múltiples aplicaciones (Aspect Library), y con el segundo lenguaje, un usuario diferente puede describir la forma en que quiere aplicar los aspectos predefinidos a sus componentes. En términos de AOP, el lenguaje de usuario permite seleccionar los JoinPoints en donde se quiere aplicar los aspectos definidos por el lenguaje de definición.

4.4.4 Aspect J2EE

Aspect J2EE es un lenguaje de aspectos propuesto por Tal Cohen y Joseph Gil, que permite integrar Aspectos en la arquitectura J2EE [31]. El trabajo se implementa y valida con la versión 2.1 de los EJBs. Se introducen dos conceptos importantes: Aspectos Parametrizables y Entretejido en tiempo de despliegue.

Los Aspectos Parametrizables, permiten al igual que en otros modelos, tener una librería de aspectos reutilizables. Los aspectos se definen en términos de parámetros mediante los cuales se logra una solución más general.

Page 36: Lenguaje para Definir Interacción entre Componentes: Caso ...

35

El entretejido en tiempo de despliegue (deploy-time weaving), según los autores, da una mejor administración al alcance del Aspecto y presenta una semántica del modelo más entendible y mantenible, esto debido a la no intrusión sobre el modelo de objetos. Es una idea que parece ser acertada, pues es más fácil modelar los aspectos y los objetos por aparte, sin tener que pensar en lo que sería el entretejido.

4.4.5 Composición transparente y dinámica de aspectos

Anis Charfi propone un modelo de interacción entre componentes (de cualquier tipo) [1]. Mediante un lenguaje basado en técnicas de AOSD llamado ISL (Interacción Specification Language) Charfi propone la expresión de la forma en que interactúan dos o más componentes en una composición. El lenguaje ISL es usado para representar la interacción entre Componentes Funcionales y Componentes No Funcionales. A continuación se muestra un ejemplo tomado de [1]:

El lenguaje toma como parámetros los componentes para los cuales va a expresar la interacción. Lo que se encuentra antes de –> son los pointcuts. En el ejemplo, los pointcuts apuntan a los métodos “addMeeting” y “removeMeeting”. El ISL permite definir pointcuts basados en patrones y expresiones, al igual que en AspectJ. Después de -> se incluyen los advices. El ejemplo mostrado permite validar los permisos de seguridad antes de ejecutar los métodos de Agenda.

4.4.6 FAC

Nicolas Pessemier, Lionel Seinturier y Laurence Duchien proponen la integración del CBSE y AOSD en su modelo FAC (Fractal Aspect Component) [16]. Los RNFs son encapsulados en “Aspects Componentes”: aspectos encapsulados en componentes. Los autores hablan de la asimetría (entidades diferentes) entre los Aspectos y los Componentes, y proponen representar los aspectos en componentes que no difieran en nada de los componentes regulares.

Page 37: Lenguaje para Definir Interacción entre Componentes: Caso ...

36

Figura 20: Ejemplo del Aspecto Transacción en FAC [16]

Para representar la interacción (modelo de interacción) entre los “Aspects Components” y los “Regular Componentes” (Componentes Funcionales), usan el concepto de “Aspect Binding”. Dichos enlaces son generados para cada JoinPoint que pueda ser alcanzado por los pointcuts.

Page 38: Lenguaje para Definir Interacción entre Componentes: Caso ...

37

5 Propuesta de Solución En éste capítulo se describe la propuesta del trabajo de tesis para incluir el manejo de Requerimientos No Funcionales en modelos de componentes. Primero se describe de forma general la propuesta y lego se detalla cada uno de los puntos más importantes.

5.1 Descripción General La propuesta para incluir RNF, busca principalmente cumplir con algunas de las premisas del CBSD relacionadas con los componentes: independencia del contexto, comunicación por medio de las interfaces, separación de responsabilidades y reutilización. Para la identificación, separación y expresión de las preocupaciones transversales asociadas a RNFs se usan técnicas de AOSD.

La propuesta se basa en composición de componentes no funcionales con componentes funcionales (idea inicial de Katalina Marcos [12]) y en la expresión de la interacción entre ellos de manera externa (usando sus interfaces). Se agrega la lógica no funcional a un componente, componiendo éste con otros predefinidos que ya implementan lógica no funcional.

Si se quiere agregar manejo lógica no funcional a un componente funcional (CF), se asocia éste con un componente no funcional (CNF):

CF

CNF

+ICF

ICF’

ICNF

CF’

Figura 21: Composición con Componentes No funcionales

El resultado es un nuevo componente que ofrece la lógica funcional inicial más la lógica no funcional agregada (CF’). La faceta funcional de CF (ICF) debe ser expuesta por el nuevo componente. ICF’ debe tener por lo menos los mismos métodos de ICF. En algunos casos pueden aparecerle nuevas facetas a CF’ producto de la adición de la lógica no funcional.

Tanto el CF como el CNF se desarrollan sin conocerse. Una vez creado el CF, solo se puede aplicar lógica no funcional usando sus interfaces, evitando romper su encapsulamiento.

Page 39: Lenguaje para Definir Interacción entre Componentes: Caso ...

38

Existe

CFs, no debería pensar en la lógica no funcional que se

NF a cualquier CF, es decir, debe expresar la interacción entre los n

os componentes pueden ofrecer facetas o requerir

¿En qué punto interviene la lógica no funcional? ¿Cuál es l orden de llamados?

n tres roles de desarrolladores para la propuesta: Desarrollador de Componentes Funcionales (FCD): es un desarrollador dedicado a crear componentes que resuelven la lógica funcional y de negocio de la aplicación. Es el encargado de crear los CFs. Cuando éste

desarrollador crea susquiera aplicar a ellos.

Desarrollador de Requerimientos No Funcionales (NFRD): es el encargado de encapsular los RNFs en CNFs. Los servicios ofrecidos por los CNFs deben ser genéricos, es decir, no dependen de los CF finales, para así

permitir la reutilización. Por ejemplo, un CNF de seguridad puede ofrecer servicios como autenticación y autorización, un CNF de persistencia servicios como guardar, actualizar y consultar, etc. Existe una librería de CNFs listos para usar en diferentes aplicaciones. El NFRD además de crear los CNFs debe expresar cómo aplicar dicho Ccompo entes.

Desarrollador de Aplicaciones Basadas en Componentes (CBAD): Es el encargado de crear la aplicación completa, integrando la solución de los dos desarrolladores anteriores. El CBAD debe ser consciente de las

complejidades que surgen mientras ensambla su aplicación agregando lógica no uncional, pues los nuevfreceptáculos adicionales. Interacción Entre Componentes Se ha hablado de composición entre CF y CNF, pero no está claro cómo queda el nuevo componente compuesto en su interior. Surgen algunas preguntas: ¿Cómo se relacionan el CF y el CNF? ¿Qué pasa cuando se invoca un servicio sobre el uevo componente CF’?n

e

CF

CNF

+

m1()

mnf()

ICF

ICF’

ICNF

m1()?

Figura 22: Ejecución de métodos sobre el nuevo componente CF’

La interacción entre los componentes encierra la solución a los interrogantes anteriores. Para resolver dicha interacción es necesario un nuevo componente mediador capaz de interceptar los llamados al CF para aplicar la lógica no funcional del CNF.

Page 40: Lenguaje para Definir Interacción entre Componentes: Caso ...

39

Interceptor ICF

ICFICNF

CNF

CF

Figura 23: Mediador de la interacción

El mediador es un componente generado mediante técnicas de AOSD con la ayuda de un lenguaje de dominio específico llamado ISL (Interaction Specification Lenguage) 1 que hace parte de la presente propuesta. La interface del mediador (ICF’) es la misma exportada por el nuevo componente, y por lo tanto, debe tener los métodos de ICF. La implementación de los métodos del mediador debe resolver el orden de llamados entre los diferentes componentes.

caso, se ex

cuales se encuentran invoc

contienen la lógica

la unida

5.2 Lenguaje de Interacción: ISL El ISL es un Lenguaje Orientado a Aspectos (DSAL – Domain Specific Aspect Language) creado para expresar la interacción entre componentes. En este

presa la interacción entre componentes funcionales y no funcionales. Mediante técnicas de AOSD se modifica la secuencia normal de ejecución de

la aplicación para agregar la lógica no funcional [2]. La secuencia de ejecución se modifica con base en condiciones específicas del entorno de ejecución: si una condición se cumple, se ejecutan las acciones necesarias [24]. Por ejemplo, si un método del CF que cumple cierta condición (nombre, tipo de retorno, parámetros) es invocado, se puede interceptar para ejecutar acciones antes o después de la ejecución de dicho método, e inclusive, reemplazar su ejecución. Las acciones a ejecutar hacen parte de la interacción, dentro de las

aciones a otros componentes, es decir, a los CNFs. Se interceptan los llamados al CF para poder agregar la lógica no funcional

del CNF, dicho trabajo lo realiza el mediador tal y como se mencionó. Para saber exactamente donde se intercepta se usan los pointcuts, estos permiten cuantificar o seleccionar los puntos exactos a interferir (JoinPoints). Los advices

de interacción con el orden de llamados entre el CF y el CNF. No existe ninguna diferencia de estructura entre el ISL y los lenguajes

tradicionales de AOP, por lo tanto, la sintaxis de éste es una adaptación de AspectJ [33]. La semántica varia: en AspectJ la unidad base del lenguaje (Aspect) representa el aspecto transversal en la aplicación, mientras que en el ISL

d base es la interacción y los aspectos están encapsulados en los CNFs.

1 La idea original de expresar la interacción mediante un lenguaje la mostraron Anis Charfi, Michel Riveill y Mireille Blay-Fornarino en Transparent and Dynamic Aspect Composition. [1]

Page 41: Lenguaje para Definir Interacción entre Componentes: Caso ...

40

El rol encargado de describir la interacciDesarrollador de Requerimientos No Funcionales (NF

ón mediante el ISL es el RD), por lo tanto, él provee

se puede definir un Aspecto conociendo los métodos de la

los servicios del CF. Las propiedades son meta-data adicional asignada al CF y especificada por el desarrollador de RNFs. Por ejemplo, un CNF de seguridad puede necesitar de información que indique los roles de usuario que pueden acceder a un servicio. Las propiedades describen dicha información mediante sus atributos.

tanto el CNF como la expresión de la interacción con cualquier CF.

5.2.1 Cuantificación basada en meta-data

En lenguajes cómo AspectJ, clase objetivo (la clase con la que se va a entretejer). Esta solución propone

algo más general, en donde el desarrollador de RNFs no conoce el CF objetivo, lo que implica que no conoce sus servicios (métodos) y no puede escribir los pointcuts con base en ellos.

Es necesario cuantificar con base en propiedades asociadas a

Propiedades

- RolesAllowed- PermitAll- DenyAll

Se expresamediante

ISL

Con base en

Interacción CFCNF

Seguridad

Figura 24: Ejemplo de interacción y propiedades

En el ejemplo de seguridad mostrado en la figura 23, se define la propiedad atributos es roles, el cual tiene la lista de los roles

asociadas tanto al componente como a

5.2.2 Ejemplo Logging

illo de interacción en el ISL para hacer los métodos de un componente.

RolesAllowed y uno de sus permitidos. Las propiedades pueden estar sus servicios.

A continuación de muestra un ejemplo sencgging de mensajes cuando se ejecutanlo

Page 42: Lenguaje para Definir Interacción entre Componentes: Caso ...

41

package uniandes.gaita.rnf.logger;

ogger.property.LogMessage; p ;

nalReceptacle

tcut logging() : call(@LogMessage);

be

tcut logging permite seleccionar los JoinPoints alcan

cia a la interacción mediante la anotación

en el ejemplo), se asocian a los CFs con los

JoinPoints: están orientados sólo a la invocación de servicios y, creación y destrucción de instancias de los componentes. Pointc asignadas a los componentes o a los r

dada.

destruction(@Propiedad): asociado a la destrucción de instancias del

(variable): pointcut primitivo que permite asignar la

import uniandes.gaita.rnf.lim ort uniandes.gaita.rnf.logger.cnf.ILogger

oninteracti Logger () {

r @Inte private ILogger logger;

n poi

fore() : logging(){ logger.log("Mensaje de ejemplo"); } }

En el ejemplo anterior, el poinzados cuando se invoca (call) un método del componente funcional que

tenga asociada la propiedad “LogMessage”. El advice de tipo “before” invoca el método “log” del CNF Logger antes de la ejecución de los métodos filtrados por logging. El CNF se agrega como una dependen

@InternalReceptacle.

Las propiedades (LogMessage que se va a componer el CNF. En el capítulo de implementación se detalla la forma en que se definen y usan las propiedades.

5.2.3 Elementos del lenguaje

uts: están orientados a las propiedades se vicios de ellos. El ISL soporta los siguientes tipos de pointcuts:

call(@Propiedad): pointcut asociado a la invocación de un servicio en el que esté presente la propiedad

if(condicion): permite evaluar los valores de las propiedades creation(@Propiedad): asociado a la creación de instancias del componente

componente @Property

propiedad del contexto a la variable propiedad definida como parámetro del pointcut.

Page 43: Lenguaje para Definir Interacción entre Componentes: Caso ...

42

Advices: contienen en su cuerpo el código Java que resuelve la interacción entre los componentes. Intera

CF y los CNFs. Es el equivalente al Aspecto (aspect) en AspectJ, sólo que la lógica No funcional se expresa en

Los detalles de la sintaxis del lenguaje ISL y algunos ejemplos se pueden

Cuando un desarrollador de RNFs crea un CNF, expresa la interacción de éste con un sólo CF. Dicha interacción (uno a uno) es llamada Interacción Básica. Con la interacción básica y las propiedades, un cliente de la solución provista, puede aplicar lógica no funcional a un CF.

ction: describe el inicio de un conjunto de pointcuts y advices que permiten expresar la forma en que interactúan los

componentes externos.

encontrar en el capítulo de especificación.

5.2.4 Tipos de interacción

CF

CF’

CNF+

Figura 25: Interacción básica

Uniendo interacciones básicas se pueden aplicar más de un CNF, uno después de otro, por ejemplo: aplica Logger y obtiene su CF’ con funcionalidad de logging; aplica seguridad a su CF’ y obtiene su CF’’ con funcionalidad de logging y seguridad, y así sucesivamente (ver figura 26).

CF

CF’

Logger

+

CF’’

Seguridad

+

CF

CF’

Logger

+

Figura 26: Interacción básica + secuencia

Es posible que la interacción básica e incluso la secuencia de ellas, no sea suficiente en escenarios más complejos. En la invocación de un servicio de un componente pueden interferir más de un RNF a la vez: ciclo de vida, seguridad, logger, persistencia, transacciones, etc. Para resolver casos más complejos de

Page 44: Lenguaje para Definir Interacción entre Componentes: Caso ...

43

interacciones el modelo se puede extender creando interacciones complejas que permitan expresar la relación del CF con más de un CNF a la vez.

CF

CF’CNF1

CNF2+

CNF3

Figura 27: Interacción compleja

No hace parte del presente trabajo indicar la forma correcta de la aplicación de los RNFs ni el control de las posibles interferencias al aplicar más de uno a la vez. Un desarrollador de aplicaciones basadas en componentes (CBAD) debe ser consciente de las complejidades que surgen mientras ensambla su aplicación con

. El cliente final recibe una instancia del m

método del CF necesita de lógica no funcional (porque una propiedad asoc

faces si la interacción así lo desc

dos tipos de mediadores: los que intervienen los eventos del ciclo de v

permite resolver la instancia adecuada que s

se intercepta o no, y las acciones a

lógica no funcional.

5.2.5 Mediadores

Los mediadores, al igual que en otros modelos de componentes (EJB por ejemplo), son componentes que se anteponen a los llamados del cliente sobre el CF para ejecutar la lógica adicional necesaria

ediador y no del CF como tal (aunque él no lo sabe). El componente es generado cuando se interpreta la interacción.

El código Java de los advices forma parte de los métodos del mediador. Cuando un

iada a él así lo describe) dicha lógica queda en el método equivalente en el mediador.

El mediador puede implementar otras interribe. Los métodos de las interfaces implementadas formarán parte de los

servicios que ofrecerá el componente compuesto. Existen ida del componente y los que intervienen los llamados a los servicios del

componente. Un mediador a nivel de Ciclo de Vida e va a entregar a un cliente ayudándose de un CNF de Ciclo de Vida. Este

tipo de mediador es conocido como Home.

Un mediador a nivel de servicio permite interceptar cualquier invocación a un método o servicio del componente. Esto implica que dicho mediador debe implementar la misma Interface del componente objetivo, o por lo menos, una que herede de ella. La decisión de si un método

Page 45: Lenguaje para Definir Interacción entre Componentes: Caso ...

44

tomar a en caso de interceptarlo dependen de la interpretación del ISL. Este tipo de mediador es conocido como Interceptor.

Figura 28: Tipos de mediadores

instancia correcta a entregar al cliente por medio de un CNF de Ciclo de Vida. Más detalles sobre el manejo del Ciclo de Vida se pueden ver con el ejemplo relacionado en el capítulo de ejemplos. No deben existir advices con expresiones de pointcuts mixtas, es decir, no se pueden mezclar Creation y Destruction con Call.

En la figura 28 se muestran los tipos de mediadores que se generan tras interpretar una interacción.

El mediador Home es generado cuando se encuentran en el ISL poincuts del tipo “creation” o “destruction”. Los advices deben devolver (return) la

Page 46: Lenguaje para Definir Interacción entre Componentes: Caso ...

45

5.2.6 Ejemplo Sencillo de Seguridad

Mediante el siguiente ejemplo, se quieren mostrar otras características del lenguaje como: paso del contexto de ejecución en los parámetros de los poincuts, creación de nuevos receptáculos y creación de nuevas facetas. El ejemplo siguiente describe la interacción básica de un CNF de Seguridad: package uniandes.gaita.rnf.security; import uniandes.gaita.rnf.security.property.RolesAllowed; import uniandes.gaita.rnf.security.cnf.ISecurity; import uniandes.gaita.rnf.security.cnf.SecurityContext; import uniandes.gaita.rnf.security.interaction.ISecurityContext; interaction Security implements ISecurityContext{ alReceptacle @Intern private ISecurity security;

@Ext private ISecurityContext nextSecure;

ernalReceptacle

pointcut secure(RolesAllowed ra): call(@RolesAllowed) && @property(ra);

around(RolesAllowed ra) : secure(ra) {

if (security.validate(ra.roles()){ optreturn proceed(ra); }else{

System.out.println("Permiso Denegado"); }

}

public boolean login(String user, String pwd){

boolean ok = security.login(user, pwd);

if (ok && nextSecure != null){ SecurityContext context = security.getContext();

nextSecure.setContext(context); }

return ok;

} public void setContext(ScurityContext context){

se text(coif (nextSecure != null){ curity.setCon ntext);

nextSecure.setContext(user, pwd); }

} }

Page 47: Lenguaje para Definir Interacción entre Componentes: Caso ...

46

En el ejemplo, se validan los permisos de un usuario para ejecutar los servicios de un CF que tengan la propiedad @RolesAllowed. El CNF es referenciado mediante su Interface (ISecurity) y dicha referencia se agrega como atributo de la interacción anotado con @InternalReceptacle.

La interacción implementa la Interface ISecurityContext la cual tiene los métodos login y setContext. El método login sirve para registrar un usuario en el CNF. EL método setContext sirve para pasar contextos de seguridad entre componentes. Cuando la interacción implementa una Interface, dicha Interface se convierte en una nueva faceta del componente final.

La anotación @ExternalReceptacle permite definir nuevos receptáculos del componente resultado. En el ejemplo, el atributo nextSecure es del tipo ISecurityContext y está anotado con ExternalReceptacle, lo que quiere decir que ISecurityContext representa un nuevo receptáculo del componente final. Mediante éste receptáculo el componente puede notificar el registro de usuarios a los componentes vecinos que también tienen seguridad, ya sea invocando nuevamente el método login, o pasándoles el contexto de seguridad.

ICF

ICFISecurity

Interceptor

Security

CFA

ISecurityContext ICF

ISecurityContext

ICF

ISecurity

Interceptor

Security

CFB

Figura 29: Componente final con seguridad

En la figura se muestran dos componentes comunicados por medio de las nuevas interfaces (ISecurityContext – como faceta y receptáculo) que se generan en la construcción de un componente con Seguridad.

Page 48: Lenguaje para Definir Interacción entre Componentes: Caso ...

47

5.3 Resumen de la solución Para la ejecución de la propuesta se define un marco de trabajo basado en los diferentes roles que intervienen. Básicamente, se busca abstraer de la complejidad del manejo de los RNF a los desarrolladores finales, quienes pueden crear su CF sin pensar en la lógica No Funcional. A continuación se incluye una imagen que resume la solución.

Desarrollador de Componentes

Desarrollador de RNF

Leneguaje de Componentes

Componente Funcional

Interacción Básica

Interacción Específica

Rol Utiliza Produce

Propiedades Descriptor+

Interacción Básica

Propiedades

CF

CF’

CNF+

CF

CF’CNF1

CNF2+

CNF3

Desarrolladorde Aplicaciones

Basadas en Componentes

ISL

Leneguaje de Componentes

ISL

Anotaciones

Leneguaje de Componentes

CF CNF+

CF

Anotaciones

Figura 30: Resumen de la solución

Descripción: un desarrollador final de componentes crea su componente funcional sin pensar en el manejo de RNFs. Por otra parte, un desarrollador de RNFs crea los CNFs y los deja en un repositorio junto con la especificación de las propiedades y la interacción básica. Un tercer desarrollador (desarrollador de aplicaciones basadas en componentes) se encarga de integrar las soluciones de los dos primeros, aplicando interacciones básicas a componentes funcionales o creando sus propias interacciones (interacciones complejas) según las necesidades de la aplicación.

Page 49: Lenguaje para Definir Interacción entre Componentes: Caso ...

48

6 Especificación del ISL En éste capítulo se incluyen algunos detalles del ISL como su sintaxis y su semántica. Se describe también la definición y uso de las propiedades.

6.1 Sintaxis y Semántica

6.1.1 Sintaxis Abstracta

A continuación se muestra el AST (Abstract Sintaxis Tree) del ISL. Se muestran sólo los elementos relacionados directamente con AOP, excluyendo el AST completo del lenguaje Java.

Además de Ponicut y Advice, de ésta clase Herdan los demás elementos declarables de Java: Método, Atributo, Anotación, Contructor, etc

*

*

0..1

0..*

kind

left, right

left, right

CompilationUnit(model)

----

pakageimportsinteractioncomments

: PackageDeclaration: List<ImportDeclaration>: InteractionDeclaration: List<Comment>

PackageDeclaration(model)

--

annotationsname

: List<AnnotationExpr>: NameExpr

ImportDeclaration(model)

---

nameisStaticisAsterisk

: NameExpr: boolean: boolean

InteractionDeclaration

- implementsList : List<ClassOrInterfaceType>

TypeDeclaration{abstract}

---

namemodifiersmembers

: String: int: List<BodyDeclaration

BodyDeclaration{abstract}

- javaDoc : JavadocComment

AdviceDeclaration

-----

kindparametersthrowingParameterspointcutExprbody

: AdviceKind: List<Parameter>: List<Parameter>: PointcutExpr: BlockStmt

PointcutDeclaration

---

nameparametersexpression

: String: List<Parameter>: PointcutExpr

PointcutExpr

<<Enum>>PointcutKind

+++++

CALLCREATIONDESTRUCTIONIFPROPERTY

: EnumConstant: EnumConstant: EnumConstant: EnumConstant: EnumConstant

SinglePointcutExpr

----

kindpropertyExprconditionargument

: PointcutKind: PropertyExpr: Expression: String

SinglePropertyExpr

--

namewithNot

: String: boolean

PropertyExpr

CompositePointcutExpr

---

leftrightop

: PointcutExpr: PointcutExpr: CompositePointcutExpr.Operat

Operator

CompositePropertyExpr

---

leftrightop

: PropertyExpr: PropertyExpr: uniandes.gaita.nf.isl.model.aop.Composit

Operator

DefinedPointcutExpr

--

namearguments

: String: List<NameExpr>

<<Enum>>AdviceKind

++++

AFTERBEFOREAROUNDAFTER_THROWING

: EnumConstant: EnumConstant: EnumConstant: EnumConstant

Page 50: Lenguaje para Definir Interacción entre Componentes: Caso ...

49

6.1.2 Sintaxis Concreta

Símbolos Terminales: van entre < > Símbolos No Terminales: van entre comillas Símbolo Distinguido: <compilation_unit> Convenciones:

λ = cadena vacía α = cualquier carácter [x] = 0 o 1 ocurrencia de x (opcional) (x)* = 0 o más ocurrencias de x x|y = x OR y ( ) = sirven para agrupar <java> = Código Java

Reglas: <compilation_unit> ::= [<package_declaration>]

(<import_declaration>)* <interaction_declaration>

<package_declaration> ::= package" <name> ";" "<import_declaration> ::= "import" ["static"] <name> [".*"] ";" <interaction_declaration> ::= "interaction" <identifier> [<impl_list>] <interaction_body> <impl_list> ::= "implements" <name> ("," <name>) <interaction_body> ::= "{" (<interaction_body_declaration>)* "}" <interaction_body_declaration> ::=

<field_declaration> |<pointcut_declaration> |<advice_declaration> |<method_declaration> |<class_declaration>

<pointcut_declaration> ::= "pointcut" <identifier> <parameters> ":" <pintcut_expression> ";" <pointcut_expression> ::= <cond_or_pointcut_expr> ("||" <cond_or_pointcut_expr>) <cond_or_pointcut_expr> ::= <cond_and_pointcut_expr> ("&&" <cond_and_pointcut_expr>) <cond_and_pointcut_expr> ::= <unary_pointcut_expr> ("&&" <unary_pointcut_expr>) <unary_pointcut_expr> ::= <single_pointcut_expr>

|<defined_pointcut_expr> |"(" <pointcut_expression> ")"

<single_pointcut_expr> ::= <pintcut_kind> "(" <property_expression> ")" |<if_pintcut_kind> "(" <expression> ")" |<property_pintcut_kind> "(" <identifier> ")" <defined_pointcut_expr> ::= <identifier> <arguments> <pintcut_kind> ::= "call |"creation"|"destruction" "<if_pintcut_kind> ::= "if" <property_pintcut_kind> ::= "@Property" <property_expression> ::= <cond_or_property_expr> ("||" <cond_or_property_expr>) <cond_or_property_expr> ::= <cond_and_property_expr> ("&&" <cond_and_property_expr>) <cond_and_property_expr> ::= <unary_property_expr> ("&&" <unary_property_expr>) <unary_property_expr> ::= <single_property_expr> | "(" <property_expression> ")" <single_property_expr> ::= ["!"] "@" <name>

Page 51: Lenguaje para Definir Interacción entre Componentes: Caso ...

50

<advice_declaration> ::= ( "around" ameters> <par|"before" <parameters> |"after" <parameters> [("throwing"|"returning") <parameters>]

) ":" <pointcut_expression> "{" <java> "}"

<identifier> ::= "a..z, A..Z" ("a..z, A..Z,_,0..9, α")* <name> ::= <identifier> ("." <identifier>)* <parameters> ::= "(" [ <parameter> ("," <parameter>)* ] ")" <parameter> ::= <type> <arguments> ::= "(" [<identifier> ("," <identifier>)* ] ")" <variable_declaration> ::= <java> <method_declaration> ::= <java> <class_declaration> ::= <java> <expression> ::= <java>

6.1.3 Semántica del ISL

A continuación se muestran las definiciones de algunos elementos del lenguaje de interacción enfatizando en la diferencia o similaridad con AspectJ.

Aspectos Generales Pointcuts Los pointcuts sólo seleccionan JoinPoints que dependen de las

propiedades (meta-data) asociadas al componente o a sus servicios. “Join Point Matching based on Meta-Data”. Ver Aspectivity [25]. AspectJ 5 soporta esa tarea nativamente.

JoinPoints Soporta sólo los siguientes: 1. Creación de instancia de componente 2. Destrucción de instancia de componente 3. Invocación de servicio del componente

Advices Funcionan igual que en AspectJ. Se debe tener especial cuidado con los de tipo “around”, pues éstos normalmente pueden retornar valores y en el ISL no se pueden saber los tipos de retorno.

Lógica no funcional La lógica no funcional no se incluye en el aspecto sino en los CNFs. Estos se referencian en el aspecto por medio de sus interfaces. Son atributos del aspecto con la anotación “InternalReceptacle”. Ejemplo: @Internprivate ILogger logger;

alReceptacle("LoggerService")

Entretejido El entretejido es externo a los componentes interrelacionados.

Entretejido tardío o en tiempo de despliegue (deploy). AspectJ modifica el código objeto durante el entretejido. El emparejamiento de los aspectos se realiza en tiempo de compilación.

Soporte a Java La interacción soporta la declaración la mayoría de los elementos del lenguaje Java: métodos, atributos, clases, etc. Ver ejemplo de seguridad.

Implementación de interfaces La interacción puede implementar interfaces Java. Dicha implementación es interpretada de la siguiente manera: cada interface implementada se convierte en un nuevo receptáculo del componente final.

Page 52: Lenguaje para Definir Interacción entre Componentes: Caso ...

51

Pointcuts

call(@Propiedad) Invocación de un servicio en el que esté presente la propiedad dada. Es indiferente la analogía con “call” y “execution” de AspectJ, pues la intercepción no es ni en el cliente ni en el objetivo, sino en un punto intermedio.

creation(@Propiedad) Intercepta la creación de instancias de componentes. Se puede comparar con “initialitation” de AspectJ

destruction(@Propiedad) Intercepta la remoción de instancias del repositorio de componentes.

@Property(variable) Similar al pointcut primitivo “@Annotation” de AspectJ. Permite guardar en “variable” la propiedad relacionada con su tipo. Ejemplo:

pointcut logging(LogMessage lm): call(@LogMessage) && @property(lm); En la variable “lm” se almacena la propiedad “LogMessage”. La variable puede ser usada posteriormente en los advices: after(LogMessage lm) returning() : logging(lm){

if (lm.includeTime()){ logger.log("["+ new Date().toString() + "a] - " +

lm.value()); }

} if(condicion) Igual que en AspectJ. Es un pointcut primitivo que permite evaluar

condiciones a partir de las variables definidas en el pointcut. Ejemplo: pointcut logging(LogMessage lm): call(@LogMessage) && @property(lm) && if(lm.value() != ""); Evalua que el atributo “value” de LogMessage no esté vacio.

Advices

before Intercepta antes de … after Intercepta después de … (Sin importar si ocurre o no excepción) after throwing Intercepta después de …, y se activa cuando ocurre una

excepción. En la clausula “throws” se puede definir solo la excepción Throwable para poder lanzar cualquier excepción. No necesita la cláusula throws para lanzar excepciones. Se usa el objeto del contexto exceptionHandler para lanzar excepciones de forma controlada.

after returning Intercepta después de …, y se activa cuando no ocurre excepción en el método.

around Encierra la ejecución de un método. No necesita definir tipos de retorno. Se usa la palabra reservada optreturn para retornar valores de forma controlada (el método emparejado podría retornar void). El objeto del contexto proceed no se puede usar esperando que retorne algo.

Page 53: Lenguaje para Definir Interacción entre Componentes: Caso ...

52

Objetos del contexto

thisJoinPoint Funciona igual que en AspectJ. Retorna un objeto al que se le puede pedir el método, la clase y el componente Gaita actuales. Ejemplo: before(LogMessage lm) : logging(lm){

Method m = thisJoinPoint od(); .getMethString classNa thisJoinPoint.getClass().getName(); me = Component c = thisJoinPoint.getComponent(); Logger.log("[" + className + "] – " + lm.value(); Logger.log("Logger en el servicio: " + method.getName()); Logger.log("Del componente: " + c.getServiceName());

} proceed Aplica, pero no se puede esperar que retorne algo, ya que no se

sabe el tipo de retorno del método emparejado. Se debe usar con optreturn. Ejemplo: around(RolesAllowed ra) : secure(ra) {

if t ate(ra.roles()){ (securi y.valid optreturn proceed(ra); }else{

System.out.println("Permiso Denegado"); } }

Ejemplo no válido: String result = proceed(ra);

exceptionHandler Objeto que permite lanzar excepciones en el advice de forma controlada. Ejemplo:

after() throwing(Throwable t) : logging(){

logger.error("Se presentó un error: ", t); exceptionHandler.throw(t);

}

Operadores

&&, ||, ¡ Permiten crear expresiones lógicas en los pointcuts y en sus propiedades. Ejemplo: pointcut noCicloVida(): !(creation(@Stateless) || creation(@Stateful)); pointcut logNotSecure(): call(@LogMessage && !@RollesAllowed);

6.2 Especificación y uso de las propiedades Las propiedades son definidas por un usuario y usadas por otro. El desarrollador de RNFs es el encargado de especificar qué propiedades necesita su CNF para poder aplicar la lógica no funcional a cualquier CF. Un desarrollador de aplicaciones asocia las propiedades al CF y define los valores de sus atributos.

Para no ser intrusivos con el CF, las propiedades se especifican y definen externamente. Para ello se usan anotaciones y archivos XML.

Page 54: Lenguaje para Definir Interacción entre Componentes: Caso ...

53

6.2.1 Especificación

Para especificar las propiedades y sus atributos se usan anotaciones de Java5 [31]. Las anotaciones permiten representar meta-data en estructuras con sintaxis y semántica bien definidas. A continuación se muestra un ejemplo de definición de propiedad (LogMessage) mediante anotación de Java 5: package uniandes.gaita.rnf.logger.property; public @interface LogMessage { /** * Mensaje a loggear */ String value() ; /** * Decide si se incluye fecha/hora * al final del mensaje */ boolean includeTime(); }

6.2.2 Uso de la propiedad

Usar las propiedades definidas significa asociarlas a los componentes funcionales (ya sea al componente en sí o a sus servicios). La forma no intrusiva de asociación es mediante un archivo XML externo (descriptor). La solución actual, también permite anotar las clases y métodos de los componentes, tal como lo soporta EJB 3.0. Se puede presentar el caso en que un mismo desarrollador construye los componentes funcionales y no funcionales, y él mismo sea consciente del uso de las anotaciones.

El nuevo descriptor XML es llamado “nf-descriptor.xml” y su estructura contiene: definición de los métodos factibles de interceptar, definición de las propiedades y el emparejamiento entre los métodos y propiedades definidos. Se debe crear un descriptor para cada CF al que se quiera aplicar lógica no funcional. El siguiente es un ejemplo de dicho descriptor: <?xml version="1.0" encoding="UTF-8"?> <nf-descriptor> <component> <service>SumadorService</service> <interface>uniandes.gaita.sumador.ISumadorService</interface> </component> <methods><!-- métodos CF --> <method> <id>sumarABInteger</id> <name>sumar</name> <return-type>java.lang.Integer</return-type> <parameters> <parameter>java.lang.Integer</parameter>

Page 55: Lenguaje para Definir Interacción entre Componentes: Caso ...

54

<parameter>java.lang.Integer</parameter> </parameters> </method> </methods> <properties> <property> <id>Stateful</id> <name>uniandes.gaita.rnf.lifecycle.property.Stateful</name> </property> <property> <id>LogMessage</id> <name>uniandes.gaita.rnf.logger.property.LogMessage</name> <attributes> <attribute> <name>value</name> <value>Hola Mundo</value> </attribute> <attribute> <name>includeTime</name> <value>false</value> </attribute> </attributes> </property> </properties> <methods-propeties> <method-propety> <method-id>sumarABInteger</method-id> <property-id>LogMessage</property-id> </method-propety> </methods-propeties> <component-propeties> <property-id>Stateful</property-id> </component-propeties> </nf-descriptor>

En el archivo XML es necesario incluir la firma completa de los métodos del componente funcional, es decir, los métodos de la clase que implementa el CF. Anotando el código es más sencillo, pero se rompe con la premisa de no ser intrusivos con la implementación del CF. El siguiente sería el mismo ejemplo sobre el método del CF usando anotaciones: @LogMessage(value="Hola Mundo", includeTime=false) public Integer sumar (Integer a, Integer b){ return a + b; }

El usuario del modelo debe decidirse por alguna de las dos opciones: XML o Anotaciones.

Page 56: Lenguaje para Definir Interacción entre Componentes: Caso ...

55

7 Motor de Interacción En éste capítulo se muestran algunos detalles de la implementación del intérprete del lenguaje ISL escrita en Java y usada para generar componentes Gaita. El intérprete hace parte del motor de interacción, un nuevo módulo que se agrega a Gaita, encargado de resolver toda la lógica de interacción. Está formado por los siguientes elementos:

Figura 31: Motor de Interacción

El Parser ISL es el componente encargado de validar la sintaxis del lenguaje y de obtener el Árbol de Sintaxis Abstracta (AST). Dicha tarea se desarrolló usando JavaCC [10]. El Parser usado es una adaptación de: gramática creada por Sreenivasa Viswanadha para Java 5 y Generación del AST con soporte a Visitor creado por Júlio Vilmar Gesser [11]. La adaptación consiste en la inclusión de los elementos de AOP e interacción.

El Intérprete es el componente encargado de generar los componentes necesarios para la composición no funcional a partir del AST. Esos elementos son: Componentes Mediadores, Conectores y Descriptores. El intérprete se apoya en el soporte al patrón Visitor del Parser y en plantillas de Velocity [32] para producir los elementos.

La información de la composición no funcional (interacción y descriptor de propiedades) ingresa al motor de interacción en tiempo de despliegue de los

Page 57: Lenguaje para Definir Interacción entre Componentes: Caso ...

56

componentes Gaita. El motor produce la red de componentes enlazados y los descriptores de composición (design.xml, development.xml, deploy.xml).

Motor deInteracción

CFinteraction.isl

nf-descriptor.xml

Repositorio deCNFs

CF

CNFSeguridad

Interceptor

descriptores Figura 32: Generación de la red de componentes

El resultado es una red de componentes enlazados funcionalmente. El siguiente paso es crear el componente compuesto, y para ello, los descriptores de composición son pasados al motor de composición de Gaita-C, el cual termina la tarea.

ICFCF

CNFSeguridad

Interceptor

CF

CNFSeguridad

Interceptor

descriptores

Motor deComposición

Figura 33: Creación del Componente Compuesto

La composición se realiza de forma estática: las propiedades no pueden

cambiar en tiempo de ejecución, lo que implica que tampoco los enlaces de los componentes cambien. La composición en Gaita-C, crea instancias de cada elemento interno del componente por cada instancia de él, es decir, en ejecución, existe una instancia del CNF, del CF y de los mediadores por cada instancia del componente compuesto. Esto representa un problema para los componentes no funcionales de los cuales se necesitan instancias compartidas.

Page 58: Lenguaje para Definir Interacción entre Componentes: Caso ...

57

8 Validación En éste capítulo se incluye la validación de la propuesta con dos ejemplos: manejo del ciclo de vida de los componentes Gaita y seguridad basada en JAAS. Los ejemplos permiten explorar diferentes aspectos de la solución.

8.1 Ciclo de Vida El ejemplo pretende extender el manejo del ciclo de vida de Gaita para permitir funcionalidades más avanzadas que se ajusten a las necesidades reales de las aplicaciones empresariales. Inicialmente la estrategia se basa en la analogía entre un componente Gaita y un EJB de Sesión de JEE.

Manejar el ciclo de vida de los componentes es una tarea que puede ser sencilla, o tan compleja como se desee. Un manejo básico implica crear las instancias y compartirlas entre los clientes (única instancia compartida) tal y como lo hace Gaita por defecto. Un manejo más avanzado podría orientarse a resolver parte de RNFs muy comunes como: concurrencia, rendimiento, manejo de estados, disponibilidad, escalabilidad, persistencia, etc. A continuación se describen algunos de esos RNFs y formas de resolverlos, al menos parcialmente, en el manejo del ciclo de vida.

Concurrencia: cuando existe una única instancia del servicio se pueden presentar colisiones entre los llamados a los métodos. Las colisiones son problemas graves que pueden generar inconsistencias incluso entre las variables de método. Entregarle una instancia diferente a cada cliente disminuye las colisiones.

Rendimiento: la creación de instancias es costosa. Crear una instancia de

un componente cada vez que el cliente quiere consumir un servicio adiciona latencias. Si se tiene un pool de instancias uniformes previamente construidas, y se le entrega una de ellas a cada cliente nuevo que se conecte, se puede mejorar la eficiencia. Los pools de instancias sin estado tienen tamaños parametrizables según la necesidad.

Estados: garantizar que los atributos de un objeto se mantienen durante

una sesión específica con un cliente. Las instancias ya no pueden ser uniformes y deben tener una identificación asociada. Cada instancia del pool ahora está amarrada a un cliente y no puede destruirse hasta que el cliente no la deje de usar. Existen entonces tantas instancias como clientes conectados, lo que puede agotar los recursos. Para garantizar la entrega de

Page 59: Lenguaje para Definir Interacción entre Componentes: Caso ...

58

una instancia a cada cliente nuevo aun cuando los recursos se agotan, se deben implementar algoritmos de persistencia temporal.

Disponibilidad: Si el repositorio de donde se extraen los objetos fallara, un

ciclo de vida con soporte de replicación podría obtener los objetos de otras máquinas.

Escalabilidad: mantener el rendimiento y correcto funcionamiento de la

aplicación sin importar la cantidad de clientes conectados. La virtualización de memoria es una técnica que garantiza escalabilidad básica. Las instancias de un pool pueden ser guardadas temporalmente en disco en caso de que los recursos de memoria se agoten, para así soportar nuevos clientes. Si los recursos de una máquina se agotan, un ciclo de vida inteligente, podría obtener los objetos de otra máquina. Antes de esperar a que los recursos se acaben, el ciclo de vida podría balancear cargas.

El ejemplo plantea una solución que busca abstraer el manejo del ciclo de vida, dejando el control de dicha tarea a componentes no funcionales. El ejemplo de ciclo de vida, más que un ejemplo, se convierte en parte de la propuesta de solución, ya que existe un mediador propio para el caso.

8.1.1 Componente no funcional ciclo de vida

Para el manejo del ciclo de vida, se parte de la estrategia usada por modelos de componentes como: CORBA, COM y EJB, en los cuales existe la noción de Home del componente. El home es una interface que permite controlar el ciclo de vida del componente (creación y destrucción de instancias). Pueden existir varios manejadores del ciclo de vida:

CN FCiclo V ida

C iclo V idaS tate less

C iclo V idaS tatefu l

C iclo V idaPooled

State less

IC icloV ida

Figura 34: Múltiples manejadores de ciclo de vida

Todo componente que incluya la faceta “ICicloVida” puede ser un componente manejador del ciclo de vida. Cada manejador puede especializarse dependiendo de las necesidades.

8.1.2 Composición no funcional

El nuevo componente compuesto tiene una faceta adicional proveniente del mediador Home. Dicho mediador, requiere de las funcionalidades ofrecidas por el manejador del ciclo de vida seleccionado:

Page 60: Lenguaje para Definir Interacción entre Componentes: Caso ...

59

IHome

ICF

Home

CF

CicloVida

Figura 35: Componente con ciclo de vida

El componente funcional (CF) sigue siendo el mismo original, es decir, el que un cliente que no esté interesado en ciclo de vida especializado podría utilizar. “IHome” es la Interface Home es del componente (CF) y es parte del mediador entre el cliente y el manejador del ciclo de vida (CNF). En IHome, el método create devuelve el GaitaId de una nueva instancia del CF y el método remove elimina una instancia dado su GaitaId. El mediador Home es un componente generado a partir de la interpretación de la interacción en el ISL y de las propiedades asociadas al CF. CicloVida es un CNF genérico encargado de manejar instancias de otros componentes, utilizando los servicios del nodo Gaita.

8.1.3 Propiedades en el ciclo de vida

Existen diferentes tipos de ciclos de vida. Para el presente ejemplo, se tienen en cuenta dos: ciclo de vida sin estado (Stateless) y con estado (Stateful). Es necesario crear una propiedad que pueda ser asociada al componente funcional, para cada tipo de ciclo de vida. Por ejemplo, si un CF tiene asociada la propiedad Stateless, significa que se le debe manejar un ciclo de vida sin estado.

La propiedad Stateless se define mediante anotación de la siguiente forma:

package uniandes.gaita.rnf.ciclovida.property; public @interface Stateless { /** * Decide si se manejan pools de instancias */ boolean pooled() ; /** * Tamaño del pool, en caso de manejarse */ int poolSize();

}

La propiedad Stateless incluye dos atributos, mediante los cuales se puede incluir manejo de pool de instancias.

La propiedad Stateful se define de la siguiente manera:

package uniandes.gaita.rnf.ciclovida.property; public @interface Stateful {

Page 61: Lenguaje para Definir Interacción entre Componentes: Caso ...

60

/** * Tamaño limite antes de empezar a virtualizar instancias */ boolean limitSize() ; }

La propiedad Stateful permite definir el límite de instancias a tener en memoria. Se incluye el atributo sólo como ejemplo, pues realmente no se tiene en cuenta, ya que el componente de ciclo de vida con estado no incluye serialización de instancias para ésta validación.

8.1.4 Interacción en el ISL

Como se mencionó anteriormente, el caso del ciclo de vida es especial, y por lo tanto la interacción se interpreta de forma diferente. El mediador generado es un componente Home con la siguiente interface:

public interface IHomeComponente { /** * Crea las instancias de los componentes * @return */ public GaitaId create(); /** * Elimina una instancia del componente * @param gaitaId GaitaId de la instancia a eliminar */ public void remove(GaitaId gaitaId);

}

El siguiente es un ejemplo de interacción de ciclo de vida: package uniandes.gaita.rnf.stateless; import uniandes.gaita.rnf.ciclovida.property.Satateless; import uniandes.gaita.rnf.ciclovida.cnf.ICicloVida; import uniandes.gaita.GaitaId; import uniandes.gaita.GaitaSearchTemplate; public interaction CicloVida { @InternalReceptacle("CicloVidaStateless") private ICicloVida cicloVida;

pointcut sinEstadoCrea(): creation teless); (@Satapointcut sinEstadoElimina(): destruction(@Satateless);

around() : sinEstadoCrea() {

GaitaSearchTempla new GaitaSearchTemplate(); te template =

template.setName(thisJoinPoint.getComponent().getServiceName());

Page 62: Lenguaje para Definir Interacción entre Componentes: Caso ...

61

optreturn cicloVida.getInstance(template);

} around() : sinEstadoElimina() { cicloVida.removeInstance(gaitaId); }

}

Los pointcuts del tipo creation y destruction permiten interceptar los eventos del ciclo de vida. En el ejemplo, al componente que tenga la propiedad Stateless se le administra el ciclo de vida. En el advice around de creación, se invoca el servicio getInstance del CNF ciclo de vida. Dicho servicio retorna una instancia del componente indicado por la plantilla de búsqueda de Gaita. El tipo de retorno no es explicito, ya que el lenguaje no permite utilizar “return”, pues los métodos alcanzados pueden retornar “void”, en su caso se usa la palabra reservada optreturn (Optional Return) y el interprete decide si retorna o no el valor.

El componente ciclo de vida, según su implementación, puede retornar la única instancia del CF (si no existe la crea), en caso de ser un CNF de ciclo de vida sin estado, o puede retornar una instancia diferente por cada solicitud, en caso de ser un CNF de ciclo de vida con estado.

8.1.5 Adaptación de clientes del componente

Los clientes del nuevo componente compuesto deben adaptarse para obtener las instancias ya no directamente del nodo, sino por medio del Home. Existen dos tipos de clientes: externos e internos, dependiendo de si están fuera o dentro de la red gaita. Cliente Externo Un cliente del componente ya no puede localizar instancias directamente del componente original sino de su Home. Una vez obtiene la referencia del Home, invoca el método create para obtener las instancias del componente objetivo. La localización e instanciación del servicio se encapsula en un Localizador (Locator):

Nodo

Adapter

IHome

ICFCFLocator

Client

CF’

Figura 36: Cliente externo del componente compuesto

Page 63: Lenguaje para Definir Interacción entre Componentes: Caso ...

62

El locator se encarga de devolver la instancia correcta al cliente. Para ello, mediante proxies dinámicos basados en la interface funcional, se encapsula todo lo relacionado con la comunicación con el nodo a través del adapter. Cliente Interno Un cliente interno del servicio (otro servicio Gaita) se conecta al nuevo componente por medio de su conector. El conector igualmente obtiene primero la referencia del Home y luego la de una instancia del componente objetivo. El GaitaId del CF obtenido debe guardarse para posteriores invocaciones. El conector es el encargado de entregar al componente consumidor la instancia adecuada. El conector hace las veces de proxy.

8.2 Seguridad El ejemplo de seguridad se introduce previamente en el capítulo de la propuesta de solución. El ejemplo tratado en ésta sección es un poco diferente, pues se elimina el paso de contextos de seguridad y se aumenta el nivel de detalle en el componente no funcional de seguridad, creando éste como una implementación del servicio de autorización y autenticación de Java (JAAS).

8.2.1 Introducción a JAAS

JAAS (Java Authentication and Authorization Service) es un API que hace parte del grupo de herramientas para la gestión de la seguridad en las aplicaciones Java (JSE) [28]. Se orienta principalmente a dos elementos: la autenticación y el control de acceso basado en permisos. La autenticación funciona a modo de plugin. Se pueden crear diferentes módulos de autenticación (LoginModule) y cada uno de ellos realizar la autenticidad del usuario de formas diferentes y con tecnologías diferentes. Los módulos se conectan y registran (Configuran) en un contexto de seguridad (LoginContext) el cual ofrece el servicio de autenticación al cliente. Una vez el usuario se autentica, empieza a trabajar el componente de autorización de JAAS. El usuario (Subject) tiene una lista de roles y permisos. Cuando el proceso de autenticación es exitoso, el Subject se convierte en un Principal (Entidad autenticada con credenciales) a través del LoginModule seleccionado.

8.2.2 Componente No Funcional de Seguridad

Este componente contiene los elementos necesarios para dar soporte de autenticación y autorización basado JAAS. Tiene clases que implementan las principales interfaces: Principals, CallBackHandler y LoginModule. El componente ofrece la siguiente interface:

Page 64: Lenguaje para Definir Interacción entre Componentes: Caso ...

63

SecurityISecurity

*

ISecurity

++++

login (User user)logout ()login (User user, CallBackHandler callBack)getLoginContext ()

: boolean: void: boolean: LoginContext

User

---

namepasswordroles

: String: String: List<Role>

Role

- name : String

Figura 37: Interface del CNF de seguridad

La Interface ofrece los siguientes métodos: Login (User user): loguea al usuario en el contexto de seguridad. Recibe

como parámetro el usuario a autenticar. Dicho usuario, además del nombre y el password, tiene su lista de roles. Se hizo así por simplicidad para la presente prueba.

Login (User user, CallBackHandler callBack): al igual que login, permite autenticar el usuario, pero recibe un parámetro adicional para la interacción del CNF con el cliente. El callBack permite personalizar la forma en que se piden los datos de usuario y password al cliente.

Logout(): elimina el usuario del contexto de seguridad. getLoginContext(): devuelve el contexto de seguridad JAAS, para que pueda

ser pasado a otros componentes seguros. En el interior del componente se tiene:

Implementación del componente: clase tipo fachada encargada de realizar las operaciones contra el LoginContext.

DefaultLoginModule: modulo de logueo de JAAS. Autentica el usuario simplemente validando que el nombre no sea vacio. No valida password en esta prueba.

DefaultPrincipal: representa un Principal de JAAS

Security

ISecurityImplementación Default

LoginModule

DefaultPrincipal

DefaultCallBackHandler

Figura 38: Elementos que conforman el CNF de seguridad

Page 65: Lenguaje para Definir Interacción entre Componentes: Caso ...

64

DefaultCallBackHandler: representa un CallBackHandler de JAAS. Dicho CallBack se activa cuando se invoca el método login sin pasar un handler. Este CallBack pide los datos del usuario por medio de diálogos de swing.

8.2.3 Interacción

La interacción en el ISL es la siguiente: package uniandes.gaita.rnf.security; import uniandes.gaita.rnf.security.property.RolesAllowed; import uniandes.gaita.rnf.security.cnf.ISecurity; import javax.security.auth.login.LoginContext.LoginContext; import java.io.*; import javax.security.auth.callback.*; interaction Security { alReceptacle("SecurityService") @Intern private ISecurity security;

private User user;

pointcut secure(RolesAllowed ra): call(@RolesAllowed) && @property(ra);

around(RolesAllowed ra) : secure(ra) { try { optreturn proceed(ra); } catch (LoginException e) { if (user != null){

CallBackHandler cbh = new MyCallBackHandler(); if (security.login(user, cbh)){ optreturn proceed(ra);

} }

System.out.println("Permiso Denegado"); }

}

public class MyCallBack implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { String user, pwd; for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback)callbacks[i]; System.out.print(nc.getPrompt()); System.out.flush(); user = (new BufferedReader(

Page 66: Lenguaje para Definir Interacción entre Componentes: Caso ...

65

new InputStreamReader(System.in))).readLine(); nc.setName(user); }else if (callbacks[i] instanceof PasswordCallback){ PasswordCallback pc =

(PasswordCallback) callbacks[i]; System.out.print(pc.getPrompt()); System.out.flush();

pwd = (new BufferedReader( new InputStreamReader(System.in))) .readLine().toCharArray();

pc.setPassword(pwd); }else{ throw new UnsupportedCallbackException (callbacks[i], "Callback no reconocido"); } }

user = new User(); user.setName(user);

user.setPassword(pwd); } } }

La diferencia más importante en el ejemplo anterior es la definición de la clase interna que procesa las invocaciones desde el CNF (MyCallBackHandler). Dicha clase se encarga de obtener los datos del usuario y devolverlos al CNF. El ejemplo anterior no tiene un método login, pues automáticamente cuando se detecta un error por no existir un usuario logueado, se invoca el login del CNF. Tampoco es necesaria la invocación de un servicio “validateRoles”, pues JAAS automáticamente produce errores de seguridad cuando el usuario no tiene los permisos suficientes.

El componente final quedaría con la siguiente estructura:

ICF

ICF

ISecurity

Interceptor

Security

CF

Figura 39: Componente Final con Seguridad

El nuevo componente ofrece el servicio de seguridad de forma transparente. Cuando un servicio del componente funcional (CF) es invocado el interceptor controla las excepciones ocurridas por error de acceso y se encarga de loguear el usuario en el contexto de seguridad de JAAS.

Page 67: Lenguaje para Definir Interacción entre Componentes: Caso ...

66

9 Conclusiones 9.1 Aportes

Se define un lenguaje de dominio específico orientado por aspectos que permite describir la forma en que interactúan dos componentes que no se conocen. El lenguaje, llamado ISL (Interaction Specification Languge), permite definir interacciones de forma general, entre un componente fijo y cualquier otro componente. Se implementa el Parser de dicho lenguaje en JavaCC y se obtiene un Árbol de Sintaxis Abstracta que puede ser utilizado en diferentes intérpretes.

Se propone una solución para incluir soporte a requerimientos no funcionales en modelos de componentes, apoyada en el lenguaje de interacción definido (ISL). La solución planteada tiene en cuenta los principios de dos tecnologías relativamente recientes: Ingeniería del Software Basada en Componentes (CBSE) y Desarrollo de Software Orientado por Aspectos (AOSD).

Se aplica la solución de RNF al modelo de componentes Gaita, agregando a éste las bases para el manejo de un ciclo de vida más avanzado y creando algunos ejemplos extensibles de otros RNFs, como seguridad y logging.

Se plantean las bases de una metodología para el desarrollo funcional y no funcional basada en Roles. Se pretende abstraer a los desarrolladores finales de la complejidad de los RNFs. Se asignan responsabilidades a otros dos roles: desarrollador de RNFs y desarrollador de aplicaciones basadas en componentes.

9.2 Conclusiones El ISL permite cuantificación (Matching) basada en meta-data asignada a los

componentes. De ésta forma se puede definir una interacción de forma externa a ellos garantizando la no intrusión en sus implementaciones. Se usan sólo las interfaces de los componentes, tal y como se espera según el CBSE.

La cuantificación basada en meta-data obliga a un entretejido en tiempo de despliegue (deply-time weaving) permitiendo un mejor modelamiento de los componentes en tiempo de diseño.

Mediante la unión entre CBSE y AOSD, se obtiene una solución con bajos acoplamientos, reutilizable y extensible.

Mediante el CBSE se logran mejorar aspectos como: calidad, reutilización, mentenibilidad, etc. Los componentes le dan mayor modularidad y flexibilidad a las aplicaciones.

Mediante el AOSD se pueden separar los requerimientos funcionales de los no funcionales permitiendo un mejor modelamiento. Al expresar los aspectos no funcionales en componentes, se ganan las ventajas del CBSE.

La solución se acerca bastante a lo ideal del CBSE. Las premisas no logradas tiene que ver con lenguaje y plataforma.

Page 68: Lenguaje para Definir Interacción entre Componentes: Caso ...

67

La propuesta explota una de las más potentes premisas del CBSE: la composición de componentes. Crear componentes que se crean a partir del ensamble de otros componentes incrementa la productividad de las aplicaciones.

Fue necesario incluir el concepto de aplicación basada en componentes (CBA) para poder explotar al máximo las características de los componentes y garantizar el correcto uso de la solución.

Al expresar los requerimientos no funcionales como componentes se puede hablar de una librería de lógica no funcional reutilizable.

La solución es general en el sentido de que los componentes no funcionales pueden aplicarse a cualquier componente funcional gracias al lenguaje de interacción y la cuantificación basada en meta-data.

El lenguaje de interacción permite, con sus dos niveles de aplicación, expresar la forma en que interactúan dos o más componentes.

La solución mejora varios aspectos del modelo contenedor: independencia de contexto, componentes no funcionales reutilizables, configurables, extensibles y adaptables. Los CNFs pueden ser fácilmente modelados en los dominios funcional y no funcional.

La solución puede ser aplicada a otros modelos de componentes y no solamente a Gaita.

9.3 Trabajo Futuro Estudiar las ventajas y desventajas de permitir que la interacción modifique los

componentes relacionados. Crear un nivel más bajo de generalización, en el que se pueda expresar la

interacción con un componente funcional especifico. Estudiar las ventajas y desventajas. Posiblemente sea necesario crear dos lenguajes, como se hace en [7], o adaptar el ISL.

Tratar de definir una metodología para la separación de la lógica no funcional de la funcional. No siempre es clara dicha separación, y en muchos casos el componente funcional no se puede crear sin pensar en la lógica no funcional.

Pensar en un modelo más dinámico. Que los mediadores puedan adaptarse en tiempo de ejecución según los cambios en las propiedades.

Adaptar el modelo de composición de Gaita para poder crear instancias compartidas de los componentes internos, ya que el modelo actual siempre crea una instancia de cada componente interno por cada instancia del componente compuesto.

Implementar más ejemplos de requerimientos no funcionales sobre el modelo propuesto. En lo posible detectar conflictos que se puedan presentar al tratar de modelar más de un RNF a la vez. Deberían existir un conjunto de patrones o buenas prácticas para expresar varios RNFs en una interacción.

Page 69: Lenguaje para Definir Interacción entre Componentes: Caso ...

68

Referencias [1] A. Charfi, M. Riveill, M. Blay-Fornarino, and A. Pinna-Dery, "Transparent and

Dynamic Aspect Composition," Presentado en SPLAT Worshop, Bonn, Germany, March 2006.

[2] A. M. R. Quintero, “Visión General de la Programación Orientada a Aspectos,” Departamento de Lenguajes y Sistemas Informáticos, Facultad de Informática y Estadística, Universidad de Sevilla, Reporte técnico. Dic. 2000.

[3] C. Szyperski, D. Gruntz, and S. Murer. Component Software - Beyond Object- Oriented Programming, Addison-Wesley / ACM Press, 2002. p. 3-15.

[4] E. Bruneton, T. Coupaye, J. B. Stefani. (2004). Specification The Fractal Component Model. [AEn línea]. Disponible: http://fractal.objectweb.org.

[5] Eclipse Foundation (2008, July). AspectJ Project. Web site: http://www.eclipse.org/aspectj/

[6] F. Bachmann, L. Bass, C. Buhman, D. Comella, and F. Long. (2000). Volume. II: Technical Concepts of Component-Based Software Engineering. Software Engineering Institute, Carnegie Mellon University, Pittsburgh, PA. [AEn línea]. pp. 15-20. Disponible: http://www.sei.cmu.edu/staff/kcw/00tr008.pdf

[7] F. Duclos, J. Estublier, and P. Morat. "Describing and using non functional aspects in component based applications," Presentado en International Conference on AOSD, Enschede The Netherlands, April 2002.

[8] J. Ramírez. Modelo de Composición en Gaita-S. Universidad de los andes 2007. Documento no publicado

[9] J. Villalobos, R. Casallas, K. Marcos, P. Barvo, and C. Rocha, "Gaita-s: Model specification," Universidad de los Andes, Bogotá. Doc. técnico, 2005.

[10] Java.net (2008, July). Java Compiler Cimpiler (JavaCC). Web site: https://javacc.dev.java.net/

[11] Java.net (2008, July). JDK 5 Grammar y AST. Disponible: https:// javacc.dev.java.net/files/documents/17/44514/Java1.5_parser_and_AST.zip

[12] K. Marcos B. Gaita-nf: Un Modelo de Composición de Componentes Funcionales con Servicios No Funcionales. Bogotá, 2005. Tesis (Magíster en ingeniería de sistemas). Universidad de los Andes. Facultad de Ingeniería. Departamento de Ingeniería de Sistemas.

[13] Kiczales, G., Lamping, J., Mendhekar, A., Maeda, C., Lopes, C., Loingtier, J.M., Irwin, J.: Aspect-oriented programming. In: ECOOP, Berlin (1997)

[14] L. Fuentes, J. M. Troya y A. Vallecillo, Desarrollo de Software Basado en Componentes. Depto. Lenguajes y Ciencias de la Computación. Universidad de Málaga. Disp: http://www.lcc.uma.es/~av/Docencia/Doctorado/tema1.pdf

[15] Microsoft.(2008, feb.). .NET Framework. http://msdn.microsoft.com/ [16] N. Pessemier, L. Seinturier, L. Duchien, T. Coupaye. A Component-Based

and Aspect-Oriented Model for Software Evolution. International Journal of Computer Applications in Technology 31, 1-2 (2008) 94-105.

[17] Object Web Consortium (2008, July). The JAC Project (Java Aspect Component). Web site: http://jac.objectweb.org/

Page 70: Lenguaje para Definir Interacción entre Componentes: Caso ...

69

[18] OMG. (2006, May.). CORBA Component Model Specification, v4.0. [AEn línea] Disponible: http://www.omg.org/docs/formal/06-04-01.pdf

[19] P. Clemente, J. Herández “Aspect Component Based Software Engineering”. AOSD Workshop on Aspects, Components, and Patterns for Infrastructure Software (ACP4IS), March 2003.

[20] P. J. Barvo. Izaza. Diseño e implementación del motor del modelo de servicios Gaita-S V0. Bogotá, 2005. Tesis (Pegrado). Universidad de los Andes. Facultad de Ingeniería. Departamento de Ingeniería de Sistemas.

[21] P. J. Clemente, J. Herández and F. Sánchez. “Extending Component Composition Using Model Driven and Aspect-Oriented Techniques,” Journal of software, vol. 3, No. 1, January. 2008.

[22] R. Andersson y H. Grankvist. “Using Standard Components for Non-Functional requirements,”. Tesis de grado. Växjö University. 2002

[23] R. Patel, G. Brose, M. Silverman. Mastering Enterprise JavaBeans 3.0 4th Edition. pp. 3-88. Wiley Publishing Inc. 2006.

[24] R.E. Filman and D.P. Friedman, "Aspect-Oriented Programming is Quantification and Obliviousness," Presentado en Workshop on Advanced Separation of Concerns, OOPSLA 2000, Minneapolis, Octuber 2000.

[25] R. Laddad. (2008, feb.). Aspectivity. AspectJ language support for metadata. Disponible en http://ramnivas.com/blog/index.php?p=10.

[26] S. Clarke, R. J. Walker. “Separating Crosscutting Concerns Across the Lifecycle - From Composition Patterns to AspectJ and HyperJ,” Technical Report UBC-CS-2001-05, University of British Columbia, Canada, 2001.

[27] S. Clarke. “Designing Reusable Patterns of Cross-Cutting Behaviour with Composition Patterns,”. OOPSLA 2000, Workshop on advanced separation of concerns. Minneapolis, Minnesota.

[28] Sun Microsystems, Inc. (2008, March). Java Security Technology. Disponible: http://java.sun.com/javase/6/docs/technotes/guides/security/index.html

[29] Sun Microsystems, Inc. (2008, March). The Enterprise JavaBeans™ (EJB). Web site: http://java.sun.com/products/ejb/

[30] Sun Microsystems, Inc.(2004, Sep.). JSR 175: A Metadata Facility for the JavaTM Programming Language. [AEn línea]. Disponible: http://jcp.org/en/jsr/detail?id=175

[31] T. Cohen and J. Gil, “AspectJ2EE = AOP J2EE: Towards An Aspect Based, Programmable and Extensible Middleware Framework,” Presentado en ECOOP, Ed., vol. 3086, pp. 219– 243, Springer, 2004.

[32] The Apache Software Foundation (2008, July). The Apache Velocity Project. Web site: http://velocity.apache.org

[33] The AspectJTM 5 Development Kit Developer's Notebook. (2008, feb.). Disp: http://www.eclipse.org/aspectj/doc/released/adk15notebook/index.html

[34] Universidad de los Andes. (2008, Feb.). Grupo de Investigación en Construcción de software – Gaita. Web site, http://chie.uniandes.edu.co/~gaita/doku.php

[35] BEA, IBM, Interface21, IONA, Oracle, SAP, Siebel, Sybase. (2008, July). “Service Component Architecture”. 2005. Paper de la especificación inicial.

[36] OASIS Open CSA. (2008, July). OASIS Open Composite Services Architecture (CSA). Disponible en: http://www.oasis-opencsa.org/