96
JBoss Enterprise Application Platform 5 Manual del usuario de JBoss Microcontainer para uso con JBoss Enterprise Application Platform 5 Mark Newton Aleš Justin

JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Embed Size (px)

Citation preview

Page 1: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

JBoss EnterpriseApplication Platform 5

Manual del usuario deJBoss Microcontainerpara uso con JBoss Enterprise Application Platform 5

Mark Newton

Aleš Justin

Page 2: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Manual del usuario de JBoss Microcontainer

JBoss Enterprise Application Platform 5 Manual del usuario deJBoss Microcontainerpara uso con JBoss Enterprise Application Platform 5Edición 5.1.0

Autor Mark Newton [email protected] Aleš Justin [email protected] Misty Stanley-Jones [email protected]

Copyright © 2011 Red Hat, Inc.

The text of and illustrations in this document are licensed by Red Hat under a Creative CommonsAttribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is availableat http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute thisdocument or an adaptation of it, you must provide the URL for the original version.

Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert,Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.

Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the InfinityLogo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.

Linux® is the registered trademark of Linus Torvalds in the United States and other countries.

Java® is a registered trademark of Oracle and/or its affiliates.

XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United Statesand/or other countries.

MySQL® is a registered trademark of MySQL AB in the United States, the European Union and othercountries.

All other trademarks are the property of their respective owners.

Este manual está dirigido a aquellos desarrolladores Java que desean utilizar el microcontenedorJBoss para implementar entornos Java modulares y personalizados para sus aplicaciones.

Page 3: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

iii

Prefacio v1. Convenciones del Documento .......................................................................................... v

1.1. Convenciones Tipográficas ................................................................................... v1.2. Convenciones del documento ............................................................................... vi1.3. Notas y Advertencias .......................................................................................... vii

2. Cómo obtener ayuda y hacer sus comentarios ............................................................... viii2.1. ¿Necesita ayuda? .............................................................................................. viii2.2. ¡Necesitamos sus comentarios! ........................................................................... viii

I. Introducción al tutorial sobre el Microcontainer 1

1. Prerequisitos para el uso de este manual 31.1. Instale Maven ...................................................................................................... 31.2. Configuración especial de Maven para los ejemplos del microcontenedor ................. 61.3. Descarga de los ejemplos .................................................................................... 7

2. Introducción al microcontenedor 92.1. Funcionalidades ................................................................................................... 92.2. Definiciones ......................................................................................................... 92.3. Instalación .......................................................................................................... 10

3. Construcción de servicios 113.1. Introducción al ejemplo de recusos humanos ....................................................... 113.2. Compilación del proyecto de ejemplo HRManager ................................................ 123.3. Creación de POJOs ........................................................................................... 12

3.3.1. Descriptores de implementación XML ....................................................... 123.4. Conexión de POJOs ........................................................................................... 13

3.4.1. Consideraciones especiales ..................................................................... 133.5. Trabajar con servicios ......................................................................................... 14

3.5.1. Configuración de un servicio .................................................................... 143.5.2. Probar un servicio ................................................................................... 153.5.3. Empacar un servicio ................................................................................ 16

4. Uso de los servicios 194.1. Bootstrap del microcontenedor ............................................................................ 214.2. Implementación del servicio ................................................................................ 234.3. Acceso directo ................................................................................................... 244.4. Acceso indirecto ................................................................................................. 264.5. Carga de clase dinámica .................................................................................... 27

4.5.1. Problemas con cargadores de clase creados con los descriptores deimplementación ................................................................................................. 30

5. Agregar comportamiento con AOP 315.1. Creación de un aspecto ...................................................................................... 315.2. Configuración del microcontenedor para AOP ...................................................... 335.3. Aplicación de un aspecto .................................................................................... 345.4. Callbacks del ciclo de vida .................................................................................. 365.5. Agregar búsquedas de servicios por medio de JNDI ............................................. 38

II. Conceptos avanzados con el microcontenedor 41

6. Modelos de componentes 436.1. Interacciones permitidas con los modelos de componentes ................................... 436.2. Un Bean sin dependencias ................................................................................. 436.3. Uso del microcontenedor con Spring ................................................................... 436.4. Uso de Guice con el microcontenedor ................................................................. 44

Page 4: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Manual del usuario de JBoss Microcontainer

iv

6.5. MBeans de legado y mezcla de diferentes modelos de componentes ..................... 466.6. Exponer POJOs como MBeans ........................................................................... 46

7. Inyección avanzada de dependencias y ldC 497.1. Fábrica de valores .............................................................................................. 497.2. Callbacks ........................................................................................................... 507.3. Modo de acceso del Bean .................................................................................. 517.4. Alias Bean ........................................................................................................ 527.5. Soporte para anotaciones XML (o metadatos) ...................................................... 537.6. Autowire ............................................................................................................. 547.7. Fábrica de beans ............................................................................................... 557.8. Constructor de metadatos Bean .......................................................................... 567.9. ClassLoader personalizado ................................................................................. 577.10. Modo controlador .............................................................................................. 587.11. Ciclo ................................................................................................................ 587.12. Oferta y demanda ............................................................................................ 597.13. Instalaciones .................................................................................................... 597.14. Imitación perezosa ............................................................................................ 607.15. Ciclo de vida .................................................................................................... 60

8. El sistema virtual de archivos 618.1. API pública VFS ................................................................................................. 628.2. Arquitectura VFS ................................................................................................ 688.3. Implementaciones existentes ............................................................................... 688.4. Ganchos de extensión ........................................................................................ 698.5. Funcionalidades ................................................................................................. 69

9. La capa ClassLoading 719.1. ClassLoader ....................................................................................................... 719.2. ClassLoading ..................................................................................................... 769.3. Carga de clase VFS ........................................................................................... 80

10. Marco de trabajo de la implementación virtual 8110.1. Manejo agnóstico de tipos de implementación .................................................... 8110.2. Separación del reconocimiento de la estructura de la lógica del ciclo de vida dela implementación ..................................................................................................... 8110.3. Control de flujo natural en forma de anexos ....................................................... 8410.4. Detalles de la implementación y del cliente, usuario y uso del servidor ................. 8510.5. Máquina de estado único .................................................................................. 8510.6. Escaneo de clases en busca de anotaciones ..................................................... 86

A. Historial de revisiones 87

Page 5: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

v

Prefacio

1. Convenciones del DocumentoEste manual utiliza varias convenciones para resaltar algunas palabras y frases y llamar la atenciónsobre ciertas partes específicas de información.

En ediciones PDF y de papel, este manual utiliza tipos de letra procedentes de Liberation Fonts1.Liberation Fonts también se utilizan en ediciones de HTML si están instalados en su sistema. Si no,se muestran tipografías alternativas pero equivalentes. Nota: Red Hat Enterprise Linux 5 y siguientesincluyen Liberation Fonts predeterminadas.

1.1. Convenciones TipográficasSe utilizan cuatro convenciones tipográficas para llamar la atención sobre palabras o frasesespecíficas. Dichas convenciones y las circunstancias en que se aplican son las siguientes:

Negrita monoespaciado

Utilizada para resaltar la entrada del sistema, incluyendo comandos de shell, nombres de archivo yrutas. También se utiliza para resaltar teclas claves y combinaciones de teclas. Por ejemplo:

Para ver el contenido del archivo my_next_bestselling_novel en su directorioactual de trabajo, escriba el comando cat my_next_bestselling_novel en elintérprete de comandos de shell y pulse Enter para ejecutar el comando.

El ejemplo anterior incluye un nombre de archivo, un comando de shell y una tecla clave. Todo sepresenta en negrita-monoespaciado y distinguible gracias al contexto.

Las combinaciones de teclas se pueden distinguir de las teclas claves mediante el guión que conectacada parte de una combinación de tecla. Por ejemplo:

Pulse Enter para ejecutar el comando.

Pulse Control+Alt+F2 para cambiar a la primera terminal virtual. PulseControl+Alt+F1 para volver a su sesión de Ventanas-X.

La primera oración resalta la tecla clave determinada que se debe pulsar. La segunda resalta dosconjuntos de tres teclas claves que deben ser presionadas simultáneamente.

Si se discute el código fuente, los nombres de las clase, los métodos, las funciones, los nombres devariables y valores de retorno mencionados dentro de un párrafo serán presentados en Negrita-monoespaciado. Por ejemplo:

Las clases de archivo relacionadas incluyen filename para sistema de archivos,file para archivos y dir para directorios. Cada clase tiene su propio conjuntoasociado de permisos.

Negrita proporcional

Esta denota palabras o frases encontradas en un sistema, incluyendo nombres de aplicación, texto decuadro de diálogo, botones etiquetados, etiquetas de cajilla de verificación y botón de radio; títulos demenú y títulos del sub-menú. Por ejemplo:

1 https://fedorahosted.org/liberation-fonts/

Page 6: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Prefacio

vi

Seleccionar Sistema → Preferencias → Ratón desde la barra del menú principalpara lanzar Preferencias de Ratón. En la pestaña de Botones, haga clic en la cajillaratón de mano izquierda y luego haga clic en Cerrar para cambiar el botón principaldel ratón de la izquierda a la derecha (adecuando el ratón para la mano izquierda).

Para insertar un caracter especial en un archivo de gedit, seleccione desde la barra

del menú principal Aplicaciones → Accessories → Mapa de caracteres. Luego,

desde la barra de menúes de mapa de caracteres elija Búsqueda → Hallar…,teclee el nombre del caracter en el campo Búsqueda y haga clic en Siguiente. Elcaracter buscado se resaltará en la Tabla de caracteres. Haga doble clic en estecaracter resaltado para colocarlo en el campo de Texto para copiar y luego haga clic

en el botón de Copiar. Ahora regrese a su documento y elija Editar → Pegar desdela barra de menú de gedit.

El texto anterior incluye nombres de aplicación; nombres y elementos del menú de todo el sistema;nombres de menú de aplicaciones específicas y botones y texto hallados dentro de una interfazgráfica de usuario, todos presentados en negrita proporcional y distinguibles por contexto.

Itálicas-negrita monoespaciado o Itálicas-negrita proporcional

Ya sea negrita monoespaciado o negrita proporcional, la adición de itálicas indica texto reemplazableo variable. Las itálicas denotan texto que usted no escribe literalmente o texto mostrado que cambiadependiendo de la circunstancia. Por ejemplo:

Para conectar a una máquina remota utilizando ssh, teclee [email protected] en un intérprete de comandos de shell. Si lamáquina remota es example.com y su nombre de usuario en esa máquina es john,teclee ssh [email protected].

El comando mount -o remount file-system remonta el sistema de archivollamado. Por ejemplo, para volver a montar el sistema de archivo /home, el comandoes mount -o remount /home.

Para ver la versión de un paquete actualmente instalado, utilice el comando rpm -qpaquete. Éste entregará el resultado siguiente: paquete-versión-lanzamiento.

Observe las palabras en itálicas y negrita sobre — nombre de usuario, domain.name, sistema dearchivo, paquete, versión y lanzamiento. Cada palabra es un marcador de posición, tanto para el textoque usted escriba al ejecutar un comando como para el texto mostrado por el sistema.

Aparte del uso estándar para presentar el título de un trabajo, las itálicas denotan el primer uso de untérmino nuevo e importante. Por ejemplo:

Publican es un sistema de publicación de DocBook.

1.2. Convenciones del documentoLos mensajes de salida de la terminal o fragmentos de código fuente se distinguen visualmente deltexto circundante.

Los mensajes de salida enviados a una terminal se muestran en romano monoespaciado y sepresentan así:

books Desktop documentation drafts mss photos stuff svnbooks_tests Desktop1 downloads images notes scripts svgs

Page 7: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Notas y Advertencias

vii

Los listados de código fuente también se muestran en romano monoespaciado, pero se presentany resaltan de la siguiente manera:

package org.jboss.book.jca.ex1;

import javax.naming.InitialContext;

public class ExClient{ public static void main(String args[]) throws Exception { InitialContext iniCtx = new InitialContext(); Object ref = iniCtx.lookup("EchoBean"); EchoHome home = (EchoHome) ref; Echo echo = home.create();

System.out.println("Created Echo");

System.out.println("Echo.echo('Hello') = " + echo.echo("Hello")); }}

1.3. Notas y AdvertenciasFinalmente, utilizamos tres estilos visuales para llamar la atención sobre la información que de otromodo se podría pasar por alto.

Nota

Una nota es una sugerencia, atajo o enfoque alternativo para una tarea determinada. Ignoraruna nota no debería tener consecuencias negativas, pero podría perderse de algunos trucos quepueden facilitarle las cosas.

Importante

Los cuadros con el título de importante dan detalles de cosas que se pueden pasar por altofácilmente: cambios de configuración únicamente aplicables a la sesión actual, o serviciosque necesitan reiniciarse antes de que se aplique una actualización. Ignorar estos cuadros noocasionará pérdida de datos, pero puede causar enfado y frustración.

Advertencia

Las advertencias no deben ignorarse. Ignorarlas muy probablemente ocasionará pérdida dedatos.

Page 8: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Prefacio

viii

2. Cómo obtener ayuda y hacer sus comentarios

2.1. ¿Necesita ayuda?

Si encuentra dificultades con alguno de los procedimientos descritos en este documento, visite elPortal del cliente de Red Hat en http://access.redhat.com. A través del portal del cliente, usted podrá:

• buscar o navegar a través de la base de artículos de soporte técnico sobre productos de Red Hat.

• enviar un caso de soporte a Servicios de Soporte Global de Red Hat (GSS)

• acceder a otra documentación del producto.

Red Hat alberga una lista grande de correos electrónicos para discutir sobre software de RedHat y tecnología. Encontrará un listado de las listas de correo disponibles al público en https://www.redhat.com/mailman/listinfo. Haga clic en el nombre de la lista a la que quiera suscribirse o paraacceder a los archivos de listados.

2.2. ¡Necesitamos sus comentarios!

Si encuentra algun error o si se le ocurre una manera de mejorar este manual, nos encantaríaescuchar sus sugerencias. Complete un reporte en Bugzilla frente al producto JBoss EnterpriseApplication Platform 5 y el componente doc-JBoss_Microcontainer_User_Guide.El siguiente enlace le llevará a un reporte de error ya completado para este producto: http://bugzilla.redhat.com/2.

Llene la siguiente plantilla en el campo de Description de Bugzilla. Sea tan especifico como lesea posible al describir el problema, esto ayudará a asegurarnos de que lo podemos solucionarrápidamente.

URL del documento:

Número de la sección y nombre:

Describa el problema:

Sugerencias para mejorar:

Información adicional:

Asegúrese de darnos su nombre para poder darle todo el crédito por reportar el problema.

2 https://bugzilla.redhat.com/enter_bug.cgi?product=JBoss%20Enterprise%20Application%20Platform%205&component=doc-JBoss_Microcontainer_User_Guide&version=5.1.1&short_desc=Bug%20in%20JBoss%20Microcontainer%20User%20Guide

Page 9: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Parte I. Introducción al tutorialsobre el Microcontainer

Page 10: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES
Page 11: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

3

Prerequisitos para el uso de estemanualPara poder utilizar los ejemplos en este manual es necesario instalar y configurar el software desoporte y debe descargar el código para los ejemplos.

1.1. Instale MavenLos ejemplos utilizados en este proyecto requieren Maven v2.2.0 o posteriores. Descargue Mavendirectamente de la página de inicio de Apache Maven e instale y configure su sistema tal como sedescribe en Procedimiento 1.1, “Instale Maven”.

Procedimiento 1.1. Instale Maven1. Verifique que tiene instalado Java Developer Kit 1.6 o posteriores. Este también es un

requerimiento para la plataforma empresarial.Asegúrese de que tiene instalado Java en su sistema y configure la variable de entornoJAVA_HOME en su ~/.bash_profile para Linux o en las propiedades del sistema paraWindows. Para mayor información con relación a la configuración de las variables de entorno,consulte el paso Paso 4 en este procedimiento.

2. Descargue Maven

Nota

Este paso y en el futuro se asume que ha guardado Maven en la ubicación sugerida ensu sistema operativo. Maven, como cualquier otra aplicación Java se puede instalar encualquier lugar razonable en su sistema.

Visite http://maven.apache.org/download.html.

Haga clic en el enlace de fichero zip compilado, por ejemplo apache-maven-2.2.1-bin.zip

Seleccione un espejo de descarga de la lista.

Para usuarios de LinuxGuarde el fichero zip en su directorio home.

Para usuarios de WindowsGuarde el fichero zip en su directorio C:\Documents and Settings\user_name.

3. Instale Maven

Para usuarios de LinuxExtraiga el archivo zip en su directorio home. Si seleccionó el fichero zip en el paso 2 y no vuelvea nombrar el directorio, el directorio extraído se llama apache-maven-version.

Page 12: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 1. Prerequisitos para el uso de este manual

4

Para usuarios de WindowsExtraiga el fichero zip en C:\Program Files\Apache Software Foundation. Si seleccionó el ficherozip en el paso 2 y no vuelve a nombrar el directorio, el directorio extraído se llama apache-maven-version.

4. Configure las variables del entorno

Para usuarios de LinuxAgregue las siguientes líneas a su ~/.bash_profile. Asegúrese de cambiar el [username]a su nombre de usuario real y verifique que el directorio Maven es de hecho el nombre deldirectorio. El número de la versión puede ser diferente del que se lista a continuación.

export M2_HOME=/home/[username]/apache-maven-2.2.1 export M2=$M2_HOME/bin export PATH=$M2:$PATH

Al incluir M2 al comienzo de su ruta, la versión Maven que acabó de instalar será la versiónpredeterminada utilizada. Puede que también quierar establecer la ruta de su variable de entornoJAVA_HOME con la ubicación del JDK en su sistema.

Para usuarios de WindowsAgregue las variables de entorno M2_HOME, M2 y JAVA_HOME.

1. Oprima Start+Pause|Break. Se presenta la ventana de propiedades del sistema.

2. Haga clic en la pestaña Advanced y luego haga clic en el botón Environment Variables.

3. Bajo System Variables, seleccione Path.

4. Haga clic en Edit y agregue las dos rutas Maven usando un punto y coma para separar cadaentrada. No se requieren comillas alrededor de las rutas.

• Agregue la variable M2_HOME y establezca la ruta como C:\Program Files\ApacheSoftware Foundation\apache-maven-2.2.1.

• Agregue la variable M2 y configure el valor como %M2_HOME%\bin.

5. En la misma ventana, cree la variable de entorno JAVA_HOME:

• Agregue la variable %JAVA_HOME% y establezca el valor con la ubicación de su JDK. Porejemplo C:\Program Files\Java\jdk1.6.0_02.

6. En la misma ventana actualice o cree la variable de entorno de la ruta:

• Agregue la variable %M2% para permitir que se ejecute Maven desde la línea de comandos.

• Agregue la variable %JAVA_HOME%\bin para establecer la ruta con la instalación correctade Java.

7. Haga clic en OK hasta que la ventana System Properties se cierre.

Page 13: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Instale Maven

5

5. Implemente los cambios en .bash_profile

Solo para los usuarios de LinuxPara actualizar los cambios realizados al .bash_profile en la sesión de la terminal actualproporcione su .bash_profile.

[localhost]$ source ~/.bash_profile

6. Update gnome-terminal profile

Solo para los usuarios de LinuxActualice el perfil de la terminal para asegurarse de que las iteraciones posteriores de la terminalgnome (o la terminal Konsole) lean las nuevas variables de entorno.

1. Haga clic en Edit → Profiles

2. Seleccione Default y luego haga clic en el botón Edit.

3. En la ventana Editing Profile, haga clic en la pestaña Title and Command.

4. Seleccione la opción Run command as login shell.

5. Cierre todas las terminales que tenga abiertas.

7. Verifique los cambios en las variables de entorno y en la instalación de Maven

Para usuarios de LinuxPara verificar que los cambios se han implementado correctamente, abra una terminal y ejecutelos siguientes comandos:

• Ejecute echo $M2_HOME, el cual debe retornar el siguiente resultado.

[localhost]$ echo $M2_HOME /home/username/apache-maven-2.2.1

• Ejecute echo $M2, el cual debe retornar el siguiente resultado.

[localhost]$ echo $M2 /home/username/apache-maven-2.2.1/bin

• Ejecute echo $PATH y verifique que el directorio Maven /bin está incluído.

[localhost]$ echo $PATH /home/username/apache-maven-2.2.1/bin

• Ejecute which mvn, el cual debe presentar la ruta al Maven ejecutable.

[localhost]$ which mvn ~/apache-maven-2.2.1/bin/mvn

• Ejecute mvn -version, la cual debe presentar la versión de Maven, la versión Javarelacionada y la información relacionada con el sistema operativo.

Page 14: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 1. Prerequisitos para el uso de este manual

6

[localhost]$ $ mvn -version Apache Maven 2.2.1 (r801777; 2009-08-07 05:16:01+1000) Java version: 1.6.0_0 Java home: /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/jre Default locale: en_US, platform encoding: UTF-8 OS name: "Linux" version: "2.6.30.9-96.fc11.i586" arch: "i386" Family: "unix"

Para usuarios de WindowsPara verificar que los cambios se han implementado correctamente, abra una terminal y ejecuteel siguiente comando:

