1.Introducción XML | 2.Modelo XML | 3.Vista XML | 4.Tab XML | 5.Mapeo XML | 6.Aspectos XML

Capítulo 6: Aspectos XML (clásico)

Introducción a AOP

AOP (Programación Orientada a Aspectos) introduce una nueva forma de reutilizar código. Realmente complementa algunas deficiencias de la programación orientada a objetos tradicional.
¿Qué problema resuelve AOP? A veces tenemos funcionalidad que es común a un grupo de clases pero usar herencia no es práctico (en Java solo contamos con herencia simple) ni ético (porque se rompe la relación es-un). Además el sistema puede esta ya escrito, o quizá necesitamos poder incluir o no la funcionalidad bajo demanda. AOP es una manera fácil de resolver estos problemas.
¿Qué es un aspecto? Un aspecto es un puñado de código que puede ser esparcido a nuestro gusto por la aplicación.
El lenguaje Java ofrece un soporte completo de AOP mediante el proyecto AspectJ.
OpenXava añade algún soporte para el concepto de aspectos desde la versión 1.2.1. El soporte de aspectos para los componentes XML es pequeño, pero si usamos POJOs + anotaciones (desde la versión 3.0) podemos usar AspectJ y disfrutar de toda la fuerza de los aspectos.

Definición de aspectos

El archivo aspectos.xml dentro de la carpeta xava de nuestro proyecto se usa para definir los aspectos.
Su sintaxis es:
<aspectos>
    <aspecto ... /> ...  <!-- 1 -->
    <aplicar ... /> ...  <!-- 2 -->
</aspectos>
  1. aspecto (varios, opcional): Para definir aspectos.
  2. aplicar (varios, opcional): Para aplicar los aspectos definidos a los modelos seleccionados.
Con aspecto (1) podemos definir un aspecto (es decir un grupo de características) con un nombre, y usando aplicar (2) conseguimos que ese conjunto de modelos (entidades o agregados) obtengan esas características automáticamente.
Veamos la sintaxis para un aspecto:
<aspecto
    nombre="nombre"                     <!-- 1 -->
>
    <calculador-poscrear .../> ...      <!-- 2 -->
    <calculador-poscargar .../> ...     <!-- 3 -->
    <calculador-posmodificar .../> ...  <!-- 4 -->
    <calculador-preborrar .../> ...     <!-- 5 -->
</aspecto>
  1. nombre (obligado): Nombre para este aspecto. Tiene que ser único.
  2. calculador-poscrear (varios, opcional): Todos los modelos con este aspecto tendrán este calculador-poscrear implícitamente.
  3. calculador-poscargar (varios, opcional): Todos los modelos con este aspecto tendrán este calculador-poscargar implícitamente.
  4. calculador-posmodificar (varios, opcional): Todos los modelos con este aspecto tendrán este calculador-posmodificar implícitamente.
  5. calculador-preborrar (varios, opcional): Todos los modelos con este aspecto tendrán este calculador-preborrar implícitamente.
Además, tenemos que asignar el aspecto que hemos definido a nuestros modelos. La sintaxis para eso es:
<aplicar
    aspecto="aspecto"               <!-- 1 -->
    para-modelos="modelos"          <!-- 2 -->
    excepto-para-modelos="modelos"  <!-- 3 -->
/>
  1. aspecto (obligado): El nombre del aspecto que queremos aplicar.
  2. para-modelos (opcional): Una lista de modelos, separados por coma, para aplicarles este aspecto. Es exclusivo con el atributo excepto-para-modelos.
  3. excepto-para-modelos (opcional): Una lista de modelos, separados por comas, para excluir cuando se aplique este aspecto. De esta forma el aspecto es aplicado a todos los modelos menos los indicados. Es exclusivo con el atributo para-modelos.
Si no usamos ni para-modelos ni excepto-para-modelos entonces el aspecto se aplicará a todos lo modelos de la aplicación. Los modelos son los nombres de componente (para sus entidades) o agregados.
Un ejemplo simple puede ser:
<aspecto nombre="MiAspecto">
    <calculador-poscrear
        clase="com.miempresa.miaplicacion.calculadores.MiCalculador"/>
</aspecto>
<aplicar aspecto="MiAspecto"/>
De esta forma tan sencilla podemos hacer que cuando un nuevo objeto se cree (se grabe en la base de datos por primera vez) la lógica en MiCalculador sea ejecutada. Y esto para todos los modelos.
Como se ve, solo unos pocos calculadores son soportados de momento. Esperamos extender las posibilidades de los aspectos en OpenXava en el futuro. De todas formas, estos calculadores ahora ofrecen posibilidades interesantes. Veamos un ejemplo en la siguientes sección.

AccessTracking: Una aplicación práctica de los aspectos