• En una línea de comandos ejecute mvn -version

C:\> mvn -version Apache Maven 2.2.1 (r801777; 2009-08-06 12:16:01-0700) Java version: 1.6.0_17 Java home: C:\Sun\SDK\jdk\jre Default locale: en_US, platform encoding: Cp1252 OS name: "windows xp" version: "5.1" arch: "x86" Family: "windows"

Ha configurado de manera exitosa Maven para utilizarlo con los ejemplos en este manual.

1.2. Configuración especial de Maven para los ejemplos delmicrocontenedorMaven es un sistema modular de construcción que llama las dependencias cuando se necesitan.Los ejemplos en este manual asumen que ha incluído el bloque de XML en Ejemplo 1.1, “Archivosettings.xml de ejemplo” en su ~/.m2/settings.xml (Linux) o C:\Documents andSettings\username\.m2\settings.xml (Windows). Si el archivo no existe entonces créeloprimero.

Ejemplo 1.1. Archivo settings.xml de ejemplo

<settings> <profiles> <profile> <id>jboss.repository</id> <activation> <property> <name>!jboss.repository.off</name> </property> </activation> <repositories> <repository> <id>snapshots.jboss.org</id> <url>http://snapshots.jboss.org/maven2</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>repository.jboss.org</id> <url>http://repository.jboss.org/maven2</url> <snapshots> <enabled>false</enabled> </snapshots> </repository>

Page 15: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Descarga de los ejemplos

7

</repositories> <pluginRepositories> <pluginRepository> <id>repository.jboss.org</id> <url>http://repository.jboss.org/maven2</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>snapshots.jboss.org</id> <url>http://snapshots.jboss.org/maven2</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> </profile> </profiles></settings>

1.3. Descarga de los ejemplosLos ejemplos en este manual le muestran cómo crear un proyecto maven que dependa del JBossMicrocontainer utilizando Maven. Puede descargarlos de images/examples.zip . Esta ubicacióncambiará pero la hemos incluído para su conveniencia.

Después de descargar el archivo ZIP que contiene los ejemplos, extraiga su contenido en un lugarconveniente y mire los ejemplos para familiarizarse con su estructura.

Page 16: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

8

Page 17: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

9

Introducción al microcontenedorEl microcontenedor JBoss es un rediseño del JBoss JMX Microkernel para soportar la implementaciónPOJO directa y el uso autónomo fuera del servidor de aplicaciones JBoss.

El microcontenedor está diseñado para llenar las necesidades especificas de los desarrolladoresJava que querían utilizar técnicas de programación orientadas a objetos para implementar softwarede manera rápida. Además permite implementar software en un amplio rango de dispositivosdesde plataformas de computación móviles, entornos de computación de grande escala y lo que seencuentre entre estos dos.

2.1. Funcionalidades• Todas las funcionalidades del microkernel JMX

• Implementación POJO directa (no hay necesidad de estándar/XMBean o MBeanProxy)

• Inyección directa de dependencias de estilo IOC

• Administración mejoarada del ciclo de vida

• Control adicional sobre las dependencias

• Integración transparente AOP

• Sistema virtual de archivos

• Marco de trabajo de implementación virtual

• Carga de clase OSGi

2.2. DefinicionesEste manual usa algunos términos que puede que no le sean familiares. Algunos de ellos se definenen Lista de definición del mMicrocontenedor.

Lista de definición del mMicrocontenedorMicrokernel JMX

JBoss JMX Microkernel es un entorno Java modular. Es diferente de los entornos estándar comoJ2EE ya que el desarrollador puede escoger exactamente los componentes que son parte delentorno y dejar por fuera el resto.

POJOUn POJO (del inglés Plain Old Java Object) es un objeto Java modular y reutilizable. El nombrese utiliza para enfatizar que un objeto dado es un objeto Java normal, no es un objeto especialy en particular no es un JavaBean empresarial. El término lo utilizó por primera vez MartinFowler, Rebecca Parsons y Josh MacKenzie in September 2000 en una charla en la cual estabanresaltando los muchos beneficios de codificar la lógica empresarial en objetos java normales enlugar de utilizar beans de entidad.

Bean JavaUn bean Java es un componente software re-utilizable que se puede manipular visualmente enuna herramienta de construcción.

Page 18: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 2. Introducción al microcontenedor

10

Un bean Java es un pedazo de código independiente. No requiere herencias de ninguna claseo interfaz base en particular. Aunque los beans Java se crean principalmente en IDEs gráficostambién se pueden desarrollar en simples editores de texto.

AOPAspect-Oriented Programming (AOP) es un paradigma de programación en el cual las funcionessecundarias o de soporte se aislan de la lógica empresarial del programa principal. Es un sub-grupo de la programación orientada a objetos.

2.3. InstalaciónEl microcontenedor es una parte integral de la plataforma empresarial. En el manual de configuracióny administración encontrará mayor información sobre la instalación y configuración de la plataformaempresarial.

Page 19: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

11

Construcción de serviciosLos servicios son pedazos de código que realizan tareas que múltiples clientes necesitan. Poaranuestro propósito pondremos algunas restricciones adicionales en la definición de un servicio.Los servicios deben tener nombres únicos, a los cuales se puede hacer referencia o los clinetespueden llamar. El interior de un servicio debe ser invisible y sin importancia para los clientes. Estees el concepto "caja negra"de la programación orientada a objetos (OOP del inglés object-orientedprogramming). En OOP, cada objeto es independente y ningún otro objeto necesita saber cómo hacesu trabajo.

En el contexto del microcontenedor, los servicios se construyen desde POJOs. Un POJO es casi unservicio como tal pero no se puede acceder por un nombre único y debe ser creado por el cliente quelo necesita.

Aunque un POJO se debe crear en tiempo de ejecución por parte del cliente, no es necesarioimplementarlo por medio de una clase separada con el fin de proporcionar una interfaz bien definida.Con tal de que no se borren los métodos y campos y el acceso a ellos no sea restringido, no haynecesidad de recompilar los clientes para utilizar un POJO recién creado.

Nota

El iImplementar una interfaz solo es necesario con el fin de permitir que un cliente escojaentre implementaciones opcionales. Si el cliente se compila frente a una interfaz, se puedenproporcionar muchas implementaciones diferentes de la interfaz sin tener que recompilar elcliente. La interfaz se asegura de que las firmas de método no cambien.

El resto de este manual consiste de la creación del servicio de recursos humanos utilizando elmicrocontenedor para capturar y modularizar la lógica empresarial de la aplicación. Después de queel microcontenedor esté instalado, el código de ejemplo se encuentra en examples/User_Guide/gettingStarted/humanResourcesService.

3.1. Introducción al ejemplo de recusos humanosAl familiarizarse con la estructura del directorio de los archivos en el ejemplo note que usa laestructura del directorio estándar Maven1.

Los archivos fuente Java se encuentran en los paquetes debajo del directorio examples/User_Guide/gettingStarted/humanResourcesService/src/main/java/org/jboss/example/service después de extraer el archivo ZIP. Cada una de estas clases representa unPOJO simple que no implementa ninguna interfaz especial. La clase más importante es HRManager,la cual representa el punto de entrada del servicio proporcionando todos los métodos públicos que losclientes llamarán.

Métodos que la clase HRManager proporciona• addEmployee(Employee employee)

• removeEmployee(Employee employee)

1 http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

Page 20: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 3. Construcción de servicios

12

• getEmployee(String firstName, String lastName)

• getEmployees()

• getSalary(Employee employee)

• setSalary(Employee employee, Integer newSalary)

• isHiringFreeze()

• setHiringFreeze(boolean hiringFreeze)

• getSalaryStrategy()

• setSalaryStrategy(SalaryStrategy strategy)

El servicio de recursos humanos está compuesto de unas pocas clases, las cuales mantienenuna lista de empleados y sus detalles (direcciones y salarios, en este caso). Al utilizar la interfazSalaryStrategy es posible configurar el HRManager de manera que hayan disponibles diferentesimplementaciones de la estrategia de salario para poner límites mínimos y máximos en los salariospara diferentes roles de empleados.

3.2. Compilación del proyecto de ejemplo HRManagerPara compilar el código fuente, escriba mvn compile desde el directoriohumanResourcesService/. Esto crea un nuevo directorio llamado target/classes, el cualcontiene las clases compiladas. Para limpiar el proyecto y borrar el directorio destino emita elcomando mvn clean.

3.3. Creación de POJOsantes de poder utilizar un POJO, necesita crearlo. Necesita un mecanismo de nombrado que lepermita registrar una referencia a la instancia POJO con un nombre. Los clientes necesitan estenombre para utilizar el POJO.

El microcontenedor proporciona dicho mecanismo: un controlador. Un controlador le permiteimplementar sus servicios basados en POJO en un entorno en tiempo de ejecución.

3.3.1. Descriptores de implementación XMLDespués de compilar las clases, use un descriptor de implementación XML para crear instanciasde ellas. El descriptor contiene una lista de beans representandos instancias individuales. Cadabean tiene un nombre único de manera que los clientes lo pueden llamar en tiempo de ejecución. Elsiguiente descriptor implementa una instancia del HRManager:

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0"> <bean name="HRService" class="org.jboss.example.service.HRManager"/></deployment>

Este XML crea una instancia de la clase HRManager y la registra con el nombre HRService. Estearchivo se le pasa a un programa de implementación XML asociado con el microcontenedor entiempo de ejecución, el cual realiza la implementación real e instancia los beans.

Page 21: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Conexión de POJOs

13

3.4. Conexión de POJOsLas instancias individuales POJO solo pueden proporcionar comportamientos relativamente simples.El verdadero poder de los POJOs viene de conectarlos entre ellos para realizar tareas complejas.¿Cómo puede conectar POJOs para seleccionar diferentes implementaciones de estrategia desalarios?

El siguiente descriptor de implementación XML hace justamente eso:

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0"> <bean name="HRService" class="org.jboss.example.service.HRManager"> <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property> </bean> <bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy"/></deployment>

Este XML crea una instancia de la implementación de la estrategia de salario incluyendoun elemento <bean> adicional. Esta vez, se selecciona AgeBasedSalaryStrategy. Luego elcódigo inyecta una referencia a este bean en la instancia de HRManager creada utilizandoel bean HRService. La inyección es posible ya que la clase HRManager contiene un métodosetSalaryStrategy(SalaryStrategy strategy). Mientras tanto detrás de bastidores elmicrocontenedor JBoss llama a este método en la instancia HRManager recién creada y le pasa unareferencia a la instancia AgeBasedSalaryStrategy.

El descriptor de implementación XML causa la misma secuencia de eventos como si hubiera escrito elsiguiente código:

HRManager hrService = new HRManager();AgeBasedSalaryStrategy ageBasedSalary = new AgeBasedSalaryStrategy();hrService.setSalaryStrategy(ageBasedSalary);

Además de realizar la inyección por medio de los métodos setter de las propiedades, elmicrocontenedor JBoss también puede realizar la inyección por medio de parámetros del constructorsi es necesario. Para obtener mayores detalles consulte el capítulo sobre 'Inyección' en la parte II'Desarrollo POJO.'

3.4.1. Consideraciones especialesAunque es posible el crear instancias de clases utilizando el elemento <bean> en el descriptor deimplementación, no siempre es la mejor manera. Por ejemplo, el crear instancias de las clasesEmployee y Address es innecesario ya que el cliente crea estas en respuesta a la entrada delusuario. Todavía son parte del servicio pero no se referencian en el descriptor de implementación.

Realice comentarios en su códigoPuede definir múltiples beans dentro de un descriptor de implementación en tanto cada uno tenga unnombre único, el cual se utiliza para realizar inyecciones como se mostró anteriormente. Sin embargo,todos los beans no necesariamente representan servicios. Aunque un servicio se puede implementarutilizando un solo bean, usualmente se utilizan múltiples beans. Un bean usualmente representael punto de entrada del servicio y contiene los métodos públicos que los clientes llaman. En esteejemplo, el punto de entrada es el bean HRService. El descriptor de implementación XML no indicasi un bean representa un servicio o si un bean es el punto de entrada del servicio. Es una buena idea

Page 22: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 3. Construcción de servicios

14

el utilizar comentariosy un esquema de nombrado obvio para diferenciar los beans de servicio de losbeans que no son de servicio.

3.5. Trabajar con serviciosDespués de crear POJOs y conectarlos para formar servicios, necesita configurar los servicios,probarlos y empacarlos.

3.5.1. Configuración de un servicioLos servicios se pueden configurar de dos maneras:

• Inyección de referencias entre instancias POJO

• Inyección de valores en propiedades POJO

En este ejemplo se utiliza el segundo método. El siguiente descriptor de implementación configura lainstancia de HRManager de la siguiente manera:

• Se implementa una congelación en la contratación

• La AgeBasedSalaryStrategy implementa un nuevo valor de salario mínimo y máximo.

El inyectar referencias enter instancias POJO es una manera de configurar un servicio; sin embargo,también podemos inyectar valores en propiedades POJO. El siguiente descriptor de implementaciónmuestra cómo podemos configurar la instancia HRManager para que realice una congelación en lacontratación y para que la AgeBasedSalaryStrategy tenga un valor de salario mínimo y máximo:

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0">

<bean name="HRService" class="org.jboss.example.service.HRManager"> <property name="hiringFreeze">false</property> <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property> </bean>

<bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy"> <property name="minSalary">1000</property> <property name="maxSalary">80000</property> </bean>

</deployment>

Las clases deben tener métodos setter públicos para las propiedades relevantes de maneraque los valores se puedan inyectar. Por ejemplo, la clase HRManager tiene un métodosetHiringFreeze(boolean hiringFreeze) y la clase AgeBasedSalaryStrategy tiene losmétodos setMinSalary(int minSalary) y setMaxSalary(int maxSalary).

Los valores en el descriptor de implementación se convierten de cadenas a los tipos relevantes(boolean, int, etc) por medio de PropertyEditors JavaBean. Muchos PropertyEditors se brindan pordefecto para los tipos estándar, pero puede crear los propios si es necesario. Consulte el capítulo depropiedades en la parte II 'Desarrollo POJO' para obtener mayores detalles.

Page 23: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Probar un servicio

15

3.5.2. Probar un servicioDespués de crear sus POJOs y de conectarlos para formar servicios, necesita probarlos. JBossMicrocontainer le permite la prueba de unidades de POJOs individuales así como de servicios pormedio del uso de una clase MicrocontainerTest.

La clase org.jboss.test.kernel.junit.MicrocontainerTest hereda dejunit.framework.TestCase, configurando cada prueba realizando bootstrap en JBossMicrocontainer y agregando un BasicXMLDeployer. Luego busca la ruta de clase para un descriptorde implementación XML con el mismo nombre que la clase de prueba terminado en .xml y que seencuentra en el nombre del paquete de la clase que representa la estructura del directorio. Cualquierbean que se encuentre en este archivo se implementan y luego se pueden acceder utilizando unmétodo conveniente llamado getBean(String name).

Puede encontrar ejemplos de estos descriptores de implementación en Ejemplo 3.1, “Listado deldirectorio src/test/resources”.

Ejemplo 3.1. Listado del directorio src/test/resources

├── log4j.properties└── org └── jboss └── example └── service ├── HRManagerAgeBasedTestCase.xml ├── HRManagerLocationBasedTestCase.xml ├── HRManagerTestCase.xml └── util ├── AgeBasedSalaryTestCase.xml └── LocationBasedSalaryTestCase.xml

El código de prueba se encuentra en el directorio the src/test/java :

Ejemplo 3.2. Listado del directorio src/test/java

└── org └── jboss └── example └── service ├── HRManagerAgeBasedTestCase.java ├── HRManagerLocationBasedTestCase.java ├── HRManagerTestCase.java ├── HRManagerTest.java ├── HRManagerTestSuite.java └── util ├── AgeBasedSalaryTestCase.java ├── LocationBasedSalaryTestCase.java └── SalaryStrategyTestSuite.java

La clase HRManagerTest extiende MicrocontainerTest con el fin de configurar un número deempleados a utilizar como base para la prueba. Ejemplos individuales luego crean sub-clases enHRManagerTest para realizar el trabajo en sí. También se includyen un par de clases TestSuiteque se utilizan para agrupar ejemplos individuales por comodidad.

Para ejecutar las pruebas escriba mvn test desde el directorio humanResourcesService/.Debe ver alguna salida de registro DEBUG, el cual muestra a JBoss Microcontainer inicando e

Page 24: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 3. Construcción de servicios

16

implementando los desde el archivo XML relevante antes de ejecutar cada prueba. Al final de laprueba se borra la implementación de los beans y se apaga el microcontenedor.

Nota

Algunas de las pruebas tal como HRManagerTestCase, AgeBasedSalaryTestCase yLocationBasedSalaryTestCase prueban POJOs individuales. Otras pruebas tal comoHRManagerAgeBasedTestCase y HRManagerLocationBasedTestCase prueban serviciosenteros. De cualquier manera, las pruebas se ejecutan de la misma manera. El utilizar la claseMicrocontainerTest facilita el configurar y conducir pruebas completas de cualquier parte de sucódigo.

Las clases Address y Employee no se anidan aquí. El escribir pruebas para ellas queda de suparte.

3.5.3. Empacar un servicioDespués de probar su servicio es hora de empacarlo de manera que otros puedan utilizarlo. Lamanera más simple de hacer esto es crear una JAR que contenga todas las clases. Puede escogerel incluir el descriptor de implementación si hay una manera predeterminada sensible de configurar elservicio, pero es opcional.

Procedimiento 3.1. Empacar un servicio1. Ponga el descriptor de implementación en el directorio META-INF (opcional)

Si decide incluir el descriptor de implementación por convención se debe llamar jboss-beans.xml y se debe poner en un directorio META-INF. Esta es la distribución predeterminadapara la plataforma empresarial así que el programa de implementación JAR reconoce estadistribución y realiza la implementación de manera automática.

El descriptor de implementación no se incluye en el ejemplo de recursos humanos ya que elservicio se configura modificando el descriptor directamente como un archivo a separado.

2. Generación de la JARPara generar una JAR que contenga todas las clases compiladas introduzca mvn packagedesde el directorio humanResourcesService/.

3. Hacer la JAR disponible para otros proyectos MavenPara hacer la JAR disponible para los otros proyectos Maven introduzca mvn install conel fin de copiarlo a su repositorio Maven local. La distribución final de la JAR se puede ver enEjemplo 3.3, “Listado de los directorios org/jboss/example/service y META-INF”.

Ejemplo 3.3. Listado de los directorios org/jboss/example/service y META-INF

`-- org `-- jboss `-- example `-- service |-- Address.java |-- Employee.java |-- HRManager.java `-- util |-- AgeBasedSalaryStrategy.java |-- LocationBasedSalaryStrategy.java

Page 25: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Empacar un servicio

17

`-- SalaryStrategy.java`--META-INF `-- MANIFEST.MF `-- maven `-- org.jboss.micrcontainer.examples `-- humanResourceService

Nota

Maven crea automáticamente el directorio META-INF/maven y no estará presente si estáutilizando uns sistema de construcción diferente.

Page 26: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

18

Page 27: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

19

Uso de los serviciosEl capítulo anterior le mostró cómo crear, configurar, probar y empacar un servicio. El siguiente pasoes crear un cliente, el cual realizará el trabajo utilizando el servicio.

El cliente en este ejemplo usa un Text User Interface (TUI) para aceptar entradas del usuario ypresentar los resultados. Esto reduce el tamaño y complejidad del código ejemplo.

Todos los archivos necesarios se encuentran en el directorio examples/User_Guide/gettingstarted/commandLineClient, el cual sigue la estructura del directorio estándarMaven, como se puede ver en Ejemplo 4.1, “Listar el directorio examples/User_Guide/gettingstarted/commandLineClient”.

Ejemplo 4.1. Listar el directorio examples/User_Guide/gettingstarted/commandLineClient

├── pom.xml├── src│ ├── main│ │ ├── assembly│ │ │ ├── aop.xml│ │ │ ├── classloader.xml│ │ │ ├── common.xml│ │ │ └── pojo.xml│ │ ├── config│ │ │ ├── aop-beans.xml│ │ │ ├── classloader-beans.xml│ │ │ ├── pojo-beans.xml│ │ │ └── run.sh│ │ ├── java│ │ │ └── org│ │ │ └── jboss│ │ │ └── example│ │ │ └── client│ │ │ ├── Client.java│ │ │ ├── ConsoleInput.java│ │ │ ├── EmbeddedBootstrap.java│ │ │ └── UserInterface.java│ │ └── resources│ │ └── log4j.properties│ └── test│ ├── java│ │ └── org│ │ └── jboss│ │ └── example│ │ └── client│ │ ├── ClientTestCase.java│ │ ├── ClientTestSuite.java│ │ └── MockUserInterface.java│ └── resources│ └── jboss-beans.xml└── target └── classes └── log4j.properties

El cliente consiste de las tres clases y una interfaz que se encuentra en el directorio org/jboss/example/client.

UserInterface describe los métodos que el cliente llama en tiempo de ejecución para solicitarlla entrada del usuario. ConsoleInput es una implementación de UserInterface que crea un

Page 28: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 4. Uso de los servicios

20

TUI que el usuario utiliza para interactuar con el cliente. La ventaja de este diseño es que puedecrear fácilmente una implementación Swing de UserInterface en una fecha posterior y puedereemplazar el TUI con un GUI. También puede simular el proceso de ingreso de datos con un script.Luego puede chequear el comportamiento del cliente automáticamente usando ejemplos JUnitconvencionales que se encuentran en Ejemplo 3.2, “Listado del directorio src/test/java”.

Para que la construcción funcione primero debe construir e instalar auditAspect.jar desde eldirectorio examples/User_Guide/gettingStarted/auditAspect usando el mvn installcommand. Se crean un número de distribuciones diferentes de clientes, incluyendo una basada enAOP, la cual depende de que auditAspect.jar se encuentre disponible en el repositorio localMaven.

Si anteriormente escribió mvn install desde el directorio examples/User_Guide/gettingStarted entonces humanResourcesService.jar y auditAspect.jar ya se hanconstruído y empacado junto con el cliente así que este paso no será necesario.

Para compilar el código fuente, se realizan todos los pasos que se encuentran en Procedimiento 4.1,“Compilación del código fuente” al emitir el comando mvn package desde el directoriocommandLineClient.

Procedimiento 4.1. Compilación del código fuente1. Ejecute las pruebas de las unidades.

2. construya una JAR cliente.

3. Ensamble una distribución que contenga todos los archivos necesarios.

Después de compilar y empacar el cliente, la estructura del directorio en el diretcoriocommandLineClient/target incluye los subdirectorios descritos en Ejemplo 4.2, “Lossubdirectorios del directorio commandLineClient/target”.

Ejemplo 4.2. Los subdirectorios del directorio commandLineClient/targetclient-pojo

utilizado para llamar al servicio sin AOP.

client-clutilizado para demostrar las funcionalidades de carga de clase.

client-aopAgregar soporte AOP. Consulte Capítulo 5, Agregar comportamiento con AOP para obtenermayores detalles.

Cada sub-directorio representa una distribución diferente con todos los scripts shell, JARs ydescriptores de implementación XML que se necesitan para ejecutar el cliente en diferentesconfiguraciones. El resto de este capítulo usea la distribución client-pojo que se encuentra en elsub-directorio client-pojo, el cual se lista en Ejemplo 4.3, “Listado del directorio client-pojo”.

Ejemplo 4.3. Listado del directorio client-pojo

|-- client-1.0.0.jar |-- jboss-beans.xml |-- lib | |-- concurrent-1.3.4.jar | |-- humanResourcesService-1.0.0.jar | |-- jboss-common-core-2.0.4.GA.jar | |-- jboss-common-core-2.2.1.GA.jar

Page 29: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Bootstrap del microcontenedor

21

| |-- jboss-common-logging-log4j-2.0.4.GA.jar | |-- jboss-common-logging-spi-2.0.4.GA.jar | |-- jboss-container-2.0.0.Beta6.jar | |-- jboss-dependency-2.0.0.Beta6.jar | |-- jboss-kernel-2.0.0.Beta6.jar | |-- jbossxb-2.0.0.CR4.jar | |-- log4j-1.2.14.jar | `-- xercesImpl-2.7.1.jar `-- run.sh

Para ejecutar el cliente, cámbiese al directorio client-pojo y escriba ./run.sh. Aparecerá el TheEjemplo 4.4, “Pantalla del menú de HRManager”.

Ejemplo 4.4. Pantalla del menú de HRManager

Menú:

d) Implementar el servicio de recursos humanos u) Borrar la implementación del servicio de recursos humanos

a) Agregar empleado l) Listar los empleados r) Borrar empleado g) Ver un salario s) Establecer un salario t) Alternar la congelación de la contratación

m) Ver el menú p) Imprimir el estatus del servicio q) Salir >

Para seleccionar una opción, introduzca la letra que se muestra en el lado izquierdo y oprimaRETURN. Por ejemplo para ver lsa opciones del menú introduzca m y luego presione RETURN. Elintroducir más de una letra o el introducir una opción inválida genera un mensaje de error.

Importante

El script run.sh establece el entorno de ejecución agregando todas las JARs que seencuentran en el directorio lib/ a la ruta de clase usando la propiedad del sistema java.ext.dirs.También agrega el directorio actual y la client-1.0.0.jar usando la eiqueta -cp de maneraque el descriptor de implementación jboss-beans.xml se encuentre en tiempo de ejecuciónjunto con la clase org.jboss.example.client.Client, la cual se llama para iniciar laaplicación.

4.1. Bootstrap del microcontenedorAntes de utilizar el cliente para implementar y llamar a su servicio, mire detalladamente lo que pasódurante la construcción:

public Client(final boolean useBus) throws Exception { this.useBus = useBus;

Page 30: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 4. Uso de los servicios

22

ClassLoader cl = Thread.currentThread().getContextClassLoader(); url = cl.getResource("jboss-beans.xml");

// Start JBoss Microcontainer bootstrap = new EmbeddedBootstrap(); bootstrap.run();

kernel = bootstrap.getKernel(); controller = kernel.getController(); bus = kernel.getBus();}

Primero que todo se creó una URL que representa el descriptor de implementación jboss-beans.xml. Esto se necesita luego de manera que el programa de implementación XML puedaimplementar y borrar la implementación de los beans declarados en el archivo. El métodogetResource() del cargador de clase de la aplicación se utiliza ya que se incluye el archivojboss-beans.xml en la ruta de clase. esto es opcional; el nombre y ubicación del descriptor deimplementación no son importantes en tanto la URL sea válida y se pueda llegar a ella.

Luego se crea una instancia de JBoss Microcontainer junto con un programa de implementaciónXML. Este proceso se llama bootstrapping y se proporciona una clase llamada BasicBootstrapcomo parte del microcontenedor para tener en cuenta la configuración programática. Paraagregar un programa de implementación XML, extienda BasicBootstrap para crear una claseEmbeddedBootstrap y sobrescriba el método protegido bootstrap() así:

public class EmbeddedBootstrap extends BasicBootstrap { protected BasicXMLDeployer deployer; public EmbeddedBootstrap() throws Exception { super(); }

public void bootstrap() throws Throwable { super.bootstrap(); deployer = new BasicXMLDeployer(getKernel()); Runtime.getRuntime().addShutdownHook(new Shutdown()); }

public void deploy(URL url) { ... deployer.deploy(url); ... }

public void undeploy(URL url) { ... deployer.undeploy(url); ... }

protected class Shutdown extends Thread { public void run() { log.info("Shutting down"); deployer.shutdown(); } }}

Page 31: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Implementación del servicio

23

El gancho shutdown se asegura de que cuando la MVJ termina, se borra la implementaciónde todos los beans en el orden correcto. Los métodos públicos deploy/undeploy delegan alBasicXMLDeployer de manera que los beans declarados en jboss-beans.xml se puedanimplementar y borrar.

Finalmente las referencias al controlador del microcontenedor y el bus se reestablecen así que puedebuscar las referencias de beans por su nombre y puede accederlas directamente o indirectamentecuando los necesite.

4.2. Implementación del servicioDespués de crear el cliente puede implementar el servicio de recursos humanos. Esto se lograintroduciendo la opción d del TUI. La salida indica que el BasicXMLDeployer ha analizadosintácticamente el archivo jboss-beans.xml usando la URL y ha instanciado los beans que seencuentran adentro.

Nota

El microcontenedor puede instanciar los beans ya que sus clases están disponibles en la ruta declase de extensión dentro del archivo lib/humanResourcesService.jar. También puedeponer estas clases en una estructura de directorio expandido y agregarla a la ruta de clase de laaplicación, pero el empacarlos en una JAR usualmente es más conveniente.

El descriptor de implementación es completamente separado del archivohumanResourcesService.jar. Esto permite modificarlo para propósitos de pruebas. El archivojboss-beans.xml en el ejemplo contiene algunos fragmentos de XML comentados, lo cual muestraalgunas de las configuraciones posibles.

<?xml version="1.0" encoding="UTF-8"?><deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0">

<bean name="HRService" class="org.jboss.example.service.HRManager"> <!-- <property name="hiringFreeze">true</property> <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property> --> </bean>

<!-- <bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy"> <property name="minSalary">1000</property> <property name="maxSalary">80000</property> </bean>

<bean name="LocationBasedSalary" class="org.jboss.example.service.util.LocationBasedSalaryStrategy"> <property name="minSalary">2000</property> <property name="maxSalary">90000</property> </bean> -->

</deployment>

Page 32: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 4. Uso de los servicios

24

Importante

Dependiendo de la manera en que acceda el servicio en tiempo de ejecución es posible quenecesite apagar la aplicación y re-iniciarla para volver a implementar el servicio y ver suscambios. Esto reduce la flexibilidad de la aplicación, pero incrementa el rendimiento en tiempode ejecución. Opcionalmente puede simplemente volver a implementar el servicio mientras quela aplicación esté ejecutando. Esto incrementa la flexibilidad pero disminuye el rendimiento entiempo de ejecución. Mantenga estas opciones en consideración al diseñar sus aplicaciones.

4.3. Acceso directoSi no se le pasan parámetros al script run.sh cuando se inicia el cliente entonces se busca unareferencia al bean HRService usando el controlador del microcontenedor después de que se haimplementado el servicio:

private HRManager manager;...private final static String HRSERVICE = "HRService";

...void deploy() { bootstrap.deploy(url); if (!useBus && manager == null) { ControllerContext context = controller.getInstalledContext(HRSERVICE); if (context != null) { manager = (HRManager) context.getTarget(); } }}

En lugar del buscar inmediatamente una referencia a la instancia del bean, el ejemplo primero buscauna referencia a un ControllerContext, luego obtiene una referencia a la instancia del bean delcontexto utilizando el método getTarget(). El bean puede existir dentro del microcontenedor encualquiera de los estados listados en Estados de un Bean dentro del microcontenedor.

Estados de un Bean dentro del microcontenedor• NO_INSTALADO

• DESCRITO

• INSTANCIADO

• CONFIGURADO

• INSTALADO

Para mantener el registro de en qué estado se encuentra el bean, envuélvalo en otro objeto llamadoun context, el cual describe el estado actual. El nombre del contexto es el mismo que el nombre delbean. Una vez que un contexto alcanza el estado INSTALADO entonces el bean que representa seconsidera implementado.

Después de crear una referencia a la instancia del bean que representa el punto de entrada delservicio, puede llamar a los métodos en este para realizar tareas:

Page 33: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Acceso directo

25

@SuppressWarnings("unchecked") Set<Employee> listEmployees() { if (useBus) ... else return manager.getEmployees();}

El cliente está accediendo el servicio directamente ya que está utilizando una referencia a la instanciadel bean real. El rendimiento es bueno ya que cada llamada de método va directamente al bean. Sinembargo, ¿Qué pasa si desea re-configurar el servicio y volver a implementarlo mientras la aplicaciónestá ejecutando?

La re-configuración se logra realizando cambios al descriptor de implementación XML y guardandoel archivo. Con el fin de volver a implementar el servicio, se debe borrar la implementación de lainstancia actual. Al borrar la implementación el controlador del microcontenedor libera su referenciaa la instancia del bean, junto con los beans dependientes. Posteriormente estos beans se harándisponibles para el servicio de recolección de basura ya que la aplicación ya no los necesitamás. El volver a implementar el servicio crea nuevas instancias del bean representando la nuevaconfiguración. Cualquier búsqueda posterior de parte de los clientes recuperará las referencias aestas nuevas instancias y podrán volver a acceder el servicio re-configurado.

El problema es que la referencia a la instancia del bean que representa nuestro punto de entradadel servicio va al caché cuando implementa el servicio por primera vez. El borrar la implementacióndel servicio no tienen ningún efecto ya que la instancia del bean todavía se puede acceder usandola referencia en caché y no irá a la basura hasta que el cliente la libere. De la misma manera, elimplementar el servicio de nuevo no generará otra búsqueda ya que el cliente ya tiene una referenciaen caché. Por lo tanto continuará utilizando la instancia del bean representando la configuración delservicio inicial.

Puebe probar este comportamiento escribiendo u seguido de RETURN para borrar la implementacióndel servicio actual. Debe poder acceder el servicio todavía desde el cliente aunque haya 'borrado'la implementación. Luego, realice algunos cambios a la configuración utilizando el archivo jboss-beans.xml, guarde el archivo y vuelva a implementarlo usando la opción d. Puede imprimir elestatus del servicio utilizando la opción p, la cual muestra que el cliente todavía está accediendo lainstancia inicial del servicio que se implementó.

Aviso

Incluso si modifica el cliente para que busque una nueva referencia cada vez que el servicio sevuelve a implementar, es posible que los nuevos desarrolladores entreguen por error copias deesta referencia a otros objetos. Si todas estas referencias no se limpian al volver a realizar laimplementación se puede presentar el mismo problema de caché.

Para volver a implementar el servicio reconfigurado de manera confiable, apague la aplicacióncompletamente utilizando la opción 'q' y reinícela usando el script run.sh. Para serviciosempresariales tal como transacciones, mensajería y persistencia este es un comportamientocompletamente aceptable ya que generalmente se utilizan. No se pueden volver a implementar entiempo de ejecución y también se benefician del alto rendimiento dado por el uso del acceso directo.

Page 34: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 4. Uso de los servicios

26

Si su servicio cae en esta categoria, considere el utilizar el acceso directo por medio del controladordel microcontenedor.

4.4. Acceso indirectoEl script run.sh se puede llamar con un parámetro opcional bus, el cual hace que las llamadas alservicio de recursos humanos utilicen el bus del microcontenedor.

En lugar de utilizar una referencia directa a la instancia del bean que se obtuvo del controladormicrocontenedor, el nuevo comportamiento es llamar a un método invoke() en el bus, pasando elnombre del bean, el nombre del método, los argumentos del método y los tipos de método. El bus usaesta información para llamar al bean de parte del cliente.

private final static String HRSERVICE = "HRService";

...

@SuppressWarnings("unchecked") Set<Employee> listEmployees() { if (useBus) return (Set<Employee>) invoke(HRSERVICE, "getEmployees", new Object[] {}, new String[] {}); else return manager.getEmployees(); }

private Object invoke(String serviceName, String methodName, Object[] args, String[] types) { Object result = null; try { result = bus.invoke(serviceName, methodName, args, types); } catch (Throwable t) { t.printStackTrace(); } return result;}

El bus busca la referencia a la instancia del bean nombrado y llama al método seleccionado usandola reflexión. El cliente nunca tiene una referencia directa a la instancia del bean así que se dice queaccede al servicio indirectamente. Ya que el bus no pone en el caché la referencia puede realizar demanera segura los cambios a la configuración del servicio y se puede volver a implementar en tiempode ejecución. Las llamadas posteriores por parte del cliente utilizarán la nueva referencia tal como seespera. El cliente y el servicio han sido desvinculados.

Nota

Este comportamiento se puede probar implementado el servicio y utilizando la opción p paraimprimir el estatus. Borre la implementación del servicio utilizando la opción u y observe que esinaccesible. Luego realice algunos cambios al archivo jboss-beans.xml, guarde los cambiose implemente de nuevo usando la opción d. Imprima el estatus de nuevo usando la opción p. Elcliente está accediendo la nueva configuración del servicio.

Ya que el bus usa la refleción para llamar instancias del bean, es un poco más lento que el accesodirecto. El beneficio del enfoque es que solo el bus tiene referencias a las instancias del bean.Cuando un servicio se vuelve a implementar, todas las referencias existentes se pueden limpiary reemplazar con las nuevas. De esta manera, se puede volver a implementar de manera segura

Page 35: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Carga de clase dinámica

27

un servicio en tiempo de ejecución. Los servicios que no se utilizan con tanta frecuencia o que sonespecificos para ciertas aplicaciones son buenos candidatos para acceso indirect usando el busdel microcontenedor. Con frecuencia la reducción en el rendimiento es superior a la flexibilidad queproporciona.

4.5. Carga de clase dinámicaHasta ahora ha utilizado los cargadores de clase de aplicación y extensión para cargar todas lasclases en la aplicación. La ruta de clase de la aplicación se configura por medio del script run.shutilizando la etiqueta -cp para incluir el directorio actual y la client-1.0.0.jar como se puede veraquí:

java -Djava.ext.dirs=`pwd`/lib -cp .:client-1.0.0.jar org.jboss.example.client.Client $1

Por comodidad las JARs en el directorio lib se agregaron a la extensión de la ruta de clase delcargador de clase usando la propiedad del sistema java.ext.dirs, en lugar de listar la ruta completapara cada una de las JARs después de la etiqueta -cp. Ya que la extensión classloader espadre de la aplicación classloader, las clases del cliente pueden encontrar todas las clases delmicrocontenedor y las clases del servicio de recursos humanos en tiempo de ejecución.

Nota

Con las versiones de Java 6 y posteriores puede utilizar un comodín para incluir todas lasJARs en un directorio con la etiqueta -cp: java -cp `pwd`/lib/*:.:client-1.0.0.jarorg.jboss.example.client.Client $1

Aquí todas las clases en la aplicació se agregarán a la ruta de clase del cargador de clasede la aplicación y extensión de la ruta de clase del cargador de clase retendrá su valorpredeterminado.

¿Qué pasa si necesita implementar un servicio adicional en tiempo de ejecución? Si el nuevo servicioestá empacado en un archivo JAR debe ser visible para un cargador de clase antes de que cualquierade sus clases puedan ser cargadas. Ya que ya configuró la ruta de clase para el cargador de clasede la aplicación (y el cargador de clase de extensión) en el arranque, no es fácil el agregar la URLde la JAR. La misma situación aplica si las clases del servicio se encuentran en una estructurade directorio. A menos de que el directorio a nivel superior se encuentre en el directorio actual (elcual está en la ruta de clase de la aplicación) entonces el cargador de clase de la aplicación noencoentrará las clases.

Si desea volver a implementar un servicio existente cambiando algunas de sus clases, necesitatrabajar teniendo en cuenta las restricciones de seguridad, las cuales le impiden a un cargador declase existente el volver a cargar las clases.

La meta es crear un nuevo cargador de clases que conozca la ubicación de las clases del nuevoservicio o que pueda cargar nuevas versiones de las clases de un servicio ya existente con el finde implementar los beans del servicio. JBoss Microcontainer usa el elemento <classloader> en eldescriptor de implementación para lograr esto.

La distribución client-cl contiene el archivo listado en el Ejemplo 4.5, “Listado del directoriocommandLineClient/target/client-cl” .

Page 36: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 4. Uso de los servicios

28

Ejemplo 4.5. Listado del directorio commandLineClient/target/client-cl

|-- client-1.0.0.jar |-- jboss-beans.xml |-- lib | |-- concurrent-1.3.4.jar | |-- jboss-common-core-2.0.4.GA.jar | |-- jboss-common-core-2.2.1.GA.jar | |-- jboss-common-logging-log4j-2.0.4.GA.jar | |-- jboss-common-logging-spi-2.0.4.GA.jar | |-- jboss-container-2.0.0.Beta6.jar | |-- jboss-dependency-2.0.0.Beta6.jar | |-- jboss-kernel-2.0.0.Beta6.jar | |-- jbossxb-2.0.0.CR4.jar | |-- log4j-1.2.14.jar | `-- xercesImpl-2.7.1.jar |-- otherLib | `-- humanResourcesService-1.0.0.jar |`-- run.sh

Se ha movido el archivo humanResourcesService.jar a un nuevo sub-directorio llamadootherLib. Ya no está disponible para los cargadores de clase de extensión o de la aplicación, coyaruta de clase se configura en el script run.sh:

java -Djava.ext.dirs=`pwd`/lib -cp .:client-1.0.0.jar org.jboss.example.client.Client $1

Para solucionar esto cree un nuevo cargador de clase durante la implementación del servicio,cárguela en las clases del servicio y cree instancias de los beans. Para ver cómo se logra esto vea elcontenido del archivo jboss-beans.xml:

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0">

<bean name="URL" class="java.net.URL"> <constructor> <parameter>file:/Users/newtonm/jbossmc/microcontainer/trunk/docs/examples/User_Guide/gettingStarted/commandLineClient/target/client-cl.dir/otherLib/humanResourcesService-1.0.0.jar</parameter> </constructor> </bean>

<bean name="customCL" class="java.net.URLClassLoader"> <constructor> <parameter> <array> <inject bean="URL"/> </array> </parameter> </constructor> </bean>

<bean name="HRService" class="org.jboss.example.service.HRManager"> <classloader><inject bean="customCL"/></classloader> <!-- <property name="hiringFreeze">true</property> <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property> --> </bean>

Page 37: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Carga de clase dinámica

29

<!-- <bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy"> <property name="minSalary">1000</property> <property name="maxSalary">80000</property> </bean>

<bean name="LocationBasedSalary" class="org.jboss.example.service.util.LocationBasedSalaryStrategy"><property name="minSalary">2000</property><property name="maxSalary">90000</property></bean> -->

</deployment>

1. Primero cree una instancia de java.net.URL llamada URL, usando la inyección de parámetrosen el constructor para especificar la ubicaci´on del archivo humanResourcesService.jar enel sistema local de archivos.

2. Luego, cree una instancia de un URLClassLoader inyectando el bean URL en el constructorcomo único elemento en el array.