La distribución actual de OpenXava incluye el proyecto AccessTracking. Este proyecto define un aspecto que nos permite llevar la pista de todos los acceso a la información en nuestra aplicación. Actualmente, este proyecto permite que nuestras aplicaciones cumplan con la Ley de Protección de Datos española, incluyendo los datos con un nivel de seguridad alto. Aunque es lo suficientemente genérico para ser útil en una amplia variedad de circunstancia.

La definición del aspecto

Podemos encontrar la definición del aspecto en AccessTracking/xava/aspects.xml:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
 
<!DOCTYPE aspects SYSTEM "dtds/aspects.dtd">
 
<!-- AccessTracking -->
 
<aspects>
 
    <aspect name="AccessTracking">
        <postcreate-calculator
            class="org.openxava.tracking.AccessTrackingCalculator">
            <set property="accessType" value="Create"/>
        </postcreate-calculator>
        <postload-calculator
            class="org.openxava.tracking.AccessTrackingCalculator">
            <set property="accessType" value="Read"/>
        </postload-calculator>
        <postmodify-calculator
            class="org.openxava.tracking.AccessTrackingCalculator">
            <set property="accessType" value="Update"/>
        </postmodify-calculator>
        <preremove-calculator
            class="org.openxava.tracking.AccessTrackingCalculator">
            <set property="accessType" value="Delete"/>
        </preremove-calculator>
    </aspect>
 
</aspects>
Cuando aplicamos este aspecto a nuestro componentes el código de AccessTrackingCalculator es ejecutado cada vez que un objeto es creado, cargado, modificado o borrado. AccessTrackingCalculator escribe un registro en una tabla de la base de datos con información acerca del acceso.
Para poder aplicar este aspecto necesitamos escribir en nuestro aspectos.xml algo como esto:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
 
<!DOCTYPE aspectos SYSTEM "dtds/aspectos.dtd">
 
<aspectos>
 
    <aplicar aspecto="AccessTracking" para-modelos="Almacen, Factura"/>
 
</aspectos>
De esta forma este aspecto es aplicado a Almacen y Factura. Todos los accesos a estas entidades serán registrados en una tabla de base de datos.

Configurar AccessTracking

Si queremos usar el aspecto AccessTracking en nuestro proyecto hemos de seguir los siguientes pasos de configuración:
  • Añadir AccessTracking como proyecto referenciado: Dentro de Eclipse ponerse encima del proyecto, pulsar el botón derecho e ir a Properties > Java Build Path > Projects.
  • Crear la tabla en nuestra base de datos para almacenar el registro de los accesos. Podemos encontrar los CREATE TABLEs en el archivo AccessTracking/data/access-tracking-db.script.
  • Hemos de incluir la propiedad hibernate.dialect en nuestros archivos de configuración. Puedes ver ejemplos de esto en OpenXavaTest/jboss-hypersonic.properties y otros archivos OpenXavaTest/xxx.properties.
  • Dentro del proyecto AccessTracking necesitamos seleccionar una configuración (editando build.xml) y regenerar código hibernate (usando la tarea ant generateHibernate) para AccessTracking.
  • Editamos el archivo de nuestro proyecto build/ejb/META-INF/MANIFEST.MF para añadir los siguientes jars al classpath: ./lib/tracking.jar ./lib/ehcache.jar ./lib/antlr.jar ./lib/asm.jar ./lib/cglib.jar ./lib/hibernate3.jar ./lib/dom4j.jar ./lib/slf4j-api.jar ./lib/slf4j-jdk14.jar ./lib/javassist.jar. Este paso no es necesario si solo usamos POJOs, y no usamos EJB CMP2, nuevo en v2.0. Los jars slf4j-api.jar, slf4j-jdk14.jar y javassist.jar jars son solo necesarios desde v3.1.
También necesitamos modificar la tarea ant crearJarEJB (solo si usamos EJB2 CMP) y desplegarWar de nuestro build.xml de esta forma:
<target name="crearJarEJB">    <!-- 'crearJarEJB' solo si usamos EJB2 CMP -->
    ...
    <ant antfile="../AccessTracking/build.xml" target="createEJBTracker"/>
</target>
<target name="desplegarWar">
    <ant antfile="../AccessTracking/build.xml" target="createTracker"/>
    ...
</target>
Después de todo esto, hemos de aplicar el aspecto en nuestra aplicación. Creamos un archivo xava/aspectos.xml en nuestro proyecto:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
 
<!DOCTYPE aspectos SYSTEM "dtds/aspectos.dtd">
 
<aspectos>
 
    <aplicar aspecto="AccessTracking"/>
 
</aspectos>
Ahora solo nos queda desplegar el war para nuestro proyecto (nuevo en v2.0).
En el caso de que usemos EJB2 CMP tenemos que regenerar código, desplegar EJB y desplegar el war para nuestro proyecto.
Los accesos son registrados en una tabla con el nombre TRACKING.ACCESS. Si lo deseamos podemos desplegar el módulo web o el portlet del proyecto AccessTracking para tener una aplicación web para examinar los accesos.
Para más detalle podemos echar un vistazo al proyecto OpenXavaTest.