3. Incluya un elemento <classloader> en su definición de bean HRService e inyecte el beancustomCL. Esto especifica que la clase HRManager necesita ser cargada por el cargador declase customCL.

Necesita una manera de decidir cuál cargador de clase utilizar para los otros beans en laimplementación. Todos los beans en la implementación utilizan el cargador de clase del contexto delhilo actual. En este caso el hilo que maneja la implementación es el hilo principal de la aplicación, elcual tiene su cargador de clase de contexto establecido para el cargador de clase de la aplicacióndurnate el arranque. Si desea puede especificar un cargador de clase diferente para toda laimplementación utilizando un elemento <classloader> como se puede ver en Ejemplo 4.6, “Especificarun cargador de clase diferente”.

Ejemplo 4.6. Especificar un cargador de clase diferente

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0">

<classloader><inject bean="customCL"/></classloader>

<bean name="URL" class="java.net.URL"> <constructor> <parameter>file:/Users/newtonm/jbossmc/microcontainer/trunk/docs/examples/User_Guide/gettingStarted/commandLineClient/target/client-cl.dir/otherLib/humanResourcesService-1.0.0.jar</parameter> </constructor> </bean>

<bean name="customCL" class="java.net.URLClassLoader"> <constructor> <parameter> <array> <inject bean="URL"/> </array> </parameter> </constructor> </bean>

Page 38: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 4. Uso de los servicios

30

...

</deployment>

Esto sería necesario para permitir la reconfiguración del service al borrar los comentarios de losbeans AgeBasedSalary o LocationBasedSalary. Los cargadores de clase especificados anivel del bean sobreescriben el cargador de clase a nivel de la implementación. Para sobreescribir elcargador de clase a nivel de implementación y utilizar el cargador de clase predeterminado para unbean, use el valor <null/> así:

<bean name="HRService" class="org.jboss.example.service.HRManager"> <classloader><null/></classloader></bean>

4.5.1. Problemas con cargadores de clase creados con losdescriptores de implementaciónSi crea un nuevo cargador de clase para su servicio utilizando el descriptor de implementaciónes posible que no pueda acceder las clases cargadas por este desde el cargador de clase de laaplicación. En el ejemplo HRManager, el cliente ya no puede poner en caché una referencia directa ala instancia del bean al utilizar el controlador del microcontenedor.

Para ver este comportamiento inicie el cliente usando el comando run.sh y luego trate deimplementar el servicio. Se presenta una excepción java.lang.NoClassDefFoundError y laaplicación termina.

En este escenario debe usar el bus para acceder el servicio indirectamente y proporcionar accesoa cualquier clase compartida por el cliente en la ruta de clase de la aplicación. En este ejemplo, lasclases afectadas son Address, Employee y SalaryStrategy.

Page 39: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

31

Agregar comportamiento con AOPLa programación orientada a objetos (OOP del inglés Object Oriented Programming) tiene muchastécnicas útiles para el desarrollo de software incluyendo la encapsulación, herencia y polimorfismo.Sin embargo, no soluciona el problema de la lógica de direccionamiento que con frecuencia se repiteen muchas clases diferentes. Ejemplos de esto incluye los registros, seguridad y lógica transaccional,la cual es tradicionalmente codificada a fuego en cada clase. Este tipo de lógica se llama un asuntode corte transversal.

La programación orientada a aspectos (AOP del ingles Aspect Oriented Programming funciona parapermitir el aplicar asuntos de corte transversal a las clases después de que se han compilado. Estomantiene el código fuente libre de lógica, lo cual no es una parte central del propósito principal dela clase y optimiza el mantenimiento. El método depende de la implementación AOP. Usualmentesi una clase implementa una interfaz, cada llamada de método a una instancia de la clase primeropasa por un proxy. Este proxy implementa la misma interfaz, agregando el comportamiento requerido.Opcionalmente, si no se utiliza una interfaz entonces el código byte java de la clase compilada semodifica: los métodos originales se re-nombran y se reemplazan con métodos que implementan lalógica de corte transversal. Luego estos nuevos métodos llaman a los métodos originales despuésde haber ejecutado la lógica de corte transversal. Otro método para lograr el mismo resultado esmodificar el código byte para crear una subclase de la clase original que sobreescribe sus métodos.Los métodos sobreescritos luego ejecutan la lógica de corte transversal antes de llamar los métodoscorrespondiente de la super clase.

JBoss AOP es un marco de trabajo para AOP. Utilizándolo puede crear asuntos de corte transversalutilizando métodos y clases java convencionales. En terminologia de AOP cada asunto estárepresentado por un aspecto que usted implementa utilizando un POJO simple. El comportamientolo proporciona los métodos dentro del aspecto llamado consejos. Estos consejos siguen ciertasreglas para su parámetro y retornan tiposy cualquier excepción que presenten. Dentro de estemarco de trabajo puede utilizar nociones convencionales orientadas a objetos tal como la herencia,encapsulación y composición para hacer que sus asuntos de corte transversal sean fáciles demantener. Los aspectos se aplican al código utilizando un lenguaje de expresiones que le permiteespecificar los constructores, los métodos e incluso los campos de destino. Puede cambiarrápidamente el comportamiento de múltiples clases modificando el archivo de configuración.

Este capítulo contiene ejemplos, los cuales demuestran cómo utilizar JBoss AOP junto con elmicrocontenedor para crear y aplicar un aspecto de auditoría al servicio de recursos humanos. Elcódigo de auditoría se puede poner dentro de la clase HRManager, pero llenaría la clase con códigoque no es relevante para su propósito principal, expandiéndola y haciendo más dificil el mantenerla.El diseño del aspecto también proporciona modularidad, facilitando el auditar otras clases en el futuro,si el ámbito del proyecto cambia.

AOP también se puede utilizar para aplicar comportamiento adicional durante la fase deimplementación. Este ejemplo creará y enlazará un proxy a una instancia bean en un serviciobásico JNDI, permitiendo accederlo utilizando una búsqueda JNDI en lugar del controlador delmicrocontenedor.

5.1. Creación de un aspectoEl directorio examples/User_Guide/gettingStarted/auditAspect contiene todos losarchivos necesarios para crear el aspecto.

• pom.xml

• src/main/java/org/jboss/example/aspect/AuditAspect.java

Page 40: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 5. Agregar comportamiento con AOP

32

Ejemplo 5.1. POJO de ejemplo

public class AuditAspect {

private String logDir; private BufferedWriter out;

public AuditAspect() { logDir = System.getProperty("user.dir") + "/log";

File directory = new File(logDir); if (!directory.exists()) { directory.mkdir(); } }

public Object audit(ConstructorInvocation inv) throws Throwable { SimpleDateFormat formatter = new SimpleDateFormat("ddMMyyyy-kkmmss"); Calendar now = Calendar.getInstance(); String filename = "auditLog-" + formatter.format(now.getTime());

File auditLog = new File(logDir + "/" + filename); auditLog.createNewFile(); out = new BufferedWriter(new FileWriter(auditLog)); return inv.invokeNext(); }

public Object audit(MethodInvocation inv) throws Throwable { String name = inv.getMethod().getName(); Object[] args = inv.getArguments(); Object retVal = inv.invokeNext();

StringBuffer buffer = new StringBuffer(); for (int i=0; i < args.length; i++) { if (i > 0) { buffer.append(", "); } buffer.append(args[i].toString()); }

if (out != null) { out.write("Method: " + name); if (buffer.length() > 0) { out.write(" Args: " + buffer.toString()); } if (retVal != null) { out.write(" Return: " + retVal.toString()); } out.write("\n"); out.flush(); } return retVal; }}

Procedimiento 5.1. Creación del POJO1. El constructor chequea a ver si hay un directorio log en el directorio actual de trabajo y lo crea si

no lo encuentra.

Page 41: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Configuración del microcontenedor para AOP

33

2. Luego se define un aviso. Se llama a este aviso cuando se llama al constructor de la clasede destino. Esto crea un nuevo archivo de registro dentro del directorio log para registrarla llamadas de métodos realizadas en diferentes instancias de la clase destino en archivosseparados.

3. Finalmente se define otro aviso. Este aviso aplica a cada llamada de método realizada en laclase destino.El nombre del método y los argumentos se almacenan junto con el valor de retorno.Esta información se utiliza para construir un registro de auditoría y escribirlo en el archivo deregistro actual. Cada aviso llama a inv.invokeNext(), el cual encadena los avisos si se haaplicado más de un asunto de corte transversal o para llamar el constructor/método destino.

Nota

Cada aviso se implementa utilizando un método que toma un objeto de invocación comoparámetro, presenta Throwable y retorna Object. En el momento del diseño no se sabe a quéconstructores o métodos se aplicarán estos avisos así que haga los tipos tan genéricos comosea posible.

Para compilar la clase y crear un archivo auditAspect.jar que lo puedan utilizar otros ejemplos,escriba mvn install desde el directorio auditAspect.

5.2. Configuración del microcontenedor para AOPAntes de aplicar el aspecto de auditoría al servicio de recursos humanos, se debe agregar un númerode JARs a la ruta de clase de la extensión. Se encuentran en el sub-directorio lib de la distribuciónclient-aop que se encuentra en el directorio examples/User_Guide/gettingStarted/commandLineClient/target/client-aop.dir:

Ejemplo 5.2. Listado del directorio examples/User_Guide/gettingStarted/commandLineClient/target/client-aop.dir

|-- client-1.0.0.jar |-- jboss-beans.xml |-- lib |-- auditAspect-1.0.0.jar |-- concurrent-1.3.4.jar |-- humanResourcesService-1.0.0.jar |-- javassist-3.6.0.GA.jar |-- jboss-aop-2.0.0.beta1.jar |-- jboss-aop-mc-int-2.0.0.Beta6.jar |-- jboss-common-core-2.0.4.GA.jar |-- jboss-common-core-2.2.1.GA.jar |-- jboss-common-logging-log4j-2.0.4.GA.jar |-- jboss-common-logging-spi-2.0.4.GA.jar |-- jboss-container-2.0.0.Beta6.jar |-- jboss-dependency-2.0.0.Beta6.jar |-- jboss-kernel-2.0.0.Beta6.jar |-- jbossxb-2.0.0.CR4.jar |-- log4j-1.2.14.jar |-- trove-2.1.1.jar `-- xercesImpl-2.7.1.jar |-- log `-- auditLog-18062010-122537 `-- run.sh

Page 42: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 5. Agregar comportamiento con AOP

34

Primero, se necesita lib/auditAspect-1.0.0.jar para crear una instancia del aspecto entiempo de ejecución con el fin de ejecutar la lógica. Luego el archivo jar para JBoss AOP (jboss-aop.jar) junto con sus dependencias javassist y trove, agrega la funcionalidad AOP. Finalmente, senecesita la jar jboss-aop-mc-int ya que contiene una definición de esquema XML que le permite definiraspectos dentro de un descriptor de implementación XML. También contiene código de integraciónpara crear dependencias entre beans normales y beans de aspecto dentro del microcontenedor,permitiéndole agregar comportamiento durante las fases de implementación y de borrado de laimplementación.

Ya que está utilizando Maven2 para montar la distribución cliente-aop, debe agregar estos archivosJAR declarando las dependencias apropiadas en su archivo pom.xml y creando un descriptor deensamblaje válido. Puede ver un ejemplo de pom.xml en Ejemplo 5.3, “Extracto de ejemplo pom.xmlpara AOP”. Para realizar su construcción utilizando Ant, el procedimiento será diferente.

Ejemplo 5.3. Extracto de ejemplo pom.xml para AOP

<dependency> <groupId>org.jboss.microcontainer.examples</groupId> <artifactId>jboss-oap</artifactId> <version>2.0.0</version></dependency><dependency> <groupId>org.jboss.microcontainer.examples</groupId> <artifactId>javassist</artifactId> <version>3.6.0.GA</version></dependency><dependency> <groupId>org.jboss.microcontainer.examples</groupId> <artifactId>trove</artifactId> <version>2.1.1</version></dependency><dependency> <groupId>org.jboss.microcontainer.examples</groupId> <artifactId>jboss-aop-mc-int</artifactId> <version>2.0.0.Beta6</version></dependency>

5.3. Aplicación de un aspectoAhora que tiene una distribución válida que contiene todo lo que necesitad, puede configurar jboss-beans.xml para aplicar el aspecto de auditoría. Se encuentra en examples/User_Guide/gettingStarted/commandLineClient/target/client-aop.dir.

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0">

<bean name="AspectManager" class="org.jboss.aop.AspectManager"> <constructor factoryClass="org.jboss.aop.AspectManager" factoryMethod="instance"/> </bean>

<aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0" name="AuditAspect" class="org.jboss.example.aspect.AuditAspect" method="audit" pointcut="execution(public org.jboss.example.service.HRManager->new(..)) OR execution(public * org.jboss.example.service.HRManager->*(..))"> </aop:aspect>

Page 43: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Aplicación de un aspecto

35

...

</deployment>

Procedimiento 5.2. Explicación del código para aplicar un aspecto1. Antes de que pueda aplicar su aspecto a cualquier clase necesita crear una instancia de

org.jboss.aop.AspectManager usando un elemento <bean>. Aquí se utiliza un método defábrica en lugar de llamar un constructor convencional ya que solo es necesario una instancia delAspectManager en la MVJ en tiempo de ejecución.

2. Luego se crea una instancia de nuestro aspecto llamada AuditAspect, utilizando el elemento<aop:aspect>. Este se ve similar al elemento <bean> ya que tiene los atributos name y classque se utilizan de la misma manera. Sin embargo, también tiene los atributos method y pointcutque puede utilizar para aplicar o enlazar un consejo dentro del aspecto para los constructoresy métodos dentro de otras clases. Estos atributos enlazan el consejo de auditoría a todos losconstructores y métodos públicos dentro de la clase HRManager. Sólo es necesario especificarel método audit ya que ha sido sobrecargado dentro de la clase AuditAspect con diferentesparámetros. JBoss AOP sabe cuál seleccionar en tiempo de ejecución dependiendo de si se estárealizando una invocación de método o constructor.

Esta configuración adicional es todo lo que se necesita para aplicar el aspecto de auditoría entiempo de ejecución agregando un comportamiento de auditoría al servicio Human Resources.Puede probar esto ejecutando el cliente utilizando el script run.sh. Se crea un directorio log aliniciar junto con el directorio lib cuando el microcontenedor crea el bean AuditAspect. Cadaimplementación del servicio de recursos humanos hace que aparezca un nuevo archivo de registrosdentro del directorio log. El archivo de registro contiene un registro de las llamadas realizadas delcliente al servicio. Se llama algo como auditLog-28112007-163902 y contiene salidas similares aEjemplo 5.4, “Ejemplo de la salida del registro AOP”.

Ejemplo 5.4. Ejemplo de la salida del registro AOP

Method: getEmployees Return: [] Method: addEmployee Args: (Santa Claus, 1 Reindeer Avenue, Lapland City - 25/12/1860) Return: true Method: getSalary Args: (Santa Claus, null - Birth date unknown) Return: 10000 Method: getEmployees Return: [(Santa Claus, 1 Reindeer Avenue, Lapland City - 25/12/1860)] Method: isHiringFreeze Return: false Method: getEmployees Return: [(Santa Claus, 1 Reindeer Avenue, Lapland City - 25/12/1860)] Method: getSalaryStrategy

Para borrar el comportamiento de auditoría, comente los fragmentos relevantes de XML en eldescriptor de implementación y re-inicie la aplicación.

Page 44: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 5. Agregar comportamiento con AOP

36

Aviso

El orden de la implementación sí importa. Especificamente cada aspecto debe ser declaradoantes de los beans a los que aplica, así que el microcontenedor los implementa en ese orden.Esto se debe a que es posible que el microcontenedor tenga que alterar el código byte de laclase bean para agregar la lógica cross-cutting, antes de crear una instancia y almacena unareferencia a esta en el controlador. Si ya se ha creado una instancia normal del bean entoncesno es posible.

5.4. Callbacks del ciclo de vidaAdemás de aplicar aspectos a los beans que instanciamos utilizando el microcontenedor tambiénpodemos agregar comportamiento durante el proceso de implementación y de borrado de laimplementación. Tal como lo mencinamos en Sección 4.3, “Acceso directo”, un bean atravieza variosestados diferentes cuando se implementa. Estos incluyen:

NOT_INSTALLEDel descriptor de implementación que contiene el bean ha sido analizado sintácticamente junto concualquier anotación en el bean mismo.

DESCRIBEDcualquier dependencia que AOP ha creado ha sido agregada al bean y se han procesado lasanotaciones personalizadas.

INSTANTIATEDse ha creado una instancia del bean.

CONFIGUREDse han inyectado las propiedades en el bean junto con cualquier otra referencia a los otros beans.

CREATEse ha llamado al método create, si está definido en el bean.

STARTse ha llamado al método start, si está definido en el bean.

INSTALLEDcualquier acción de instalación personalizada que se definió en el descriptor de implementaciónse ha ejecutado y está listo para acceder al bean.

Importante

Los estados CREATE y START están incluídos por razones de legado. Esto le permite a losservicios que estaban implementados como MBeans en versiones anteriores de la plataformaempresarial el funcionar correctamente cuando se implementan como beans en la plataformaempresarial 5.1. Si no define ningún método crear/inicar correspondientes en su bean, pasaráderecho por estos estados.

Page 45: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Callbacks del ciclo de vida

37

Estos estados representan el ciclo de vida del bean. Puede definir un número de callbacks para quese apliquen en cualquier momento utilizando un grupo adicional de elementos <aop>.

<aop:lifecycle-describe>aplicado al entrar/salir del estado DESCRIBED

<aop:lifecycle-instantiate>aplicado al entrar/salir del estado INSTANTIATED

<aop:lifecycle-configure>aplicado al entrar/salir del estado CONFIGURED

<aop:lifecycle-create>aplicado al entrar/salir del estado CREATE

<aop:lifecycle-start>aplicado al entrar/salir del estado START

<aop:lifecycle-install>aplicado al entrar/salir del estado INSTALLED

Así como los elementos <bean> y <aop:aspect>, los elementos <aop:lifecycle-> contienen atributosname y class. El microcontenedor usa estos atributos para crear una instancia de la clase callback,nombrándola de manera que se pueda utilizar cuando los beans entren o salgan del estado relevantedurante la implementación y durante el borrado de la implementación. Puede especificar cuáles beansson afectados por el callback utilizando el atributo clases como se puede ver en Ejemplo 5.5, “Uso delatributo classes”.

Ejemplo 5.5. Uso del atributo classes

<aop:lifecycle-install xmlns:aop="urn:jboss:aop-beans:1.0"

name="InstallAdvice"

class="org.jboss.test.microcontainer.support.LifecycleCallback"

classes="@org.jboss.test.microcontainer.support.Install">

</aop:lifecycle-install>

Este código especifica que la lógica adicional en la clase lifecycleCallback se aplica a cualquierclase de bean que esté anotada con @org.jboss.test.microcontainer.support.Installantes de que entren y luego de que han dejado el estado INSTALLED.

Para que la clase callback funcione, debe contener los métodos install y uninstall que tomanControllerContext como parámetro, como se puede ver en Ejemplo 5.6, “Métodos de instalacióny desinstalación”.

Ejemplo 5.6. Métodos de instalación y desinstalación

import org.jboss.dependency.spi.ControllerContext;

public class LifecycleCallback {

public void install(ControllerContext ctx) {

Page 46: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 5. Agregar comportamiento con AOP

38

System.out.println("Bean " + ctx.getName() + " is being installed"; } public void uninstall(ControllerContext ctx) { System.out.println("Bean " + ctx.getName() + " is being uninstalled"; }}

El método install se llama durante la implementación del bean y se llama al método uninstalldurante el borrado de la implementación.

Nota

Aunque se está agregando comportamiento al proceso de implementación y de borrado dela implementación utilizando callbacks, AOP de ehcho no se utiliza aquí. La funcionalidadpointcut expression de JBoss AOP se utiliza para determinar a cuáles clases bean se aplican loscomportamientos.

5.5. Agregar búsquedas de servicios por medio de JNDIHasta ahora ha utilizado el microcontenedor para buscar referencias a instancias del bean querepresentan servicios. Esto no es ideal ya que requiere una referencia al kernel del microcontenedorantes de poder acceder al controlador. Esto se puede ver en Ejemplo 5.7, “Búsqueda de referencias alos Beans”.

Ejemplo 5.7. Búsqueda de referencias a los Beans

private HRManager manager;private EmbeddedBootstrap bootstrap;private Kernel kernel;private KernelController controller;private final static String HRSERVICE = "HRService";

...

// Start JBoss Microcontainerbootstrap = new EmbeddedBootstrap();bootstrap.run();

kernel = bootstrap.getKernel();controller = kernel.getController();

...

ControllerContext context = controller.getInstalledContext(HRSERVICE);if (context != null) { manager = (HRManager) context.getTarget(); }

El entregar referencias del kernel a todos los clientes que buscan un servicio es un riesgo deseguridad ya que proporciona un amplio acceso a la configuración del microcontenedor. Paramayor seguridad aplique el patrón ServiceLocator y utilice una clase para realizar búsquedasde parte de los clientes. Incluso puede pasar las referencias del bean junto con sus nombres alServiceLocator en el momento de la implementación utilizando un callback del ciclo de vida. En eseescenario, el ServiceLocator puede buscarlos sin llegar a saber del microcontenedor. El borrado de la

Page 47: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Agregar búsquedas de servicios por medio de JNDI

39

implementación posteriormente borraría las referencias del bean del ServiceLocator para evitar másbúsquedas.

No sería dificil es escribir su propia implementación ServiceLocator. En integrar una ya existentetal como JBoss Naming Service (JBoss NS) es incluso más rápido y tiene el beneficio adicional decumplir con la especificación de JNDI - Java Naming and Directory Interface. JNDI habilita a losclientes para acceder diferentes y posiblemente múltiples servicios de nombrado utilizando una APIcomún.

Procedimiento 5.3. Escritura de su propia implementación ServiceLocator1. Primero cree una instancia de JBoss NS usando el microcontenedor.

2. Luego, agregue un callback del ciclo de vida para realizar el enlace y des-enlace de lasreferencias bean durante la implementación y durante el borrado de la implementación.

3. Marque las clases bean a las que desea enlazar sus referencias, utilizando anotaciones.

4. Ahora puede ubicar los beans en tiempo de ejecución utilizando la expresión como se mostróanteriormente.

Page 48: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

40

Page 49: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Parte II. Conceptos avanzadoscon el microcontenedor

Esta sección aborda conceptos avanzados y muestra algunas funcionalidades interesantes delmicrocontenedor. Se asume que los ejemplos de código en el resto del manual son ejemplosincompletos y es responsabilidad del programador el extrapolarlos y extenderlos como sea necesario.

Page 50: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES
Page 51: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

43

Modelos de componentesEl JBoss Microcontainer funciona dentro de varios modelos de componentes POJO populares. Loscomponentes son programas de software re-utilizables que puede desarrollar y ensamblar fácilmentepara crear aplicaciones sofisticadas. Una de las metas clave del microcontenedor es la integraciónefectiva con estos modelos de componentes. Algunos modelos de componentes populares que sepueden utilizar con el microcontenedor son JMX, Spring y Guice.

6.1. Interacciones permitidas con los modelos decomponentesAntes de discutir la interacción como algunos de los modelos de componentes populares, esimportante el comprender qué tipos de interacciones se permiten. JMX MBeans son un ejemplo de unmodelo de componentes. Sus interacciones incluyen la ejecución de operaciones MBean, referenciaa atributos, el configurar atributos y la declaración explícita de dependencias entre las MBeansnombradas.

Las interacciones y comportamientos predeterminados en el microcontenedor son lo quenormalmente obtiene de cualquier otro contenedor Inversión de Control (IoC del inglés >Inversionof Control) y es similar a la funcionalidad que los MBeans proporcionan, incluyendo simplesinvocaciones de método para operaciones, setters/getters para los atributos y dependenciasexplícitas.

6.2. Un Bean sin dependenciasEjemplo 6.1, “Descriptor de implementación para un POJO simple” muestra un descriptor deimplementación para un POJO simple sin dependencias. Este es el punto inicial para integrar elmicrocontenedor con Spring o Guice.

Ejemplo 6.1. Descriptor de implementación para un POJO simple

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="PlainPojo" class="org.jboss.demos.models.plain.Pojo"/>

<beanfactory name="PojoFactory" class="org.jboss.demos.models.plain.Pojo"> <property name="factoryClass">org.jboss.demos.models.plain.PojoFactory</property> </beanfactory>

</deployment>

6.3. Uso del microcontenedor con Spring

Ejemplo 6.2. Descriptor con soporte para Spring

<beans xmlns="urn:jboss:spring-beans:2.0">

<!-- Adding @Spring annotation handler --> <bean id="SpringAnnotationPlugin" class="org.jboss.spring.annotations.SpringBeanAnnotationPlugin" />

<bean id="SpringPojo" class="org.jboss.demos.models.spring.Pojo"/>

</beans>

Page 52: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 6. Modelos de componentes

44

El espacio de nombre del archivo es diferente del archivo del bean del microcontenedor. El espaciode nombre urn:jboss:spring-beans:2.0 apunta a su versión del puerto del esquema Spring,el cual describe el estilo Spring de su bean. El microcontenedor implementa los beans a maneraopuesta de la noción de fábrica de beans de Spring.

Ejemplo 6.3. Uso de Spring con el microcontenedor

public class Pojo extends AbstractPojo implements BeanNameAware { private String beanName;

public void setBeanName(String name) { beanName = name; }

public String getBeanName() { return beanName; }

public void start() { if ("SpringPojo".equals(getBeanName()) == false) throw new IllegalArgumentException("Name doesn't match: " + getBeanName()); }}

Aunque el bean SpringPojo tiene una dependencia en la biblioteca de Spring causada por laimplementación de la interfaz BeanNameAware, su único propósito es exponer e imitar algo delcomportamiento del callback de Spring.

6.4. Uso de Guice con el microcontenedorEl enfoque de Guice es el acomplamiento de tipos. Los beans Guice se generan y se configuranusando módulos.

Ejemplo 6.4. Descriptor de implementación para la integración Guice en el microcontenedor

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="GuicePlugin" class="org.jboss.guice.spi.GuiceKernelRegistryEntryPlugin"> <constructor> <parameter> <array elementClass="com.google.inject.Module"> <bean class="org.jboss.demos.models.guice.PojoModule"/> </array> </parameter> </constructor> </bean>

</deployment>

Page 53: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Uso de Guice con el microcontenedor

45

Dos partes importantes de observar en este archivo son PojoModule yGuiceKernelRegistryEntryPlugin. PojoModule configura sus beans tal como en Ejemplo 6.5,“Configuración de Beans para Guice”. GuiceKernelRegistryEntryPlugin proporcionaintegración con el microcontenedor tal como se puede ver en Ejemplo 6.6, “Integración mock con elmicrocontenedor”.

Ejemplo 6.5. Configuración de Beans para Guice

public class PojoModule extends AbstractModule { private Controller controller;

@Constructor public PojoModule(@Inject( bean = KernelConstants.KERNEL_CONTROLLER_NAME) Controller controller) { this.controller = controller; }

protected void configure() { bind(Controller.class).toInstance(controller); bind(IPojo.class).to(Pojo.class).in(Scopes.SINGLETON); bind(IPojo.class).annotatedWith(FromMC.class). toProvider(GuiceIntegration.fromMicrocontainer(IPojo.class, "PlainPojo")); }}

Ejemplo 6.6. Integración mock con el microcontenedor

public class GuiceKernelRegistryEntryPlugin implements KernelRegistryPlugin { private Injector injector;

public GuiceKernelRegistryEntryPlugin(Module... modules) { injector = Guice.createInjector(modules); }

public void destroy() { injector = null; }

public KernelRegistryEntry getEntry(Object name) { KernelRegistryEntry entry = null; try { if (name instanceof Class<?>) { Class<?> clazz = (Class<?>)name; entry = new AbstractKernelRegistryEntry(name, injector.getInstance(clazz)); } else if (name instanceof Key) { Key<?> key = (Key<?>)name; entry = new AbstractKernelRegistryEntry(name, injector.getInstance(key)); } } catch (Exception ignored) {

Page 54: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 6. Modelos de componentes

46

} return entry; } }

Nota

Se crea un Injector desde la clase Modules luego realiza una búsqueda en este para versi hay beans que coincidan. Consulte Sección 6.5, “MBeans de legado y mezcla de diferentesmodelos de componentes” para encontrar mayor información sobre la declaración y uso deMBeans de legado.

6.5. MBeans de legado y mezcla de diferentes modelos decomponentesEl ejemplo más simple de mezclar diferentes modelos de contenido se puede ver en Ejemplo 6.7,“Inyección de un POJO en un MBean”.

Ejemplo 6.7. Inyección de un POJO en un MBean

<server>

<mbean code="org.jboss.demos.models.mbeans.Pojo" name="jboss.demos:service=pojo"> <attribute name="OtherPojo"><inject bean="PlainPojo"/></attribute> </mbean>

</server>

Para implementar MBeans por medio del microcontenedor debe escribir un manejador nuevo porcompleto para el modelo de componentes. Consulte system-jmx-beans.xml para obtenermayores detalles. El código de este archivo se encuentra en el código fuente del servidor deaplicaciones JBoss: sub-proyecto system-jmx.

6.6. Exponer POJOs como MBeans

Ejemplo 6.8. Exponer un POJO existenete como un MBean

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="AnnotatedJMXPojo" class="org.jboss.demos.models.jmx.AtJmxPojo"/>

<bean name="XmlJMXPojo" class="org.jboss.demos.models.mbeans.Pojo"> <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(exposedInterface=org.jboss.demos.models.mbeans.PojoMBean.class, registerDirectly=true)</annotation> </bean>

<bean name="ExposedPojo" class="org.jboss.demos.models.jmx.Pojo"/>

<bean name="AnnotatedExposePojo" class="org.jboss.demos.models.jmx.ExposePojo">

Page 55: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Exponer POJOs como MBeans

47

<constructor> <parameter><inject bean="ExposedPojo"/></parameter> </constructor> </bean>

</deployment>

Este descriptor presenta un POJO existente como un MBean y lo registra en un servidor MBean.

Para exponer un POJO como un MBean finalícelo con una anotación @JMX asumiendo que haimportado org.jboss.aop.microcontainer.aspects.jmx.JMX. El bean se puede exponerdirectamente o en su propiedad.

Ejemplo 6.9. Presentación de un POJO como un MBean usando su propiedad

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="XMLLoginConfig" class="org.jboss.demos.models.old.XMLLoginConfig"/>

<bean name="SecurityConfig" class="org.jboss.demos.models.old.SecurityConfig"> <property name="defaultLoginConfig"><inject bean="XMLLoginConfig"/></property> </bean>

<bean name="SecurityChecker" class="org.jboss.demos.models.old.Checker"> <property name="loginConfig"><inject bean="jboss.security:service=XMLLoginConfig"/></property> <property name="securityConfig"><inject bean="jboss.security:service=SecurityConfig"/></property> </bean>

</deployment>

Puede utilizar cualquiera de los tipos de búsqueda de inyección ya sea buscando un POJO simple uobteniendo un MBean del servidor MBean. Una de las opciones de inyección es utilizar la inyecciónde tipos, algunas veces llamada autowiring y se puede ver en Ejemplo 6.10, “Autowiring”.

Ejemplo 6.10. Autowiring

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="FromGuice" class="org.jboss.demos.models.plain.FromGuice"> <constructor><parameter><inject bean="PlainPojo"/></parameter></constructor> <property name="guicePojo"><inject/></property> </bean>

<bean name="AllPojos" class="org.jboss.demos.models.plain.AllPojos"> <property name="directMBean"><inject bean="jboss.demos:service=pojo"/></property> <property name="exposedMBean"><inject bean="jboss.demos:service=ExposedPojo"/></property> <property name="exposedMBean"><inject bean="jboss.demos:service=ExposedPojo"/></property> </bean>

</deployment>

Page 56: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 6. Modelos de componentes

48

El bean FromGuice inyecta el bean Guice por medio de la correspondencia de tipos, en dondePlainPojo se inyecta con una inyección de nombres común. Ahora puede probar a ver si el enlaceGuice funciona como se esperaba como se puede ver en Ejemplo 6.11, “Prueba de la funcionalidadde Guice”.

Ejemplo 6.11. Prueba de la funcionalidad de Guice

public class FromGuice { private IPojo plainPojo; private org.jboss.demos.models.guice.Pojo guicePojo;

public FromGuice(IPojo plainPojo) { this.plainPojo = plainPojo; }

public void setGuicePojo(org.jboss.demos.models.guice.Pojo guicePojo) { this.guicePojo = guicePojo; }

public void start() { f (plainPojo != guicePojo.getMcPojo()) throw new IllegalArgumentException("Pojos are not the same: " + plainPojo + "!=" + guicePojo.getMcPojo()); }}

Ejemplo 6.11, “Prueba de la funcionalidad de Guice” solo proporciona un modelo de componentesalias. El alias es una funcionalidad trivial pero necesaria. Se debe introducir como un modelo nuevode componentes dentro del microcontenedor con el fin de implementarlo como una dependenciaverdadera. Los detalles de la implementación se pueden ver en Ejemplo 6.12, “Código fuente deAbstractController”.

Ejemplo 6.12. Código fuente de AbstractController

<deployment xmlns="urn:jboss:bean-deployer:2.0"> <alias name="SpringPojo">springPojo</alias></deployment>

Este descriptor mapea el nombre del SpringPojo al alias del springPojo. El beneficio de los aliasescomo verdaeros modelos de componentes es que el momento de la implementación del bean sevuelve menos importante. El alias espera en un estado no-instalado hasta que el bean real lo dispara.

Page 57: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

49

Inyección avanzada de dependencias yldCHoy en día la Inyección de Dependencias (ID), también llamada Inversión de Control (IdC), seencuentra en la parte central de muchos marcos de trabajo que adoptan la noción de un contenedoro un modelo de componentes. En un capítulo anterior abordamos los modelos de componentes. Elkernel JBoss JMX, el precursor al microcontenedor, solo proporcionaba soporte ligero para ID/IdC ,principalmente debido a las limitaciones del acceder los MBeans por medio del servidor MBeans. Sinembargo, con el nuevo modelo de componentes basados en POJO se encuentran disponibles variasnuevas e interesantes funcionalidades.

Este capítulo muestra la manera en que puede aplicar diferentes conceptos ID con la ayuda delmicrocotenedor JBoss. Estos conceptos se expresarán por medio del código XML pero tambiénpuede aplicar la mayoría de estas funcionalidades utilizando las anotaciones.

7.1. Fábrica de valoresUna fábrica de valores es un bean, el cual tiene uno o más métodos dedicados a generar valores porusted. Consulte Ejemplo 7.1, “Fábrica de valores”.

Ejemplo 7.1. Fábrica de valores

<bean name="Binding" class="org.jboss.demos.ioc.vf.PortBindingManager"> <constructor> <parameter> <map keyClass="java.lang.String" valueClass="java.lang.Integer"> <entry> <key>http</key> <value>80</value> </entry> <entry> <key>ssh</key> <value>22</value> </entry> </map> </parameter> </constructor></bean><bean name="PortsConfig" class="org.jboss.demos.ioc.vf.PortsConfig"> <property name="http"><value-factory bean="Binding" method="getPort" parameter="http"/></property> <property name="ssh"><value-factory bean="Binding" method="getPort" parameter="ssh"/></property> <property name="ftp"> <value-factory bean="Binding" method="getPort"> <parameter>ftp</parameter> <parameter>21</parameter> </value-factory> </property> <property name="mail"> <value-factory bean="Binding" method="getPort"> <parameter>mail</parameter> <parameter>25</parameter> </value-factory> </property></bean>

Page 58: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 7. Inyección avanzada de dependencias y ldC

50

Ejemplo 7.2, “PortsConfig” muestra la manera en que el bean PortsConfig usa el bean de enlace paraobtener sus valores por medio de la invocación del método getPort.

Ejemplo 7.2. PortsConfig

public class PortBindingManager { private Map<String, Integer> bindings; public PortBindingManager(Map<String, Integer> bindings) { this.bindings = bindings; } public Integer getPort(String key) { return getPort(key, null); } public Integer getPort(String key, Integer defaultValue) { if (bindings == null) return defaultValue; Integer value = bindings.get(key); if (value != null) return value; if (defaultValue != null) bindings.put(key, defaultValue); return defaultValue; }}

7.2. CallbacksEl descriptor que se puede ver en Ejemplo 7.3, “Callbacks para reunir y filtrar beans” le permite reunirtodos los beans de un cierto tipo e incluso limitar el número de beans que coincidan.

Junto con el descriptor en Ejemplo 7.3, “Callbacks para reunir y filtrar beans”, el código Java quese puede ver en Ejemplo 7.4, “Un analizador sintáctico para reunir todos los editores” muestra unParser, el cual reune todos los Editores.

Ejemplo 7.3. Callbacks para reunir y filtrar beans

<bean name="checker" class="org.jboss.demos.ioc.callback.Checker"> <constructor> <parameter> <value-factory bean="parser" method="parse"> <parameter> <array elementClass="java.lang.Object"> <value>http://www.jboss.org</value> <value>SI</value> <value>3.14</value> <value>42</value> </array> </parameter> </value-factory> </parameter> </constructor></bean><bean name="editorA" class="org.jboss.demos.ioc.callback.DoubleEditor"/><bean name="editorB" class="org.jboss.demos.ioc.callback.LocaleEditor"/><bean name="parser" class="org.jboss.demos.ioc.callback.Parser"> <incallback method="addEditor" cardinality="4..n"/> <uncallback method="removeEditor"/>

Page 59: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Modo de acceso del Bean

51

</bean><bean name="editorC" class="org.jboss.demos.ioc.callback.LongEditor"/><bean name="editorD" class="org.jboss.demos.ioc.callback.URLEditor"/>

Ejemplo 7.4. Un analizador sintáctico para reunir todos los editores

public class Parser { private Set<Editor> editors = new HashSet<Editor>(); ... public void addEditor(Editor editor) { editors.add(editor); } public void removeEditor(Editor editor) { editors.remove(editor); }}

Observe que incallback y uncallback usan el nombre del método para buscar.

<incallback method="addEditor" cardinality="4..n"/><uncallback method="removeEditor"/>

Un límite inferior controla cuántos editores de hecho hacen que el bean progrese de un estadoconfigurado: cardinality=4..n/>

Eventualmente se crea Checker y corrige el analizador sintáctico. Esto se ilustra en Ejemplo 7.5, “Elcorrector para el analizador sintáctico”.

Ejemplo 7.5. El corrector para el analizador sintáctico

public void create() throws Throwable { Set<String> strings = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); for (Object element : elements) strings.add(element.toString()); if (expected.equals(strings) == false) throw new IllegalArgumentException("Illegal expected set: " + expected + "!=" + strings);}

7.3. Modo de acceso del BeanCon el BeanAccessMode predeterminado no se inspeccionan los campos de un bean. Sin embargo,si especifica un BeanAccessMode diferente entonces los campos son accesibles como parte delas propiedades del bean. Consulte Ejemplo 7.6, “Definiciones posibles para BeanAccessMode”,Ejemplo 7.7, “Configuración de BeanAccessMode” y Ejemplo 7.8, “La clase FieldsBean” para unaimplementación.

Page 60: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 7. Inyección avanzada de dependencias y ldC

52

Ejemplo 7.6. Definiciones posibles para BeanAccessMode

public enum BeanAccessMode { STANDARD(BeanInfoCreator.STANDARD), // Getters and Setters FIELDS(BeanInfoCreator.FIELDS), // Getters/Setters and fields without getters and setters ALL(BeanInfoCreator.ALL); // As above but with non public fields included}

Aquí un valor de cadena se configura como un campo de cadena privado:

Ejemplo 7.7. Configuración de BeanAccessMode

<bean name="FieldsBean" class="org.jboss.demos.ioc.access.FieldsBean" access-mode="ALL"> <property name="string">InternalString</property></bean>

Ejemplo 7.8. La clase FieldsBean

public class FieldsBean { private String string; public void start() { if (string == null) throw new IllegalArgumentException("Strings should be set!"); }}

7.4. Alias BeanCada bean puede tener cualquier número de alias. Ya que los nombres de los componentes delmicrocontenedor se tratan como objetos, el tipo del alias no es limitado. Por defecto no se realizaun reemplazo de la propiedad del sistema; es necesario que establezca la etiqueta de reemplazo demanera explícita como se puede ver en Ejemplo 7.9, “Un alias simple de Bean”.

Ejemplo 7.9. Un alias simple de Bean

<bean name="SimpleName" class="java.lang.Object"> <alias>SimpleAlias</alias> <alias replace="true">${some.system.property}</alias> <alias class="java.lang.Integer">12345</alias> <alias><javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.demos.bootstrap.Main"/></alias></bean>

Page 61: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Soporte para anotaciones XML (o metadatos)

53

7.5. Soporte para anotaciones XML (o metadatos)Una de las funcionalidades principales en el microcontenedor de JBoss es el soporte para AOP.Puede utilizar aspectos AOP y beans simples combinadas de cualquier manera. Ejemplo 7.10,“Interceptar un método basado en una anotación” trata de interceptar una invocación de método conbase en una anotación. La anotación puede provenir de cualquier lado. Puede ser una anotación declase verdadera o puede ser una anotación agregada por medio de la configuración xml.

Ejemplo 7.10. Interceptar un método basado en una anotación

<interceptor xmlns="urn:jboss:aop-beans:1.0" name="StopWatchInterceptor" class="org.jboss.demos.ioc.annotations.StopWatchInterceptor"/>

<bind xmlns="urn:jboss:aop-beans:1.0" pointcut="execution(* @org.jboss.demos.ioc.annotations.StopWatchLog->*(..)) OR execution(* *->@org.jboss.demos.ioc.annotations.StopWatchLog(..))"> <interceptor-ref name="StopWatchInterceptor"/></bind></interceptor>

public class StopWatchInterceptor implements Interceptor { ... public Object invoke(Invocation invocation) throws Throwable { Object target = invocation.getTargetObject(); long time = System.currentTimeMillis(); log.info("Invocation [" + target + "] start: " + time); try { return invocation.invokeNext(); } finally { log.info("Invocation [" + target + "] time: " + (System.currentTimeMillis() - time)); } }}

Ejemplo 7.11, “Un verdadero ejecutor anotado de clase” and Ejemplo 7.12, “Ejecutor simple conanotaciones XML” muestra algunas maneras diferentes de implementar los ejecutores.

Ejemplo 7.11. Un verdadero ejecutor anotado de clase

<bean name="AnnotatedExecutor" class="org.jboss.demos.ioc.annotations.AnnotatedExecutor">

public class AnnotatedExecutor implements Executor { ... @StopWatchLog // <-- Pointcut match! public void execute() throws Exception { delegate.execute(); }}

Page 62: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 7. Inyección avanzada de dependencias y ldC

54

Ejemplo 7.12. Ejecutor simple con anotaciones XML

<bean name="SimpleExecutor" class="org.jboss.demos.ioc.annotations.SimpleExecutor"> <annotation>@org.jboss.demos.ioc.annotations.StopWatchLog</annotation> // <-- Pointcut match!</bean>

public class SimpleExecutor implements Executor { private static Random random = new Random(); public void execute() throws Exception { Thread.sleep(Math.abs(random.nextLong() % 101)); }}

Después de agregar los beans invocadores del ejecutor, puede ver los ejecutores en acción duranteel empleo, buscando salidas del registro tal como Ejemplo 7.13, “Salida del registro del ejecutor”.

Ejemplo 7.13. Salida del registro del ejecutor

JBoss-MC-Demo INFO [15-12-2008 13:57:39] StopWatch - Invocation [org.jboss.demos.ioc.annotations.AnnotatedExecutor@4d28c7] start: 1229345859234 JBoss-MC-Demo INFO [15-12-2008 13:57:39] StopWatch - Invocation [org.jboss.demos.ioc.annotations.AnnotatedExecutor@4d28c7] time: 31 JBoss-MC-Demo INFO [15-12-2008 13:57:39] StopWatch - Invocation [org.jboss.demos.ioc.annotations.SimpleExecutor@1b044df] start: 1229345859265 JBoss-MC-Demo INFO [15-12-2008 13:57:39] StopWatch - Invocation [org.jboss.demos.ioc.annotations.SimpleExecutor@1b044df] time: 47

7.6. AutowireAutowiring o la inyección contextual, es una funcionalidad común con con marcos de trabajo IdC.Ejemplo 7.14, “Incluir y excluir con autowiring” le muestra cómo utilizar o excluir beans con autowiring.

Ejemplo 7.14. Incluir y excluir con autowiring

<bean name="Square" class="org.jboss.demos.ioc.autowire.Square" autowire-candidate="false"/><bean name="Circle" class="org.jboss.demos.ioc.autowire.Circle"/><bean name="ShapeUser" class="org.jboss.demos.ioc.autowire.ShapeUser"> <constructor> <parameter><inject/></parameter> </constructor></bean><bean name="ShapeHolder" class="org.jboss.demos.ioc.autowire.ShapeHolder"> <incallback method="addShape"/> <uncallback method="removeShape"/></bean><bean name="ShapeChecker" class="org.jboss.demos.ioc.autowire.ShapesChecker"/>

Page 63: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Fábrica de beans

55

En ambos casos - ShapeUser y ShapeChecker - solo Circle se debe utilizar ya que Square se excluyeen el enlace contextual.

7.7. Fábrica de beansCuando quiere más de una instancia de un bean en particular, necesita utilizar el patrón de fábricadel bean. El trabajo del microcontenedor es configurar e instalar la fábrica de beans como si fuera unbean simple. Luego necesita invocar el método createBean de la fábrica de beans.

Por defecto, el microcontenedor crea una instancia GenericBeanFactory, pero puede configurarsu propia fábrica. La única limitación es que su firma y ganchos de configuración son similares al deAbstractBeanFactory.

Ejemplo 7.15. Fábrica de beans genéricas

<bean name="Object" class="java.lang.Object"/><beanfactory name="DefaultPrototype" class="org.jboss.demos.ioc.factory.Prototype"> <property name="value"><inject bean="Object"/></property></beanfactory><beanfactory name="EnhancedPrototype" class="org.jboss.demos.ioc.factory.Prototype" factoryClass="org.jboss.demos.ioc.factory.EnhancedBeanFactory"> <property name="value"><inject bean="Object"/></property></beanfactory><beanfactory name="ProxiedPrototype" class="org.jboss.demos.ioc.factory.UnmodifiablePrototype" factoryClass="org.jboss.demos.ioc.factory.EnhancedBeanFactory"> <property name="value"><inject bean="Object"/></property></beanfactory><bean name="PrototypeCreator" class="org.jboss.demos.ioc.factory.PrototypeCreator"> <property name="default"><inject bean="DefaultPrototype"/></property> <property name="enhanced"><inject bean="EnhancedPrototype"/></property> <property name="proxied"><inject bean="ProxiedPrototype"/></property></bean>

Consulte Ejemplo 7.16, “BeanFactory extendido” para ver el uso de un BeanFactory extendido.

Ejemplo 7.16. BeanFactory extendido

public class EnhancedBeanFactory extends GenericBeanFactory { public EnhancedBeanFactory(KernelConfigurator configurator) { super(configurator); } public Object createBean() throws Throwable { Object bean = super.createBean(); Class clazz = bean.getClass(); if (clazz.isAnnotationPresent(SetterProxy.class)) { Set<Class> interfaces = new HashSet<Class>(); addInterfaces(clazz, interfaces); return Proxy.newProxyInstance( clazz.getClassLoader(), interfaces.toArray(new Class[interfaces.size()]), new SetterInterceptor(bean) ); } else

Page 64: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 7. Inyección avanzada de dependencias y ldC

56

{ return bean; } } protected static void addInterfaces(Class clazz, Set<Class> interfaces) { if (clazz == null) return; interfaces.addAll(Arrays.asList(clazz.getInterfaces())); addInterfaces(clazz.getSuperclass(), interfaces); } private class SetterInterceptor implements InvocationHandler { private Object target; private SetterInterceptor(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if (methodName.startsWith("set")) throw new IllegalArgumentException("Cannot invoke setters."); return method.invoke(target, args); } }}

public class PrototypeCreator { ... public void create() throws Throwable { ValueInvoker vi1 = (ValueInvoker)bfDefault.createBean(); vi1.setValue("default"); ValueInvoker vi2 = (ValueInvoker)enhanced.createBean(); vi2.setValue("enhanced"); ValueInvoker vi3 = (ValueInvoker)proxied.createBean(); try { vi3.setValue("default"); throw new Error("Should not be here."); } catch (Exception ignored) { } }

7.8. Constructor de metadatos BeanAl utilizar el microcontenedor en su código, use BeanMetaDataBuilder para crear y configurar losmetadatos de su bean.

Ejemplo 7.17. BeanMetaDataBuilder

<bean name="BuilderUtil" class="org.jboss.demos.ioc.builder.BuilderUtil"/><bean name="BuilderExampleHolder" class="org.jboss.demos.ioc.builder.BuilderExampleHolder"> <constructor> <parameter><inject bean="BUExample"/></parameter> </constructor></bean>

Page 65: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

ClassLoader personalizado

57

Utilizando este concepto no expone su código a ninguno de los detalles de implementación delmicrocontenedor.

public class BuilderUtil { private KernelController controller; @Constructor public BuilderUtil(@Inject(bean = KernelConstants.KERNEL_CONTROLLER_NAME) KernelController controller) { this.controller = controller; } public void create() throws Throwable { BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder("BUExample", BuilderExample.class.getName()); builder.addStartParameter(Kernel.class.getName(), builder.createInject(KernelConstants.KERNEL_NAME)); controller.install(builder.getBeanMetaData()); } public void destroy() { controller.uninstall("BUExample"); }}

7.9. ClassLoader personalizadoEn el microcontenedor puede definir un ClassLoader personalizado por bean. Al definir un cargadorde clase para toda la implementación, asegúrese de no crear una dependencia cíclica -- por ejemplo,un cargador de clase recién definido que dependa de sí mismo.

Ejemplo 7.18. Definición de un cargador de clase por Bean

<classloader><inject bean="custom-classloader:0.0.0"/></classloader><!-- this will be explained in future article --><classloader name="custom-classloader" xmlns="urn:jboss:classloader:1.0" export-all="NON_EMPTY" import-all="true"/><bean name="CustomCL" class="org.jboss.demos.ioc.classloader.CustomClassLoader"> <constructor> <parameter><inject bean="custom-classloader:0.0.0"/></parameter> </constructor> <property name="pattern">org\.jboss\.demos\.ioc\..+</property></bean><bean name="CB1" class="org.jboss.demos.ioc.classloader.CustomBean"/><bean name="CB2" class="org.jboss.demos.ioc.classloader.CustomBean"> <classloader><inject bean="CustomCL"/></classloader></bean>

Ejemplo 7.19, “Prueba del cargador de clase personalizado” muestra una prueba para verificar que elbean CB2 usa un cargador de clase personalizado, el cual limita el ámbito del paquete cargable.

Ejemplo 7.19. Prueba del cargador de clase personalizado

public class CustomClassLoader extends ClassLoader { private Pattern pattern; public CustomClassLoader(ClassLoader parent) { super(parent); } public Class<?> loadClass(String name) throws ClassNotFoundException {

Page 66: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 7. Inyección avanzada de dependencias y ldC

58

if (pattern == null || pattern.matcher(name).matches()) return super.loadClass(name); else throw new ClassNotFoundException("Name '" + name + "' doesn't match pattern: " + pattern); } public void setPattern(String regexp) { pattern = Pattern.compile(regexp); }}

7.10. Modo controladorPor defecto el microcontenedor usa el modo controlador AUTO. Lleva a los beans tan lejos como esposible con respecto a las dependencias. Pero hay otros dos modos: MANUAL y ON_DEMAND.

Si el bean está marcado como ON_DEMAND entonces no se utilizará ni se instalará hasta que otrobean dependa explícitamente de este. En el modo MANUAL, el usuario microcontenedor debe llevaral bean hacia adelante y atrás junto con el estado.

Ejemplo 7.20. Modo controlador Bean

<bean name="OptionalService" class="org.jboss.demos.ioc.mode.OptionalService" mode="On Demand"/><bean name="OptionalServiceUser" class="org.jboss.demos.ioc.mode.OptionalServiceUser"/><bean name="ManualService" class="org.jboss.demos.ioc.mode.ManualService" mode="Manual"/><bean name="ManualServiceUser" class="org.jboss.demos.ioc.mode.ManualServiceUser"> <start> <parameter><inject bean="ManualService" fromContext="context" state="Not Installed"/></parameter> </start></bean>

Nota

Usando el atributo fromContext de la clase inject puede inyectar beans así como surepresentación de componentes del microcontenedor inmodificables.

Revise el código de OptionalServiceUser y ManualServiceUser para ver cómo se utiliza laAPI del microcontenedor para el manejo de beans ON_DEMAND y MANUAL.

7.11. CicloLos beans pueden depender entre ellos en un ciclo. Por ejemplo, A depende de B en la construcción,pero B depende de A durante la configuración. Debido a la separación del ciclo de vida del estadodetallado del microcontenedor, este problema se puede resolver fácilmente.

Page 67: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Oferta y demanda

59

Ejemplo 7.21. Separación del ciclo de vida del Bean

<bean name="cycleA" class="org.jboss.demos.ioc.cycle.CyclePojo"> <property name="dependency"><inject bean="cycleB"/></property></bean><bean name="cycleB" class="org.jboss.demos.ioc.cycle.CyclePojo"> <constructor><parameter><inject bean="cycleA" state="Instantiated"/></parameter></constructor></bean><bean name="cycleC" class="org.jboss.demos.ioc.cycle.CyclePojo"> <property name="dependency"><inject bean="cycleD"/></property></bean><bean name="cycleD" class="org.jboss.demos.ioc.cycle.CyclePojo"> <property name="dependency"><inject bean="cycleC" state="Instantiated"/></property></bean>

7.12. Oferta y demandaAlgunas veces así como con una inyección, es posible que una dependencia entre dos beans nosea aparente. Tales dependencias se deben expresar de manera clara tal como se puede ver enEjemplo 7.22, “Uso estático del código”.

Ejemplo 7.22. Uso estático del código

<bean name="TMDemand" class="org.jboss.demos.ioc.demandsupply.TMDemander"> <demand>TM</demand></bean><bean name="SimpleTMSupply" class="org.jboss.demos.ioc.demandsupply.SimpleTMSupplyer"> <supply>TM</supply></bean>

7.13. InstalacionesA medida que el bean se mueve a través de diferentes estados es posible que quiera invocar algunosmétodos en otros beans o en el mismo bean. Ejemplo 7.23, “Invocación de métodos en diferentesestados” muestra cómo Entry invoca a los métodos add y removeEntry del RepositoryManagerpararegistrar y desregistrarse a sí mismo.

Ejemplo 7.23. Invocación de métodos en diferentes estados

<bean name="RepositoryManager" class="org.jboss.demos.ioc.install.RepositoryManager"> <install method="addEntry"> <parameter><inject fromContext="name"/></parameter> <parameter><this/></parameter> </install> <uninstall method="removeEntry"> <parameter><inject fromContext="name"/></parameter> </uninstall></bean><bean name="Entry" class="org.jboss.demos.ioc.install.SimpleEntry"> <install bean="RepositoryManager" method="addEntry" state="Instantiated"> <parameter><inject fromContext="name"/></parameter> <parameter><this/></parameter> </install>

Page 68: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 7. Inyección avanzada de dependencias y ldC

60

<uninstall bean="RepositoryManager" method="removeEntry" state="Configured"> <parameter><inject fromContext="name"/></parameter> </uninstall></bean>

7.14. Imitación perezosaEs posible que tenga una dependencia en un bean que se utilice con muy poca frecuencia, perotoma mucho tiempo en configurar. Puede utilizar la imitación perezosa del bean que se demuestra enEjemplo 7.24, “Imitación perezosa” para resolver la dependencia. Cuando de hecho necesita el bean,invoque y use el bean destino esperando que para ese momento ya se haya instalalado.

Ejemplo 7.24. Imitación perezosa

<bean name="lazyA" class="org.jboss.demos.ioc.lazy.LazyImpl"> <constructor> <parameter> <lazy bean="lazyB"> <interface>org.jboss.demos.ioc.lazy.ILazyPojo</interface> </lazy> </parameter> </constructor></bean><bean name="lazyB" class="org.jboss.demos.ioc.lazy.LazyImpl"> <constructor> <parameter> <lazy bean="lazyA"> <interface>org.jboss.demos.ioc.lazy.ILazyPojo</interface> </lazy> </parameter> </constructor></bean><lazy name="anotherLazy" bean="Pojo" exposeClass="true"/><bean name="Pojo" class="org.jboss.demos.ioc.lazy.Pojo"/>

7.15. Ciclo de vidaPor defecto el microcontenedor usa los métodos create, start y destroy cuando avanza a travésde los variados estados. Sin embargo, es posible que no quiera que el microcontenedor los invoque.Por esta razón, se encuentra disponible una etiqueta ignore.

Ejemplo 7.25. Ciclos de vida del Bean

<bean name="FullLifecycleBean-3" class="org.jboss.demos.ioc.lifecycle.FullLifecycleBean"/><bean name="FullLifecycleBean-2" class="org.jboss.demos.ioc.lifecycle.FullLifecycleBean"> <create ignored="true"/></bean><bean name="FullLifecycleBean-1" class="org.jboss.demos.ioc.lifecycle.FullLifecycleBean"> <start ignored="true"/></bean>

Page 69: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

61

El sistema virtual de archivosEl duplicado del código de manejo de recursos es un problema común para los desarrolladores. Enla mayoría de los casos, el código ayuda a determinar la información sobre un recurso en particular,el cual puede ser un archivo, un directorio o en el caso de una JAR, una URL remota. Otro problemade duplicación es el código para el procesamiento de ficheros anidados. Ejemplo 8.1, “Problema deduplicación de recursos” ilustra el problema.

Ejemplo 8.1. Problema de duplicación de recursos

public static URL[] search(ClassLoader cl, String prefix, String suffix) throws IOException { Enumeration[] e = new Enumeration[]{ cl.getResources(prefix), cl.getResources(prefix + "MANIFEST.MF") }; Set all = new LinkedHashSet(); URL url; URLConnection conn; JarFile jarFile; for (int i = 0, s = e.length; i < s; ++i) { while (e[i].hasMoreElements()) { url = (URL)e[i].nextElement(); conn = url.openConnection(); conn.setUseCaches(false); conn.setDefaultUseCaches(false); if (conn instanceof JarURLConnection) { jarFile = ((JarURLConnection)conn).getJarFile(); } else { jarFile = getAlternativeJarFile(url); } if (jarFile != null) { searchJar(cl, all, jarFile, prefix, suffix); } else { boolean searchDone = searchDir(all, new File(URLDecoder.decode(url.getFile(), "UTF-8")), suffix); if (searchDone == false) { searchFromURL(all, prefix, suffix, url); } } } } return (URL[])all.toArray(new URL[all.size()]);}

private static boolean searchDir(Set result, File file, String suffix) throws IOException{ if (file.exists() && file.isDirectory()) { File[] fc = file.listFiles(); String path; for (int i = 0; i < fc.length; i++) { path = fc[i].getAbsolutePath(); if (fc[i].isDirectory())

Page 70: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 8. El sistema virtual de archivos

62

{ searchDir(result, fc[i], suffix); } else if (path.endsWith(suffix)) { result.add(fc[i].toURL()); } } return true; } return false;}

También hay muchos problemas con el bloqueo de archivos en los sistemas Windows, lo cual haforzado a los desarrolladores a copiar todos los ficheros de implementación en vivo a otra ubicaciónpara prevenir el bloqueo de aquellos que se encuentran en las carpetas de implementación (lo cualevitaría el borrarlos y el borrado de la implementación con base en el sistema de archivos). El bloqueode archivos es un problema importante, cuya única solución solía ser el centralizar todo el código decarga de recursos en un lugar.

El proyecto VFS se creó para resolver todos estos problemas. VFS son las siglas en ingles de VirtualFile System - sistema virtual de archivos.

8.1. API pública VFSVFS se utiliza para dos propósitos principales tal como se puede ver en Usos para VFS.

Usos para VFS• navegación simple de recursos

• API (del inglés Application Programmer Interface) del patrón del visitante

Como se mencionó anteriormente, en JDK simple, el manejo y navegación de recursos es complejo.Siempre debe chequear el tipo de recurso y estos chequeos pueden llegar engorrosos. VFS abstraelos recursos en un solo tipo de recurso, VirtualFile.

Ejemplo 8.2. El tipo de recurso VirtualFile

public class VirtualFile implements Serializable { /** * Get certificates. * * @return the certificates associated with this virtual file */ Certificate[] getCertificates()

/** * Get the simple VF name (X.java) * * @return the simple file name * @throws IllegalStateException if the file is closed */ String getName()

/** * Get the VFS relative path name (org/jboss/X.java) * * @return the VFS relative path name * @throws IllegalStateException if the file is closed */

Page 71: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

API pública VFS

63

String getPathName()

/** * Get the VF URL (file://root/org/jboss/X.java) * * @return the full URL to the VF in the VFS. * @throws MalformedURLException if a url cannot be parsed * @throws URISyntaxException if a uri cannot be parsed * @throws IllegalStateException if the file is closed */ URL toURL() throws MalformedURLException, URISyntaxException

/** * Get the VF URI (file://root/org/jboss/X.java) * * @return the full URI to the VF in the VFS. * @throws URISyntaxException if a uri cannot be parsed * @throws IllegalStateException if the file is closed * @throws MalformedURLException for a bad url */ URI toURI() throws MalformedURLException, URISyntaxException

/** * When the file was last modified * * @return the last modified time * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed */ long getLastModified() throws IOException

/** * Returns true if the file has been modified since this method was last called * Last modified time is initialized at handler instantiation. * * @return true if modifed, false otherwise * @throws IOException for any error */ boolean hasBeenModified() throws IOException

/** * Get the size * * @return the size * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed */ long getSize() throws IOException

/** * Tests whether the underlying implementation file still exists. * @return true if the file exists, false otherwise. * @throws IOException - thrown on failure to detect existence. */ boolean exists() throws IOException

/** * Whether it is a simple leaf of the VFS, * i.e. whether it can contain other files * * @return true if a simple file. * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed */ boolean isLeaf() throws IOException

/**

Page 72: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 8. El sistema virtual de archivos

64

* Is the file archive. * * @return true if archive, false otherwise * @throws IOException for any error */ boolean isArchive() throws IOException

/** * Whether it is hidden * * @return true when hidden * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed */ boolean isHidden() throws IOException

/** * Access the file contents. * * @return an InputStream for the file contents. * @throws IOException for any error accessing the file system * @throws IllegalStateException if the file is closed */ InputStream openStream() throws IOException

/** * Do file cleanup. * * e.g. delete temp files */ void cleanup()

/** * Close the file resources (stream, etc.) */ void close()

/** * Delete this virtual file * * @return true if file was deleted * @throws IOException if an error occurs */ boolean delete() throws IOException

/** * Delete this virtual file * * @param gracePeriod max time to wait for any locks (in milliseconds) * @return true if file was deleted * @throws IOException if an error occurs */ boolean delete(int gracePeriod) throws IOException

/** * Get the VFS instance for this virtual file * * @return the VFS * @throws IllegalStateException if the file is closed */ VFS getVFS()

/** * Get the parent * * @return the parent or null if there is no parent * @throws IOException for any problem accessing the virtual file system

Page 73: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

API pública VFS

65

* @throws IllegalStateException if the file is closed */ VirtualFile getParent() throws IOException

/** * Get a child * * @param path the path * @return the child or <code>null</code> if not found * @throws IOException for any problem accessing the VFS * @throws IllegalArgumentException if the path is null * @throws IllegalStateException if the file is closed or it is a leaf node */ VirtualFile getChild(String path) throws IOException

/** * Get the children * * @return the children * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed */ List<VirtualFile> getChildren() throws IOException

/** * Get the children * * @param filter to filter the children * @return the children * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed or it is a leaf node */ List<VirtualFile> getChildren(VirtualFileFilter filter) throws IOException

/** * Get all the children recursively<p> * * This always uses {@link VisitorAttributes#RECURSE} * * @return the children * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed */ List<VirtualFile> getChildrenRecursively() throws IOException

/** * Get all the children recursively<p> * * This always uses {@link VisitorAttributes#RECURSE} * * @param filter to filter the children * @return the children * @throws IOException for any problem accessing the virtual file system * @throws IllegalStateException if the file is closed or it is a leaf node */ List<VirtualFile> getChildrenRecursively(VirtualFileFilter filter) throws IOException

/** * Visit the virtual file system * * @param visitor the visitor * @throws IOException for any problem accessing the virtual file system * @throws IllegalArgumentException if the visitor is null * @throws IllegalStateException if the file is closed */ void visit(VirtualFileVisitor visitor) throws IOException

Page 74: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 8. El sistema virtual de archivos

66

}

Todas las operaciones del sistema de archivos de sólo lectura están disponibles además de unaspocas opciones para limpiar o borrar el recurso. El manejo de la limpieza o el borrado se necesitaal tratar con algunos archivos internos temporales tal como archivos creados para manejar jarsanidadas.

Para cambiar el manejo de recursos File o URL de JDK al nuevo VirtualFile necesita un VirtualFileraíz, el cual los proporciona la clase VFS con la ayuda de la URL o el parámetro URI.

Ejemplo 8.3. Uso de la clase VFS

public class VFS { /** * Get the virtual file system for a root uri * * @param rootURI the root URI * @return the virtual file system * @throws IOException if there is a problem accessing the VFS * @throws IllegalArgumentException if the rootURL is null */ static VFS getVFS(URI rootURI) throws IOException

/** * Create new root * * @param rootURI the root url * @return the virtual file * @throws IOException if there is a problem accessing the VFS * @throws IllegalArgumentException if the rootURL */ static VirtualFile createNewRoot(URI rootURI) throws IOException

/** * Get the root virtual file * * @param rootURI the root uri * @return the virtual file * @throws IOException if there is a problem accessing the VFS * @throws IllegalArgumentException if the rootURL is null */ static VirtualFile getRoot(URI rootURI) throws IOException

/** * Get the virtual file system for a root url * * @param rootURL the root url * @return the virtual file system * @throws IOException if there is a problem accessing the VFS * @throws IllegalArgumentException if the rootURL is null */ static VFS getVFS(URL rootURL) throws IOException

/** * Create new root * * @param rootURL the root url * @return the virtual file * @throws IOException if there is a problem accessing the VFS * @throws IllegalArgumentException if the rootURL */ static VirtualFile createNewRoot(URL rootURL) throws IOException

Page 75: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

API pública VFS

67

/** * Get the root virtual file * * @param rootURL the root url * @return the virtual file * @throws IOException if there is a problem accessing the VFS * @throws IllegalArgumentException if the rootURL */ static VirtualFile getRoot(URL rootURL) throws IOException

/** * Get the root file of this VFS * * @return the root * @throws IOException for any problem accessing the VFS */ VirtualFile getRoot() throws IOException}

Los tres métodos diferentes se ven similares.

• getVFS

• createNewRoot

• getRoot

getVFS retorna una instancia VFS pero todavía no crea una instancia VirtualFile. Esto es importanteya que hay métodos que ayudan con la configuración de una instancia VFS (consulte la clase VFSAPI javadocs) antes de ordenarle que cree una raíz VirtualFile.

Por otro lado, los otros dos métodos usan configuraciones predeterminadas para la creación de root.La diferencia entre createNewRoot y getRoot es en los detalles de caché, los cuales abordaremosmás adelante.

Ejemplo 8.4. Uso de getVFS

URL rootURL = ...; // get root urlVFS vfs = VFS.getVFS(rootURL);// configure vfs instanceVirtualFile root1 = vfs.getRoot();// or you can get root directlyVirtualFile root2 = VFS.crateNewRoot(rootURL);VirtualFile root3 = VFS.getRoot(rootURL);

Otra cosa útil de la API VFS es su implementación de un patrón visitante apropiado. Es muy simple elreunir recursos de manera recursiva, una tarea dificil de realizar con la carga de recursos JDK simple.

Ejemplo 8.5. Reunión de recursos de manera recursiva

public interface VirtualFileVisitor { /** * Get the search attribues for this visitor * * @return the attributes */ VisitorAttributes getAttributes();

/**

Page 76: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 8. El sistema virtual de archivos

68

* Visit a virtual file * * @param virtualFile the virtual file being visited */ void visit(VirtualFile virtualFile);}

VirtualFile root = ...; // get rootVirtualFileVisitor visitor = new SuffixVisitor(".class"); // get all classesroot.visit(visitor);

8.2. Arquitectura VFSAunque la API pública es bastante is quite intuitiva, los detalles de la implementación real agregancomplejidad. Es necesario explicar algunos conceptos en más detalle.

Cada vez que crea una instancia VFS también se crea su instancia correspondiente VFSContext.Esta creación se realiza por medio de VFSContextFactory. Protocolos diferentes mapeana diferentes instancias VFSContextFactory. Por ejemplo, file/vfsfile mapea aFileSystemContextFactory mientras que zip/vfszip mapea a ZipEntryContextFactory.

Cada vez que se crea una instancia VirtualFile también se crea su VirtualFileHandlercorrespondiente. Esta instancia VirtualFileHandler sabe cómo manejar diferentes tipos de recursosapropiadamente; el API VirtualFile solo delega invocaciones a su referencia VirtualFileHandler.

La instancia VFSContext sabe cómo crear instancias VirtualFileHandler de acuerdo con el tipode recurso. Por ejemplo, ZipEntryContextFactory crea ZipEntryContext, el cual luego creaZipEntryHandler.

8.3. Implementaciones existentesAparte de archivos, directorios (FileHandler) y ficheros zip (ZipEntryHandler), el microcontenedortambién soporta otros casos más avanzados. El primero es Assembled, el cual es similar a lo queEclipse llama Linked Resources. Su propósito es tomar recursos ya existentes de diferentes árboles y"simular" un sólo árbol de recursos.

Ejemplo 8.6. Implementación de VirtualFileHandlers reunidos

AssembledDirectory sar = AssembledContextFactory.getInstance().create("assembled.sar");

URL url = getResource("/vfs/test/jar1.jar");VirtualFile jar1 = VFS.getRoot(url);sar.addChild(jar1);

url = getResource("/tmp/app/ext.jar");VirtualFile ext1 = VFS.getRoot(url);sar.addChild(ext);

AssembledDirectory metainf = sar.mkdir("META-INF");

url = getResource("/config/jboss-service.xml");VirtualFile serviceVF = VFS.getRoot(url);metainf.addChild(serviceVF);

AssembledDirectory app = sar.mkdir("app.jar");url = getResource("/app/someapp/classes");VirtualFile appVF = VFS.getRoot(url);app.addPath(appVF, new SuffixFilter(".class"));

Page 77: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Ganchos de extensión

69

Otra implementación son los archivos en-memoria. Esta implementación surgió de la necesidad demanejar fácilmente bytes generados por AOP. En lugar de utilizar archivos temporales, puede ponerbytes en VirtualFileHandlers en la memoria.

Ejemplo 8.7. Implementación de VirtualFileHandlers en memoria

URL url = new URL("vfsmemory://aopdomain/org/acme/test/Test.class");byte[] bytes = ...; // some AOP generated class bytesMemoryFileFactory.putFile(url, bytes);

VirtualFile classFile = VFS.getVirtualFile(new URL("vfsmemory://aopdomain"), "org/acme/test/Test.class");InputStream bis = classFile.openStream(); // e.g. load class from input stream

8.4. Ganchos de extensiónEs fácil extender VFS con un nuevo protocolo, similar a lo que hicimos con Assembled y Memory.Todo lo que necesita es una combinación de las implementaciones VFSContexFactory,VFSContext, VirtualFileHandler, FileHandlerPlugin y URLStreamHandler. LaVFSContextFactory es trivial mientras que las otras dependen de la complejidad de su tarea.Puede implementar el acceso rar, tar, gzip, o incluso remote.

Después de implementar un nuevo protocolo, registre el nuevo VFSContextFactory conVFSContextFactoryLocator.

8.5. FuncionalidadesUno de los problemas principales que los desarrolladores del microcontenedor enfrentaron fue el usoapropiado de los recursos anidados, más especificamente de los archivos jar anidados: por ejemplo,implementaciones ear normales: gema.ear/ui.war/WEB-INF/lib/struts.jar.

Con el fin de leer el contenido de struts.jar tenemos dos opciones:

• manejar los recursos en la memoria

• crear copias temporales de jars a nivel superior de manera recursiva

La primera opción es más fácil de implementar, pero consume mucha memoria, lo cual requierepotencialmente que las aplicaciones grandes residan en la memoria. El otro enfoque deja atrás ungran número de archivos temporales, los cuales deben ser invisibles para el usuario y por lo tantodeben desaparecer después del borrado de la implementación.

Considere el siguiente escenario: un usuario accede uns intstancia URL VFS, la cual apunta a algunrecurso anidado.

La manera en que el VFS simple manejaría esto es re-creando toda la ruta desde el principio:desempacaría los recursos anidados y de nuevo. Esto crea un gran número de archivos temporales.

El microcontenedor evita esto utilizando VFSRegistry, VFSCache y TempInfo.

Cuando solicita VirtualFile sobrer VFS (getRoot no createNewRoot), VFS le pide a laimplementación VFSRegistry que proporcione el archivo. El DefaultVFSRegistry existenteprimero chequea si extiste un VFSContext raíz que coincida para la URI dada. Si sí existe entoncesDefaultVFSRegistry primero trata de navigar al TempInfo existente (enlace a un archivotemporal), regresando a la navegación normal si no existe dicho archivo temporal. De esta manerareutiliza completamente cualuqier archivo temporal que ya hayan sido desempacados, ahorrando

Page 78: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 8. El sistema virtual de archivos

70

tiempo y espacio en el disco. Si no se encuentra un VFSContext que coincida en el caché entoncesel código creará una nueva entrada VFSCache y continuará con la navegación predeterminada.

El determinar la manera en que el VFSCache maneja las entradas VFSContext en caché dependede la implementación utilizada. VFSCache es configurable por medio de VFSCacheFactory. Pordefecto, nada va en el caché, pero hay unas pocas implementaciones VFSCache útiles existentes,utilizando algoritmos tal como Least Recently Used (LRU) o timed cache.

Page 79: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

71

La capa ClassLoadingJBoss siempre ha tenido una manera única de tratar con la carga de clase y la nueva capaclassloading que viene junto con el microcontenedor no es la excepción. ClassLoading es unafuncionalidad agregada que puede utilizar cuando prefiera la carga de clase no predeterminada. Conuna mayor demanda por la carga de clase de estilo OSGi y un número de especificaciones nuevas decarga de clase Java en el horizonte, los cambios a la capa ClassLoading de EAP 5.1 son útiles y muyoportunos.

La capa ClassLoading del microcontenedor es una capa de abstracción. La mayoría de los detallesse esconden detrás de métodos privados y de paquetes privados sin comprometer la extensibilidad yfuncionalidad disponibles por medio de las clases y métodos públicos que hacen el API. Esto significaque usted escribe código frente a la política y no frente a los detalles del cargador de clase.

El proyecto ClassLoader se divide en 3 sub-proyectos

• el cargador de clase - classloader

• la carga de la clase - classloading

• classloading-vfs

classloader contiene una extensión java.lang.ClassLoader personalizada sin ningunapolítica de carga de clase específica. Una política de carga de clase incluye el saber desde dóndecarga y cómo cargar.

Classloading es una extensión de los mecanismos de dependencia del microcontenedor. Suimplementación respaldada por VFS es classloading-vfs. Consulte Capítulo 8, El sistema virtualde archivos para obtener mayor información sobre VFS.

9.1. ClassLoaderLa implementación ClassLoader soporta políticas enchufables y es una clase final, se suponeque no se debe alterar. Para escribir sus propias implementaciones ClassLoader, escriba unaClassLoaderPolicy, la cual proporciona una API más simple para ubicar las clases y recursos ypara especificar otras reglas asociadas con el cargador de clase.

Para personalizar la carga de clase, instance una ClassLoaderPolicy y regístrela con unClassLoaderSystem para crear un ClassLoader personalizado. También puede crear unClassLoaderDomain para realizar la partición en el ClassLoaderSystem.

La capa ClassLoader también incluye la implementación de cosas como el modelo DelegateLoader,la carga de clase, filtros de recursos y políticas de delegación padre-hijo.

El tiempo de ejecución está habilitado para JMX para exponer la política utilizada para cada cargadorde clase. También proporciona estadísticas de carga de clase y métodos de depuración para ayudar adeterminar desde dónde se cargan las cosas.

Ejemplo 9.1. La clase ClassLoaderPolicyLa ClassLoaderPolicy controla la manera en que funciona la carga de clase.

public abstract class ClassLoaderPolicy extends BaseClassLoaderPolicy { public DelegateLoader getExported()

public String[] getPackageNames()

Page 80: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 9. La capa ClassLoading

72

protected List<? extends DelegateLoader> getDelegates()

protected boolean isImportAll() protected boolean isCacheable() protected boolean isBlackListable()

public abstract URL getResource(String path);

public InputStream getResourceAsStream(String path)

public abstract void getResources(String name, Set<URL> urls) throws IOException;

protected ProtectionDomain getProtectionDomain(String className, String path) public PackageInformation getPackageInformation(String packageName) public PackageInformation getClassPackageInformation(String className, String packageName)

protected ClassLoader isJDKRequest(String name) }}

Los siguientes dos ejemplos de ClassLoaderPolicy. El primero recupera los recursos con base enexpresiones regulares, mientras que el segundo maneja los recursos encriptados.

Ejemplo 9.2. ClassLoaderPolicy con soporte para expresiones regulares

public class RegexpClassLoaderPolicy extends ClassLoaderPolicy { private VirtualFile[] roots; private String[] packageNames;

public RegexpClassLoaderPolicy(VirtualFile[] roots) { this.roots = roots; }

@Override public String[] getPackageNames() { if (packageNames == null) { Set<String> exportedPackages = PackageVisitor.determineAllPackages(roots, null, ExportAll.NON_EMPTY, null, null, null); packageNames = exportedPackages.toArray(new String[exportedPackages.size()]); } return packageNames; }

protected Pattern createPattern(String regexp) { boolean outside = true; StringBuilder builder = new StringBuilder(); for (int i = 0; i < regexp.length(); i++) { char ch = regexp.charAt(i); if ((ch == '[' || ch == ']' || ch == '.') && escaped(regexp, i) == false) { switch (ch) { case '[' : outside = false; break; case ']' : outside = true; break; case '.' : if (outside) builder.append("\\"); break; }

Page 81: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

ClassLoader

73

}

builder.append(ch); } return Pattern.compile(builder.toString()); }

protected boolean escaped(String regexp, int i) { return i > 0 && regexp.charAt(i - 1) == '\\'; }

public URL getResource(String path) { Pattern pattern = createPattern(path); for (VirtualFile root : roots) { URL url = findURL(root, root, pattern); if (url != null) return url; } return null; }

private URL findURL(VirtualFile root, VirtualFile file, Pattern pattern) { try { String path = AbstractStructureDeployer.getRelativePath(root, file); Matcher matcher = pattern.matcher(path); if (matcher.matches()) return file.toURL();

List<VirtualFile> children = file.getChildren(); for (VirtualFile child : children) { URL url = findURL(root, child, pattern); if (url != null) return url; }

return null; } catch (Exception e) { throw new RuntimeException(e); } }

public void getResources(String name, Set<URL> urls) throws IOException { Pattern pattern = createPattern(name); for (VirtualFile root : roots) { RegexpVisitor visitor = new RegexpVisitor(root, pattern); root.visit(visitor); urls.addAll(visitor.getUrls()); } }

private static class RegexpVisitor implements VirtualFileVisitor { private VirtualFile root; private Pattern pattern; private Set<URL> urls = new HashSet<URL>();

private RegexpVisitor(VirtualFile root, Pattern pattern)

Page 82: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 9. La capa ClassLoading

74

{ this.root = root; this.pattern = pattern; }

public VisitorAttributes getAttributes() { return VisitorAttributes.RECURSE_LEAVES_ONLY; }

public void visit(VirtualFile file) { try { String path = AbstractStructureDeployer.getRelativePath(root, file); Matcher matcher = pattern.matcher(path); if (matcher.matches()) urls.add(file.toURL()); } catch (Exception e) { throw new RuntimeException(e); } }

public Set<URL> getUrls() { return urls; } }}

RegexpClassLoaderPolicy usa un mecanismo simplistico para encontrar los recursos quecoinciden. Las implementaciones del mundo real serían más completas y elegantes.

public class RegexpService extends PrintService { public void start() throws Exception { System.out.println();

ClassLoader cl = getClass().getClassLoader(); Enumeration<URL> urls = cl.getResources("config/[^.]+\\.[^.]{1,4}"); while (urls.hasMoreElements()) { URL url = urls.nextElement(); print(url.openStream(), url.toExternalForm()); } }}

El servicio de expresiones regulares usa el patrón de la expresión regular config/[^.]+\\.[^.]{1,4} para listar los recursos bajo el directorio config// . La longitud del sufijo es limitado de talmanera que los nombres de archivos tal como excluded.properties se ignorarán.

Ejemplo 9.3. ClassLoaderPolicy con soporte para codificación

public class CrypterClassLoaderPolicy extends VFSClassLoaderPolicy { private Crypter crypter;

Page 83: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

ClassLoader

75

public CrypterClassLoaderPolicy(String name, VirtualFile[] roots, VirtualFile[] excludedRoots, Crypter crypter) { super(name, roots, excludedRoots); this.crypter = crypter; }

@Override public URL getResource(String path) { try { URL resource = super.getResource(path); return wrap(resource); } catch (IOException e) { throw new RuntimeException(e); } }

@Override public InputStream getResourceAsStream(String path) { InputStream stream = super.getResourceAsStream(path); return crypter.crypt(stream); }

@Override public void getResources(String name, Set<URL> urls) throws IOException { super.getResources(name, urls); Set<URL> temp = new HashSet<URL>(urls.size()); for (URL url : urls) { temp.add(wrap(url)); } urls.clear(); urls.addAll(temp); }

protected URL wrap(URL url) throws IOException { return new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile(), new CrypterURLStreamHandler(crypter)); }}

Ejemplo 9.3, “ClassLoaderPolicy con soporte para codificación” muestra cómo encriptar JARs.Puede configurar cuáles recursos codificar especificando un filtro apropiado. Aquí todo estáencriptado a excepción del contenido del directorio META-INF/.

public class EncryptedService extends PrintService { public void start() throws Exception { ClassLoader cl = getClass().getClassLoader();

URL url = cl.getResource("config/settings.txt"); if (url == null) throw new IllegalArgumentException("No such settings.txt.");

InputStream is = url.openStream(); print(is, "Printing settings:\n");

is = cl.getResourceAsStream("config/properties.xml"); if (is == null) throw new IllegalArgumentException("No such properties.xml.");

print(is, "\nPrinting properties:\n");

Page 84: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 9. La capa ClassLoading

76

}}

Este servicio imprime el contenido de dos archivos de configuración. Muestra que se esconde ladecodificación de cualquier recurso encriptado detrás de la capa de carga de clase.

Para probar esto apropiadamente puede encriptar el módulo de política usted mismo opuede utilizar uno que ya esté encriptado. Para poner esto en acción es necesario que uanapropiadamente EncryptedService con ClassLoaderSystem y los programas de implementación.

Más adelante en este capítulo abrodamos el particionamiento del ClassLoaderSystem.

9.2. ClassLoadingEn lugar de utilizar la abstracción ClassLoader directamente puede crear módulos ClassLoading,los cuales contienen declaraciones de dependencias ClassLoader. Una vez se especifican lasdependencias se construyen las ClassLoaderPolicys y se conectan de manera respectiva.

Para facilitar la definición de los ClassLoaders antes de que existan, la abstracción incluye unmodelo ClassLoadingMetaData.

El ClassLoadingMetaData se puede presentar como un objeto administrado dentro del nuevoservicio de perfil JBoss EAP. Esto le ayuda a los administradores de sistemas a tratar con los detallesde la política abstracta en lugar de los detalles de la implementación.

Ejemplo 9.4. ClassLoadingMetaData presentada como un objeto administrado

public class ClassLoadingMetaData extends NameAndVersionSupport { /** The serialVersionUID */ private static final long serialVersionUID = -2782951093046585620L;

/** The classloading domain */ private String domain;

/** The parent domain */ private String parentDomain;

/** Whether to make a subdeployment classloader a top-level classloader */ private boolean topLevelClassLoader = false;

/** Whether to enforce j2se classloading compliance */ private boolean j2seClassLoadingCompliance = true;

/** Whether we are cacheable */ private boolean cacheable = true;

/** Whether we are blacklistable */ private boolean blackListable = true;

/** Whether to export all */ private ExportAll exportAll;

/** Whether to import all */ private boolean importAll;

/** The included packages */ private String includedPackages;

/** The excluded packages */ private String excludedPackages;

Page 85: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

ClassLoading

77

/** The excluded for export */ private String excludedExportPackages;

/** The included packages */ private ClassFilter included;

/** The excluded packages */ private ClassFilter excluded;

/** The excluded for export */ private ClassFilter excludedExport;

/** The requirements */ private RequirementsMetaData requirements = new RequirementsMetaData();

/** The capabilities */ private CapabilitiesMetaData capabilities = new CapabilitiesMetaData();

... setters & getters

Ejemplo 9.5, “API ClassLoading definida en XML” y Ejemplo 9.6, “API ClassLoading definida en Java”muestran la API ClassLoading definida en XML y Java respectivamente.

Ejemplo 9.5. API ClassLoading definida en XML

<classloading xmlns="urn:jboss:classloading:1.0" name="ptd-jsf-1.0.war" domain="ptd-jsf-1.0.war" parent-domain="ptd-ear-1.0.ear" export-all="NON_EMPTY" import-all="true" parent-first="true"/>

Ejemplo 9.6. API ClassLoading definida en Java

ClassLoadingMetaData clmd = new ClassLoadingMetaData();if (name != null) clmd.setDomain(name + "_Domain");clmd.setParentDomain(parentDomain);clmd.setImportAll(true);clmd.setExportAll(ExportAll.NON_EMPTY);clmd.setVersion(Version.DEFAULT_VERSION);

Puede agregar ClassLoadingMetaData a su implementación ya sea programáticamente odeclarativamente por medio de jboss-classloading.xml.

Ejemplo 9.7. Agregar ClassLoadingMetaData por medio de jboss-classloading.xml

<classloading xmlns="urn:jboss:classloading:1.0" domain="DefaultDomain" top-level-classloader="true" export-all="NON_EMPTY"

Page 86: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 9. La capa ClassLoading

78

import-all="true"></classloading>

El DefaultDomain se comparte entre todas las aplicaciones que no definen sus propios dominios.

Ejemplo 9.8. Aislamiento típico a nivel de dominio

<classloading xmlns="urn:jboss:classloading:1.0" domain="IsolatedDomain" export-all="NON_EMPTY" import-all="true"></classloading>

Ejemplo 9.9. Aislamiento con un padre específico

<classloading xmlns="urn:jboss:classloading:1.0" domain="IsolatedWithParentDomain" parent-domain="DefaultDomain" export-all="NON_EMPTY" import-all="true"></classloading>

Ejemplo 9.10. No cumple con los requerimientos de j2seClassLoadingCompliance

<classloading xmlns="urn:jboss:classloading:1.0" parent-first="false"></classloading>

Las implementaciones .war usan este método por defecto. En lugar de realizar bśuqeudas depadres primero por defecto primero chequea sus propios recursos.

Ejemplo 9.11. Implementación típica OSGi

<classloading xmlns="urn:jboss:classloading:1.0"> <requirements> <package name="org.jboss.dependency.spi"/> </requirements> <capabilities> <package name="org.jboss.cache.api"/> <package name="org.jboss.kernel.spi"/> </capabilities></classloading>

Ejemplo 9.12. Importing and Exporting Whole Modules and Libraries, Rather than Fine-GrainedPackages

<classloading xmlns="urn:jboss:classloading:1.0"> <requirements> <module name="jboss-reflect.jar"/> </requirements>

Page 87: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

ClassLoading

79

<capabilities> <module name="jboss-cache.jar"/> </capabilities></classloading>

<classloading xmlns="urn:jboss:classloading:1.0"> <requirements> <package name="si.acme.foobar"/> <module name="jboss-reflect.jar"/> </requirements> <capabilities> <package name="org.alesj.cl"/> <module name="jboss-cache.jar"/> </capabilities></classloading>

También puede mezclar los requerimientos y los tipos de funcionalidades usando paquetes ymódulos.

El sub-proyecto de carga de clase usa una implementación muy pequeña del patrón recurso-visitante.

En el proyecto ClassLoader, la conexión entre implementación y carga de clase se realiza pormedio de la clase Module, la cual mantiene toda la información requerida para aplicar restriccionesapropiadamente en el patrón del visitante tal como los filtros.

Ejemplo 9.13. Las interfaces ResourceVisitor y ResourceContext

public interface ResourceVisitor { ResourceFilter getFilter();

void visit(ResourceContext resource);}

public interface ResourceContext { URL getUrl();

ClassLoader getClassLoader();

String getResourceName();

String getClassName();

boolean isClass();

Class<?> loadClass();

InputStream getInputStream() throws IOException;

byte[] getBytes() throws IOException;}

Para usar el módulo, instancie su instancia ResourceVisitor y pásela al método Module::visit.Esta funcionalidad se utiliza en el marco d etrabajo de la implementación para indexar los usos deanotacions en las implementaciones.

Page 88: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 9. La capa ClassLoading

80

9.3. Carga de clase VFSEsros ejemplos proporcionan una implementación de la ClassLoaderPolicy que usa un proyectode sistema de archivos virtual JBoss para cargar clases y recursos. Puede utilizar esta ideadirectamente o en conjunto con un marco de trabajo de carga de clase.

Opcionalmente puede configurar sus módulos dentro de la configuración del microcontenedor.

Ejemplo 9.14. Programa de implementación del módulo de carga de clases

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<classloader name="anys-classloader" xmlns="urn:jboss:classloader:1.0" import-all="true" domain="Anys" parent-domain="DefaultDomain"> <capabilities> <package name="org.jboss.test.deployers.vfs.reflect.support.web"/> </capabilities> <root>${jboss.tests.url}</root> </classloader>

<bean name="AnyServlet" class="org.jboss.test.deployers.vfs.reflect.support.web.AnyServlet"> <classloader><inject bean="anys-classloader:0.0.0"/></classloader> </bean>

</deployment>

La clase VFSClassLoaderFactory transforma el programa de implementación XML en unVFSClassLoaderPolicyModule, el cual luego crea la instacia real del ClassLoader. Luegopuede utilizar directamente esta nueva instancia ClassLoader con sus beans.

Nota

VFSClassLoaderFactory extiende ClassLoadingMetaData así que todos los ejemplosrelacionados con ClassLoadingMetaData aplican en este caso también.

Page 89: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

81

Marco de trabajo de la implementaciónvirtualEl nuevo Marco d etrabajo de la implementación virtual (VDF del inglés Virtual DeploymentFramework) es una manera mejorada de administrar los programas de implementación en elmicrocontenedor. Este capítulo detalla algunas de sus funcionalidades más útiles.

10.1. Manejo agnóstico de tipos de implementaciónEl tipo tradicional de implementación virtual se basa en clases que ya existen en un espcio de claseo dominio compartido. En este caso, el producto final es un nuevo servicio instalado en el servidordesde el cliente principal. La manera tradicional de lograr esto es cargar un archivo del programade implementación. El nuevo VDF simplifica este proceso pasando los bytes y serialiándolos en unainstancia Deployment.

El otro tipo de implementación, el cual extiende el primero, es una implementanción basada en elsistema simple de archivos, respaldado po el microcontenedor VFS. Este enfoque se describe conmás detalle en Capítulo 8, El sistema virtual de archivos.

10.2. Separación del reconocimiento de la estructura de lalógica del ciclo de vida de la implementaciónCon el fin de realizar cualquier trabajo real encima de una implementación primero debe comprendersu estructura incluyendo sus rutas de clase y la ubicación de sus metadatos.

La ubicación de los metadatos incluye los archivos de configuración tal como my-jboss-beans.xml, web.xml, ejb-jar.xml. Las rutas de clase son raíces del cargador de clase tal comoWEB-INF/classes o myapp.ear/lib.

Teniendo esta estructura en mente puede proceder al manejo de la implementación.

Ciclo de vida de una implementación típica1. El MainDeployer le pasa la implementación al grupo de StructuralDeployers para un

reconocimiento y recibe un contexto de implementación.

2. Luego, el MainDeployer le pasa el contexto de implementación que resulta a los Deployerspara que el Deployer apropiado lo maneje.

De esta manera, el MainDeployer es un agente con la responsibilidad de decidir qué programas deimplementación utilizar.

En el caso de una implementación virtual o programática, una información StructureMetaDatapredeterminada ya existente lee la información de la estructura y la maneja de una de las manerasque se explicó en Manejo de la información StructuredMetaData.

Manejo de la información StructuredMetaDataImplementaciones basadas en VFS

el reconocimiento de la estructura se re-envía a un grupo de StructureDeployers.

estructuras definidas de la especificación JEEtenemos implementaciones StructureDeployer que coinciden:

• EarStructure

Page 90: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 10. Marco de trabajo de la implementación virtual

82

• WarStructure

• JarStructure

DeclarativeStructuresbusca el archivo META-INF/jboss-structure.xml dentro de su implementación y lo analizasintácticamente para construir un StructureMetaData apropiado.

FileStructuressolo reconoce los archivos de configuración conocidos tal como -jboss-beans.xml o -service.xml.

Ejemplo 10.1. Un ejemplo de jboss-structure.xml

<structure> <context comparator="org.jboss.test.deployment.test.SomeDeploymentComparatorTop"> <path name=""/> <metaDataPath> <path name="META-INF"/> </metaDataPath> <classpath> <path name="lib" suffixes=".jar"/> </classpath> </context></structure>

En el caso de EarStructure, primero reconozca una implementación a nivel superior y luego proceserecursivamente las sub-implementaciones.

Puede implementar un StructureDeployer personalizado con la ayuda de la clase genéricaGroupingStructure proporcionada por la interfaz genérica StructureDeployer.

Después de tener una estructura de implementación reconocida se la puede pasar a losprogramas de implementación reales. El objeto Deployers sabe cómo encargarse de losprogramas de implementación reales, utilizando una cadena de programas de implementación porDeploymentStage.

Ejemplo 10.2. Etapas de la implementación

public interface DeploymentStages { /** The not installed stage - nothing is done here */ DeploymentStage NOT_INSTALLED = new DeploymentStage("Not Installed");

/** The pre parse stage - where pre parsing stuff can be prepared; altDD, ignore, ... */ DeploymentStage PRE_PARSE = new DeploymentStage("PreParse", NOT_INSTALLED);

/** The parse stage - where metadata is read */ DeploymentStage PARSE = new DeploymentStage("Parse", PRE_PARSE);

/** The post parse stage - where metadata can be fixed up */ DeploymentStage POST_PARSE = new DeploymentStage("PostParse", PARSE);

/** The pre describe stage - where default dependencies metadata can be created */ DeploymentStage PRE_DESCRIBE = new DeploymentStage("PreDescribe", POST_PARSE);

/** The describe stage - where dependencies are established */ DeploymentStage DESCRIBE = new DeploymentStage("Describe", PRE_DESCRIBE);

/** The classloader stage - where classloaders are created */

Page 91: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Separación del reconocimiento de la estructura de la lógica del ciclo de vida de la implementación

83

DeploymentStage CLASSLOADER = new DeploymentStage("ClassLoader", DESCRIBE);

/** The post classloader stage - e.g. aop */ DeploymentStage POST_CLASSLOADER = new DeploymentStage("PostClassLoader", CLASSLOADER);

/** The pre real stage - where before real deployments are done */ DeploymentStage PRE_REAL = new DeploymentStage("PreReal", POST_CLASSLOADER);

/** The real stage - where real deployment processing is done */ DeploymentStage REAL = new DeploymentStage("Real", PRE_REAL);

/** The installed stage - could be used to provide valve in future? */ DeploymentStage INSTALLED = new DeploymentStage("Installed", REAL);}

La etapas de implementación pre-existentes se mapean a los estados del controlador incorporadodel microcontenedor. Proporcionan una vista céntrica del ciclo de vida de la implementación de losestados del controlador genérico.

Dentro de los programas de implementación, la implementación se convierte en el componenteDeploymentControllerContext del microcontenedor. La máquina de estado del microcontenedormaneja las dependencias.

Las implementaciones se manejan secuencialmente por etapa de implementación. Para cadaporgrama de implementación se maneja todo el orden de la jerarquía implementada usando lapropiedad parent-first del programa de implementación. Esta propiedad se configura como truepor defecto.

También puede especificar los niveles de jerarquía que el programa de implementación maneja.Puede seleccionar all, top level, components only o no components.

La manera en que el microcontendor maneja los modelos de componentes y el manejo de lasdependencias también aplica aquí. Si hay dependencias no resueltas entonces la implementaciónempezará en el estado actual, potencialmente reportando un error si el estado actual no es el estadorequerido.

El agregar un nuevo programa de implementación se logra extendiendo uno de los muchosprogramas de implementación de ayuda que existen.

Algunos programas de implementacióin de hecho necesitan una implementación respaldada porVFS mientras que otros pueden utilizar una implementación general. En la mayoría de los casos losprogramas de instalación de análisis sintáctico son los que necesitan respaldo de VFS.

Aviso

También tenga en cuenta que los programas de implementación ejecutan recursivamente entoda implementación, sub-implementación y componentes. Su código necesita determinar tanpronto como sea posible en el proceso, si el programa de implementación debe manejar laimplementación actual o no.

Ejemplo 10.3. Programa de implementación simple, el cual presenta información sobre suimplementación

public class StdioDeployer extends AbstractDeployer {

Page 92: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 10. Marco de trabajo de la implementación virtual

84

public void deploy(DeploymentUnit unit) throws DeploymentException { System.out.println("Deploying unit: " + unit); }

@Override public void undeploy(DeploymentUnit unit) { System.out.println("Undeploying unit: " + unit); }}

Agregue esta descripción en uno de los archivos -jboss-beans.xml en el directorio deployers/en el servidor de aplicaciones JBoss y el bean MainDeployerImpl reconocerá este programa deimplementación por medio del manejo callback loC del microcontenedor.

Ejemplo 10.4. Descriptor de implementación simple

<bean name="StdioDeployer" class="org.jboss.acme.StdioDeployer"/>

10.3. Control de flujo natural en forma de anexosVDF incluye un mecanismo llamado anexos -attachments, el cual facilita el paso de la información deun programa de implementación al siguiente. Los anexos se implementan como un java.util.Mapcon mejoras, cuyas entradas representan un anexo.

Algunos programas de implementación son productores mientras que otros son consumidores. Elmismo programa de implementación también puede realizar ambas funciones. Algunos programas deimplementación crean metadatos o instancias de funcionalidades poniéndolos en el mapa de anexos.Otros programas de implementación solo declaran su necesidad de estos anexos y toman los datosdel mapa de anexos, antes de realizar trabajo adicional en esos datos.

El orden natural se refiere a la manera en que los porgramas de implementación se ordenan. Unorden natural común usa los términos relativos antes y después. Sin embargo, con el mecanismode anexos en uso puede ordenar los programas de implementación de acuerdo a la manera en queproducen y/o consumen los anexos.

Cada anexo tiene una llave y los programas de implementación pasan las llaves a los anexos queproducen. Si el programa de implementación produce un anexo entonces se llama a la llave output. Siel programa de implementación consume un anexo entonces esa llave se llama input.

Los programas de implementación tienen entradas ordinarias y entradas requeridas. Las entradasordinarias sólo se utilizan para ayudar a determinar el orden natural. Las entradas requeridas tambiénayudan a determinar el orden, pero también tienen otra función. Ayudan a determinar si el programade implementación de hecho es relevante para la implementación dada, chequeando a ver si existeun anexo correspondiente a esa entrada requerida en el mapa de anexos.

Aviso

Aunque se soporta el ordenamiento relativo, este se considera como mala práctica y es posibleque no haya soporte para este en lanzamientos futuros.

Page 93: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Detalles de la implementación y del cliente, usuario y uso del servidor

85

10.4. Detalles de la implementación y del cliente, usuario yuso del servidorEstas funcionalidades esconden los detalles de la implementación, lo cual hace que el uso sea menospropenso a errores y al mismo tiempo optimiza el proceso de desarrollo.

La meta es que los clientes solo vean una API de desarrollo mientras que los desarrolladoresvean un DeploymentUnit y los detalles de la implementación del servidor se encuentren en unDeploymentContext. Solo se presenta la información necesaria en un nivel en particular del ciclo devida de la implementación.

Ya mencionamos los componentes como parte del manejo de la jerarquía de los desarrolladores.Aunque la implementación y sub-implementación a nivel superior son una representación natural dela jerarquía de la estructura de la implementación, los componentes son un nuevo concepto VDF.La idea de los componentes es que tengan un mapeo 1:1 con el ControllerContexts dentro delmicrocontenedor. Consulte ¿Por qué los componentes mapean 1:1 con los ControllerContextspara ver las razones que respaldan esta afirmación.

¿Por qué los componentes mapean 1:1 con los ControllerContextsNombrado

El nombre de la unidad del componente es el mismo que el nombre del ControllerContext.

get*Scope() and get*MetaData()retorna el mismo contexto MDR que el microcontenedor utilizará para esa instancia.

IncompleteDeploymentException (IDE)Con el fin de que el IDE imprima las dependencias que faltan en una implementación, necesitasaber los nombres del ControllerContext. descubre el nombre reuniendo los nombres de lasDeploymentUnit's componentes en los programas de implementación de componentes quelos especifican tal como los métodos BeanMetaDataDeployer o setUseUnitName() enAbstractRealDeployer.

10.5. Máquina de estado únicoTodos los componentes del microcontenedor son manejados por un solo punto de entrada o una solamáquina de estado. Las implemtaciones no son la excepción.

Puede sacar ventaja de esta funcionalidad utilizando el archivo de configuración jboss-dependency.xml en sus implementaciones.

Ejemplo 10.5. jboss-dependency.xml

<dependency xmlns="urn:jboss:dependency:1.0"> <item whenRequired="Real" dependentState="Create">TransactionManager</item> (1) <item>my-human-readable-deployment-alias</item> (2)</dependency>

Note las llamadas artificiales en el XML: (1) y (2).

(1) muestra cómo describir la dependencia en otro servicio. Este ejemplo requiere el crear unTransactionManager antes de que la implementación se encuentre en la etapa 'real'.

(2) es un poco más complejo ya que le falta información adicional. Por defecto, los nombres de lasimplementaciones dentro del microcontenedor son nombres URI, lo cual hace que el escribirlos amano sea un proceso propenso a errores. Así que con el fin de declarar dependencias fácilmenteen otras implementaciones, necesita un mecanismo de alias para evitar nombres URI. Puede

Page 94: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

Capítulo 10. Marco de trabajo de la implementación virtual

86

agregar un archivo de texto simple llamado aliases.txt en su implementación. Cada líneadel archivo contiene un alias, dándole al fichero de implementación uno o más nombres simplesutilizados para referirse a este.

10.6. Escaneo de clases en busca de anotacionesLas especificaciones JEE actuales reducen el número de archivos de configuración, pero ahorase requiere que el contenedor realice la mayoría del trabajo utilizando @annotations. Con el fin deobtener información sobre @annotation, los contenedores deben escanear las clases. Este escaneocrea una penalidad en el rendimiento.

Sin embargo con el fin de reducir la cantidad de escaneo, el microcontenedor proporciona otrogancho descriptor por medio de jboss-scanning.xml.

Ejemplo 10.6. jboss-scanning.xml

<scanning xmlns="urn:jboss:scanning:1.0"> <path name="myejbs.jar"> <include name="com.acme.foo"/> <exclude name="com.acme.foo.bar"/> </path> <path name="my.war/WEB-INF/classes"> <include name="com.acme.foo"/> </path></scanning>

Este ejemplo muestra una descripción simple de rutas relativas para incluir o excluir cuando seescanea en busca de información de metadatos anotados para Java Enterprise Edition versión 5yposteriores.

Page 95: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

87

Apéndice A. Historial de revisionesRevisión 5-1 Wed Sep 15 2010 Misty Stanley-Jones [email protected]

JBPAPP-5076 - Arreglar los ejemplos y sus leyendasSe cambió el número de la versión en relación con los requerimientos de la versión.Revisado para JBoss Enterprise Application Platform 5.1.0.GA.

Page 96: JBoss Enterprise Application Platform-5-JBoss Microcontainer User Guide-Es-ES

88