Professional Documents
Culture Documents
JBoss Enterprise Application Platform 5 Manual del usuario de JBoss Microcontainer para uso con JBoss Enterprise Application Platform 5 Edicin 5.1.0
Autor Autor Editor Copyright 2011 Red Hat, Inc. The text of and illustrations in this document are licensed by Red Hat under a Creative Commons AttributionShare Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document 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 Infinity Logo, 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 States and/or other countries. MySQL is a registered trademark of MySQL AB in the United States, the European Union and other countries. All other trademarks are the property of their respective owners. Mark Newton Ale Justin Misty Stanley-Jones mark.newton@jboss.org ajustin@redhat.com misty@redhat.com
Este manual est dirigido a aquellos desarrolladores Java que desean utilizar el microcontenedor JBoss para implementar entornos Java modulares y personalizados para sus aplicaciones.
Prefacio v 1. Convenciones del Documento .......................................................................................... v 1.1. Convenciones Tipogrficas ................................................................................... v 1.2. Convenciones del documento ............................................................................... vi 1.3. Notas y Advertencias .......................................................................................... vii 2. Cmo obtener ayuda y hacer sus comentarios ............................................................... viii 2.1. Necesita ayuda? .............................................................................................. viii 2.2. Necesitamos sus comentarios! ........................................................................... viii I. Introduccin al tutorial sobre el Microcontainer 1. Prerequisitos para el uso de este manual 1.1. Instale Maven ...................................................................................................... 1.2. Configuracin especial de Maven para los ejemplos del microcontenedor ................. 1.3. Descarga de los ejemplos .................................................................................... 1 3 3 6 7
2. Introduccin al microcontenedor 9 2.1. Funcionalidades ................................................................................................... 9 2.2. Definiciones ......................................................................................................... 9 2.3. Instalacin .......................................................................................................... 10 3. Construccin de servicios 3.1. Introduccin al ejemplo de recusos humanos ....................................................... 3.2. Compilacin del proyecto de ejemplo HRManager ................................................ 3.3. Creacin de POJOs ........................................................................................... 3.3.1. Descriptores de implementacin XML ....................................................... 3.4. Conexin de POJOs ........................................................................................... 3.4.1. Consideraciones especiales ..................................................................... 3.5. Trabajar con servicios ......................................................................................... 3.5.1. Configuracin de un servicio .................................................................... 3.5.2. Probar un servicio ................................................................................... 3.5.3. Empacar un servicio ................................................................................ 4. Uso de los servicios 4.1. Bootstrap del microcontenedor ............................................................................ 4.2. Implementacin del servicio ................................................................................ 4.3. Acceso directo ................................................................................................... 4.4. Acceso indirecto ................................................................................................. 4.5. Carga de clase dinmica .................................................................................... 4.5.1. Problemas con cargadores de clase creados con los descriptores de implementacin ................................................................................................. 5. Agregar comportamiento con AOP 5.1. Creacin de un aspecto ...................................................................................... 5.2. Configuracin del microcontenedor para AOP ...................................................... 5.3. Aplicacin de un aspecto .................................................................................... 5.4. Callbacks del ciclo de vida .................................................................................. 5.5. Agregar bsquedas de servicios por medio de JNDI ............................................. II. Conceptos avanzados con el microcontenedor 6. Modelos de componentes 6.1. Interacciones permitidas con los modelos de componentes ................................... 6.2. Un Bean sin dependencias ................................................................................. 6.3. Uso del microcontenedor con Spring ................................................................... 6.4. Uso de Guice con el microcontenedor ................................................................. 11 11 12 12 12 13 13 14 14 15 16 19 21 23 24 26 27 30 31 31 33 34 36 38 41 43 43 43 43 44 iii
Manual del usuario de JBoss Microcontainer 6.5. MBeans de legado y mezcla de diferentes modelos de componentes ..................... 46 6.6. Exponer POJOs como MBeans ........................................................................... 46 7. Inyeccin avanzada de dependencias y ldC 7.1. Fbrica de valores .............................................................................................. 7.2. Callbacks ........................................................................................................... 7.3. Modo de acceso del Bean .................................................................................. 7.4. Alias Bean ........................................................................................................ 7.5. Soporte para anotaciones XML (o metadatos) ...................................................... 7.6. Autowire ............................................................................................................. 7.7. Fbrica de beans ............................................................................................... 7.8. Constructor de metadatos Bean .......................................................................... 7.9. ClassLoader personalizado ................................................................................. 7.10. Modo controlador .............................................................................................. 7.11. Ciclo ................................................................................................................ 7.12. Oferta y demanda ............................................................................................ 7.13. Instalaciones .................................................................................................... 7.14. Imitacin perezosa ............................................................................................ 7.15. Ciclo de vida .................................................................................................... 8. El sistema virtual de archivos 8.1. API pblica VFS ................................................................................................. 8.2. Arquitectura VFS ................................................................................................ 8.3. Implementaciones existentes ............................................................................... 8.4. Ganchos de extensin ........................................................................................ 8.5. Funcionalidades ................................................................................................. 9. La capa ClassLoading 9.1. ClassLoader ....................................................................................................... 9.2. ClassLoading ..................................................................................................... 9.3. Carga de clase VFS ........................................................................................... 10. Marco de trabajo de la implementacin virtual 10.1. Manejo agnstico de tipos de implementacin .................................................... 10.2. Separacin del reconocimiento de la estructura de la lgica del ciclo de vida de la implementacin ..................................................................................................... 10.3. Control de flujo natural en forma de anexos ....................................................... 10.4. Detalles de la implementacin y del cliente, usuario y uso del servidor ................. 10.5. Mquina de estado nico .................................................................................. 10.6. Escaneo de clases en busca de anotaciones ..................................................... A. Historial de revisiones 49 49 50 51 52 53 54 55 56 57 58 58 59 59 60 60 61 62 68 68 69 69 71 71 76 80 81 81 81 84 85 85 86 87
iv
Prefacio
1. Convenciones del Documento
Este manual utiliza varias convenciones para resaltar algunas palabras y frases y llamar la atencin sobre ciertas partes especficas de informacin. En ediciones PDF y de papel, este manual utiliza tipos de letra procedentes de Liberation Fonts . Liberation Fonts tambin se utilizan en ediciones de HTML si estn instalados en su sistema. Si no, se muestran tipografas alternativas pero equivalentes. Nota: Red Hat Enterprise Linux 5 y siguientes incluyen Liberation Fonts predeterminadas.
1
https://fedorahosted.org/liberation-fonts/
Prefacio Seleccionar Sistema Preferencias Ratn desde la barra del men principal para lanzar Preferencias de Ratn. En la pestaa de Botones, haga clic en la cajilla ratn de mano izquierda y luego haga clic en Cerrar para cambiar el botn principal del ratn de la izquierda a la derecha (adecuando el ratn 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 menes de mapa de caracteres elija Bsqueda Hallar, teclee el nombre del caracter en el campo Bsqueda y haga clic en Siguiente. El caracter buscado se resaltar en la Tabla de caracteres. Haga doble clic en este caracter resaltado para colocarlo en el campo de Texto para copiar y luego haga clic en el botn de Copiar. Ahora regrese a su documento y elija Editar Pegar desde la barra de men de gedit. El texto anterior incluye nombres de aplicacin; nombres y elementos del men de todo el sistema; nombres de men de aplicaciones especficas y botones y texto hallados dentro de una interfaz grfica de usuario, todos presentados en negrita proporcional y distinguibles por contexto. Itlicas-negrita monoespaciado o Itlicas-negrita proporcional Ya sea negrita monoespaciado o negrita proporcional, la adicin de itlicas indica texto reemplazable o variable. Las itlicas denotan texto que usted no escribe literalmente o texto mostrado que cambia dependiendo de la circunstancia. Por ejemplo: Para conectar a una mquina remota utilizando ssh, teclee ssh nombredeusuario@dominio.nombre en un intrprete de comandos de shell. Si la mquina remota es example.com y su nombre de usuario en esa mquina es john, teclee ssh john@example.com. El comando mount -o remount file-system remonta el sistema de archivo llamado. Por ejemplo, para volver a montar el sistema de archivo /home, el comando es mount -o remount /home. Para ver la versin de un paquete actualmente instalado, utilice el comando rpm -q paquete. ste entregar el resultado siguiente: paquete-versin-lanzamiento. Observe las palabras en itlicas y negrita sobre nombre de usuario, domain.name, sistema de archivo, paquete, versin y lanzamiento. Cada palabra es un marcador de posicin, tanto para el texto que usted escriba al ejecutar un comando como para el texto mostrado por el sistema. Aparte del uso estndar para presentar el ttulo de un trabajo, las itlicas denotan el primer uso de un trmino nuevo e importante. Por ejemplo: Publican es un sistema de publicacin de DocBook.
vi
Notas y Advertencias Los listados de cdigo fuente tambin se muestran en romano monoespaciado, pero se presentan y 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")); } }
Nota
Una nota es una sugerencia, atajo o enfoque alternativo para una tarea determinada. Ignorar una nota no debera tener consecuencias negativas, pero podra perderse de algunos trucos que pueden facilitarle las cosas.
Importante
Los cuadros con el ttulo de importante dan detalles de cosas que se pueden pasar por alto fcilmente: cambios de configuracin nicamente aplicables a la sesin actual, o servicios que necesitan reiniciarse antes de que se aplique una actualizacin. Ignorar estos cuadros no ocasionar prdida de datos, pero puede causar enfado y frustracin.
Advertencia
Las advertencias no deben ignorarse. Ignorarlas muy probablemente ocasionar prdida de datos.
vii
Prefacio
Describa el problema:
Informacin adicional:
Asegrese de darnos su nombre para poder darle todo el crdito por reportar el problema.
https://bugzilla.redhat.com/enter_bug.cgi?product=JBoss%20Enterprise%20Application%20Platform%205&component=docJBoss_Microcontainer_User_Guide&version=5.1.1&short_desc=Bug%20in%20JBoss%20Microcontainer%20User%20Guide
viii
Nota
Este paso y en el futuro se asume que ha guardado Maven en la ubicacin sugerida en su sistema operativo. Maven, como cualquier otra aplicacin Java se puede instalar en cualquier 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.
Al incluir M2 al comienzo de su ruta, la versin Maven que acab de instalar ser la versin predeterminada utilizada. Puede que tambin quierar establecer la ruta de su variable de entorno JAVA_HOME con la ubicacin del JDK en su sistema.
6.
Ejecute echo $PATH y verifique que el directorio Maven /bin est includo.
[localhost]$ echo $PATH /home/username/apache-maven-2.2.1/bin
Ejecute mvn -version, la cual debe presentar la versin de Maven, la versin Java relacionada y la informacin relacionada con el sistema operativo.
[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"
Ha configurado de manera exitosa Maven para utilizarlo con los ejemplos en este manual.
Introduccin al microcontenedor
El microcontenedor JBoss es un rediseo del JBoss JMX Microkernel para soportar la implementacin POJO directa y el uso autnomo fuera del servidor de aplicaciones JBoss. El microcontenedor est diseado para llenar las necesidades especificas de los desarrolladores Java que queran utilizar tcnicas de programacin orientadas a objetos para implementar software de manera rpida. Adems permite implementar software en un amplio rango de dispositivos desde plataformas de computacin mviles, entornos de computacin de grande escala y lo que se encuentre entre estos dos.
2.1. Funcionalidades
Todas las funcionalidades del microkernel JMX Implementacin POJO directa (no hay necesidad de estndar/XMBean o MBeanProxy) Inyeccin directa de dependencias de estilo IOC Administracin mejoarada del ciclo de vida Control adicional sobre las dependencias Integracin transparente AOP Sistema virtual de archivos Marco de trabajo de implementacin virtual Carga de clase OSGi
2.2. Definiciones
Este manual usa algunos trminos que puede que no le sean familiares. Algunos de ellos se definen en Lista de definicin del mMicrocontenedor. Lista de definicin del mMicrocontenedor Microkernel JMX JBoss JMX Microkernel es un entorno Java modular. Es diferente de los entornos estndar como J2EE ya que el desarrollador puede escoger exactamente los componentes que son parte del entorno y dejar por fuera el resto. POJO Un POJO (del ingls Plain Old Java Object) es un objeto Java modular y reutilizable. El nombre se utiliza para enfatizar que un objeto dado es un objeto Java normal, no es un objeto especial y en particular no es un JavaBean empresarial. El trmino lo utiliz por primera vez Martin Fowler, Rebecca Parsons y Josh MacKenzie in September 2000 en una charla en la cual estaban resaltando los muchos beneficios de codificar la lgica empresarial en objetos java normales en lugar de utilizar beans de entidad. Bean Java Un bean Java es un componente software re-utilizable que se puede manipular visualmente en una herramienta de construccin.
Captulo 2. Introduccin al microcontenedor Un bean Java es un pedazo de cdigo independiente. No requiere herencias de ninguna clase o interfaz base en particular. Aunque los beans Java se crean principalmente en IDEs grficos tambin se pueden desarrollar en simples editores de texto. AOP Aspect-Oriented Programming (AOP) es un paradigma de programacin en el cual las funciones secundarias o de soporte se aislan de la lgica empresarial del programa principal. Es un subgrupo de la programacin orientada a objetos.
2.3. Instalacin
El microcontenedor es una parte integral de la plataforma empresarial. En el manual de configuracin y administracin encontrar mayor informacin sobre la instalacin y configuracin de la plataforma empresarial.
10
Construccin de servicios
Los servicios son pedazos de cdigo que realizan tareas que mltiples clientes necesitan. Poara nuestro propsito pondremos algunas restricciones adicionales en la definicin de un servicio. Los servicios deben tener nombres nicos, a los cuales se puede hacer referencia o los clinetes pueden llamar. El interior de un servicio debe ser invisible y sin importancia para los clientes. Este es el concepto "caja negra"de la programacin orientada a objetos (OOP del ingls object-oriented programming). En OOP, cada objeto es independente y ningn otro objeto necesita saber cmo hace su trabajo. En el contexto del microcontenedor, los servicios se construyen desde POJOs. Un POJO es casi un servicio como tal pero no se puede acceder por un nombre nico y debe ser creado por el cliente que lo necesita. Aunque un POJO se debe crear en tiempo de ejecucin por parte del cliente, no es necesario implementarlo por medio de una clase separada con el fin de proporcionar una interfaz bien definida. Con tal de que no se borren los mtodos y campos y el acceso a ellos no sea restringido, no hay necesidad de recompilar los clientes para utilizar un POJO recin creado.
Nota
El iImplementar una interfaz solo es necesario con el fin de permitir que un cliente escoja entre implementaciones opcionales. Si el cliente se compila frente a una interfaz, se pueden proporcionar muchas implementaciones diferentes de la interfaz sin tener que recompilar el cliente. La interfaz se asegura de que las firmas de mtodo no cambien.
El resto de este manual consiste de la creacin del servicio de recursos humanos utilizando el microcontenedor para capturar y modularizar la lgica empresarial de la aplicacin. Despus de que el microcontenedor est instalado, el cdigo de ejemplo se encuentra en examples/User_Guide/ gettingStarted/humanResourcesService.
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
11
Captulo 3. Construccin de servicios 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 mantienen una lista de empleados y sus detalles (direcciones y salarios, en este caso). Al utilizar la interfaz SalaryStrategy es posible configurar el HRManager de manera que hayan disponibles diferentes implementaciones de la estrategia de salario para poner lmites mnimos y mximos en los salarios para diferentes roles de empleados.
Este XML crea una instancia de la clase HRManager y la registra con el nombre HRService. Este archivo se le pasa a un programa de implementacin XML asociado con el microcontenedor en tiempo de ejecucin, el cual realiza la implementacin real e instancia los beans. 12
Conexin de POJOs
Este XML crea una instancia de la implementacin de la estrategia de salario incluyendo un elemento <bean> adicional. Esta vez, se selecciona AgeBasedSalaryStrategy. Luego el cdigo inyecta una referencia a este bean en la instancia de HRManager creada utilizando el bean HRService. La inyeccin es posible ya que la clase HRManager contiene un mtodo setSalaryStrategy(SalaryStrategy strategy). Mientras tanto detrs de bastidores el microcontenedor JBoss llama a este mtodo en la instancia HRManager recin creada y le pasa una referencia a la instancia AgeBasedSalaryStrategy. El descriptor de implementacin XML causa la misma secuencia de eventos como si hubiera escrito el siguiente cdigo:
HRManager hrService = new HRManager(); AgeBasedSalaryStrategy ageBasedSalary = new AgeBasedSalaryStrategy(); hrService.setSalaryStrategy(ageBasedSalary);
Adems de realizar la inyeccin por medio de los mtodos setter de las propiedades, el microcontenedor JBoss tambin puede realizar la inyeccin por medio de parmetros del constructor si es necesario. Para obtener mayores detalles consulte el captulo sobre 'Inyeccin' en la parte II 'Desarrollo POJO.'
Captulo 3. Construccin de servicios el utilizar comentariosy un esquema de nombrado obvio para diferenciar los beans de servicio de los beans que no son de servicio.
Las clases deben tener mtodos setter pblicos para las propiedades relevantes de manera que los valores se puedan inyectar. Por ejemplo, la clase HRManager tiene un mtodo setHiringFreeze(boolean hiringFreeze) y la clase AgeBasedSalaryStrategy tiene los mtodos setMinSalary(int minSalary) y setMaxSalary(int maxSalary). Los valores en el descriptor de implementacin se convierten de cadenas a los tipos relevantes (boolean, int, etc) por medio de PropertyEditors JavaBean. Muchos PropertyEditors se brindan por defecto para los tipos estndar, pero puede crear los propios si es necesario. Consulte el captulo de propiedades en la parte II 'Desarrollo POJO' para obtener mayores detalles.
14
Probar un servicio
log4j.properties org jboss example service HRManagerAgeBasedTestCase.xml HRManagerLocationBasedTestCase.xml HRManagerTestCase.xml util AgeBasedSalaryTestCase.xml LocationBasedSalaryTestCase.xml
El cdigo 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 nmero de empleados a utilizar como base para la prueba. Ejemplos individuales luego crean sub-clases en HRManagerTest para realizar el trabajo en s. Tambin se includyen un par de clases TestSuite que 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 15
Captulo 3. Construccin de servicios implementando los desde el archivo XML relevante antes de ejecutar cada prueba. Al final de la prueba se borra la implementacin de los beans y se apaga el microcontenedor.
Nota
Algunas de las pruebas tal como HRManagerTestCase, AgeBasedSalaryTestCase y LocationBasedSalaryTestCase prueban POJOs individuales. Otras pruebas tal como HRManagerAgeBasedTestCase y HRManagerLocationBasedTestCase prueban servicios enteros. De cualquier manera, las pruebas se ejecutan de la misma manera. El utilizar la clase MicrocontainerTest facilita el configurar y conducir pruebas completas de cualquier parte de su cdigo. Las clases Address y Employee no se anidan aqu. El escribir pruebas para ellas queda de su parte.
3.
`-- org `-- jboss `-- example `-- service |-- Address.java |-- Employee.java |-- HRManager.java `-- util |-- AgeBasedSalaryStrategy.java |-- LocationBasedSalaryStrategy.java
16
Empacar un servicio
`-- SalaryStrategy.java `--META-INF `-- MANIFEST.MF `-- maven `-- org.jboss.micrcontainer.examples `-- humanResourceService
Nota
Maven crea automticamente el directorio META-INF/maven y no estar presente si est utilizando uns sistema de construccin diferente.
17
18
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 mtodos que el cliente llama en tiempo de ejecucin para solicitar lla entrada del usuario. ConsoleInput es una implementacin de UserInterface que crea un 19
Captulo 4. Uso de los servicios TUI que el usuario utiliza para interactuar con el cliente. La ventaja de este diseo es que puede crear fcilmente una implementacin Swing de UserInterface en una fecha posterior y puede reemplazar el TUI con un GUI. Tambin puede simular el proceso de ingreso de datos con un script. Luego puede chequear el comportamiento del cliente automticamente usando ejemplos JUnit convencionales que se encuentran en Ejemplo 3.2, Listado del directorio src/test/java. Para que la construccin funcione primero debe construir e instalar auditAspect.jar desde el directorio examples/User_Guide/gettingStarted/auditAspect usando el mvn install command. Se crean un nmero de distribuciones diferentes de clientes, incluyendo una basada en AOP, la cual depende de que auditAspect.jar se encuentre disponible en el repositorio local Maven. Si anteriormente escribi mvn install desde el directorio examples/User_Guide/ gettingStarted entonces humanResourcesService.jar y auditAspect.jar ya se han construdo y empacado junto con el cliente as que este paso no ser necesario. Para compilar el cdigo fuente, se realizan todos los pasos que se encuentran en Procedimiento 4.1, Compilacin del cdigo fuente al emitir el comando mvn package desde el directorio commandLineClient. Procedimiento 4.1. Compilacin del cdigo fuente 1. Ejecute las pruebas de las unidades. 2. 3. construya una JAR cliente. Ensamble una distribucin que contenga todos los archivos necesarios.
Despus de compilar y empacar el cliente, la estructura del directorio en el diretcorio commandLineClient/target incluye los subdirectorios descritos en Ejemplo 4.2, Los subdirectorios del directorio commandLineClient/target. Ejemplo 4.2. Los subdirectorios del directorio commandLineClient/target client-pojo utilizado para llamar al servicio sin AOP. client-cl utilizado para demostrar las funcionalidades de carga de clase. client-aop Agregar soporte AOP. Consulte Captulo 5, Agregar comportamiento con AOP para obtener mayores detalles. Cada sub-directorio representa una distribucin diferente con todos los scripts shell, JARs y descriptores de implementacin XML que se necesitan para ejecutar el cliente en diferentes configuraciones. El resto de este captulo usea la distribucin client-pojo que se encuentra en el sub-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
20
Para ejecutar el cliente, cmbiese al directorio client-pojo y escriba ./run.sh. Aparecer el The Ejemplo 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 implementacin del servicio de recursos humanos a) l) r) g) s) t) Agregar empleado Listar los empleados Borrar empleado Ver un salario Establecer un salario Alternar la congelacin de la contratacin
Para seleccionar una opcin, introduzca la letra que se muestra en el lado izquierdo y oprima RETURN. Por ejemplo para ver lsa opciones del men introduzca m y luego presione RETURN. El introducir ms de una letra o el introducir una opcin invlida genera un mensaje de error.
Importante
El script run.sh establece el entorno de ejecucin agregando todas las JARs que se encuentran en el directorio lib/ a la ruta de clase usando la propiedad del sistema java.ext.dirs. Tambin agrega el directorio actual y la client-1.0.0.jar usando la eiqueta -cp de manera que el descriptor de implementacin jboss-beans.xml se encuentre en tiempo de ejecucin junto con la clase org.jboss.example.client.Client, la cual se llama para iniciar la aplicacin.
21
Primero que todo se cre una URL que representa el descriptor de implementacin jbossbeans.xml. Esto se necesita luego de manera que el programa de implementacin XML pueda implementar y borrar la implementacin de los beans declarados en el archivo. El mtodo getResource() del cargador de clase de la aplicacin se utiliza ya que se incluye el archivo jboss-beans.xml en la ruta de clase. esto es opcional; el nombre y ubicacin del descriptor de implementacin no son importantes en tanto la URL sea vlida y se pueda llegar a ella. Luego se crea una instancia de JBoss Microcontainer junto con un programa de implementacin XML. Este proceso se llama bootstrapping y se proporciona una clase llamada BasicBootstrap como parte del microcontenedor para tener en cuenta la configuracin programtica. Para agregar un programa de implementacin XML, extienda BasicBootstrap para crear una clase EmbeddedBootstrap y sobrescriba el mtodo 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(); } } }
22
Implementacin del servicio El gancho shutdown se asegura de que cuando la MVJ termina, se borra la implementacin de todos los beans en el orden correcto. Los mtodos pblicos deploy/undeploy delegan al BasicXMLDeployer de manera que los beans declarados en jboss-beans.xml se puedan implementar y borrar. Finalmente las referencias al controlador del microcontenedor y el bus se reestablecen as que puede buscar las referencias de beans por su nombre y puede accederlas directamente o indirectamente cuando los necesite.
Nota
El microcontenedor puede instanciar los beans ya que sus clases estn disponibles en la ruta de clase de extensin dentro del archivo lib/humanResourcesService.jar. Tambin puede poner estas clases en una estructura de directorio expandido y agregarla a la ruta de clase de la aplicacin, pero el empacarlos en una JAR usualmente es ms conveniente.
El descriptor de implementacin es completamente separado del archivo humanResourcesService.jar. Esto permite modificarlo para propsitos de pruebas. El archivo jboss-beans.xml en el ejemplo contiene algunos fragmentos de XML comentados, lo cual muestra algunas 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>
23
Importante
Dependiendo de la manera en que acceda el servicio en tiempo de ejecucin es posible que necesite apagar la aplicacin y re-iniciarla para volver a implementar el servicio y ver sus cambios. Esto reduce la flexibilidad de la aplicacin, pero incrementa el rendimiento en tiempo de ejecucin. Opcionalmente puede simplemente volver a implementar el servicio mientras que la aplicacin est ejecutando. Esto incrementa la flexibilidad pero disminuye el rendimiento en tiempo de ejecucin. Mantenga estas opciones en consideracin al disear sus aplicaciones.
En lugar del buscar inmediatamente una referencia a la instancia del bean, el ejemplo primero busca una referencia a un ControllerContext, luego obtiene una referencia a la instancia del bean del contexto utilizando el mtodo getTarget(). El bean puede existir dentro del microcontenedor en cualquiera 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, envulvalo en otro objeto llamado un context, el cual describe el estado actual. El nombre del contexto es el mismo que el nombre del bean. Una vez que un contexto alcanza el estado INSTALADO entonces el bean que representa se considera implementado. Despus de crear una referencia a la instancia del bean que representa el punto de entrada del servicio, puede llamar a los mtodos en este para realizar tareas: 24
Acceso directo
El cliente est accediendo el servicio directamente ya que est utilizando una referencia a la instancia del bean real. El rendimiento es bueno ya que cada llamada de mtodo va directamente al bean. Sin embargo, Qu pasa si desea re-configurar el servicio y volver a implementarlo mientras la aplicacin est ejecutando? La re-configuracin se logra realizando cambios al descriptor de implementacin XML y guardando el archivo. Con el fin de volver a implementar el servicio, se debe borrar la implementacin de la instancia actual. Al borrar la implementacin el controlador del microcontenedor libera su referencia a la instancia del bean, junto con los beans dependientes. Posteriormente estos beans se harn disponibles para el servicio de recoleccin de basura ya que la aplicacin ya no los necesita ms. El volver a implementar el servicio crea nuevas instancias del bean representando la nueva configuracin. Cualquier bsqueda posterior de parte de los clientes recuperar las referencias a estas nuevas instancias y podrn volver a acceder el servicio re-configurado. El problema es que la referencia a la instancia del bean que representa nuestro punto de entrada del servicio va al cach cuando implementa el servicio por primera vez. El borrar la implementacin del servicio no tienen ningn efecto ya que la instancia del bean todava se puede acceder usando la referencia en cach y no ir a la basura hasta que el cliente la libere. De la misma manera, el implementar el servicio de nuevo no generar otra bsqueda ya que el cliente ya tiene una referencia en cach. Por lo tanto continuar utilizando la instancia del bean representando la configuracin del servicio inicial. Puebe probar este comportamiento escribiendo u seguido de RETURN para borrar la implementacin del servicio actual. Debe poder acceder el servicio todava desde el cliente aunque haya 'borrado' la implementacin. Luego, realice algunos cambios a la configuracin utilizando el archivo jbossbeans.xml, guarde el archivo y vuelva a implementarlo usando la opcin d. Puede imprimir el estatus del servicio utilizando la opcin p, la cual muestra que el cliente todava est accediendo la instancia inicial del servicio que se implement.
Aviso
Incluso si modifica el cliente para que busque una nueva referencia cada vez que el servicio se vuelve a implementar, es posible que los nuevos desarrolladores entreguen por error copias de esta referencia a otros objetos. Si todas estas referencias no se limpian al volver a realizar la implementacin se puede presentar el mismo problema de cach.
Para volver a implementar el servicio reconfigurado de manera confiable, apague la aplicacin completamente utilizando la opcin 'q' y reincela usando el script run.sh. Para servicios empresariales tal como transacciones, mensajera y persistencia este es un comportamiento completamente aceptable ya que generalmente se utilizan. No se pueden volver a implementar en tiempo de ejecucin y tambin se benefician del alto rendimiento dado por el uso del acceso directo. 25
Captulo 4. Uso de los servicios Si su servicio cae en esta categoria, considere el utilizar el acceso directo por medio del controlador del microcontenedor.
El bus busca la referencia a la instancia del bean nombrado y llama al mtodo seleccionado usando la reflexin. El cliente nunca tiene una referencia directa a la instancia del bean as que se dice que accede al servicio indirectamente. Ya que el bus no pone en el cach la referencia puede realizar de manera segura los cambios a la configuracin del servicio y se puede volver a implementar en tiempo de ejecucin. Las llamadas posteriores por parte del cliente utilizarn la nueva referencia tal como se espera. El cliente y el servicio han sido desvinculados.
Nota
Este comportamiento se puede probar implementado el servicio y utilizando la opcin p para imprimir el estatus. Borre la implementacin del servicio utilizando la opcin u y observe que es inaccesible. Luego realice algunos cambios al archivo jboss-beans.xml, guarde los cambios e implemente de nuevo usando la opcin d. Imprima el estatus de nuevo usando la opcin p. El cliente est accediendo la nueva configuracin del servicio.
Ya que el bus usa la reflecin para llamar instancias del bean, es un poco ms lento que el acceso directo. 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 limpiar y reemplazar con las nuevas. De esta manera, se puede volver a implementar de manera segura 26
Carga de clase dinmica un servicio en tiempo de ejecucin. Los servicios que no se utilizan con tanta frecuencia o que son especificos para ciertas aplicaciones son buenos candidatos para acceso indirect usando el bus del microcontenedor. Con frecuencia la reduccin en el rendimiento es superior a la flexibilidad que proporciona.
Por comodidad las JARs en el directorio lib se agregaron a la extensin de la ruta de clase del cargador de clase usando la propiedad del sistema java.ext.dirs, en lugar de listar la ruta completa para cada una de las JARs despus de la etiqueta -cp. Ya que la extensin classloader es padre de la aplicacin classloader, las clases del cliente pueden encontrar todas las clases del microcontenedor y las clases del servicio de recursos humanos en tiempo de ejecucin.
Nota
Con las versiones de Java 6 y posteriores puede utilizar un comodn para incluir todas las JARs en un directorio con la etiqueta -cp: java -cp `pwd`/lib/*:.:client-1.0.0.jar org.jboss.example.client.Client $1 Aqu todas las clases en la aplicaci se agregarn a la ruta de clase del cargador de clase de la aplicacin y extensin de la ruta de clase del cargador de clase retendr su valor predeterminado.
Qu pasa si necesita implementar un servicio adicional en tiempo de ejecucin? Si el nuevo servicio est empacado en un archivo JAR debe ser visible para un cargador de clase antes de que cualquiera de sus clases puedan ser cargadas. Ya que ya configur la ruta de clase para el cargador de clase de la aplicacin (y el cargador de clase de extensin) en el arranque, no es fcil el agregar la URL de la JAR. La misma situacin aplica si las clases del servicio se encuentran en una estructura de directorio. A menos de que el directorio a nivel superior se encuentre en el directorio actual (el cual est en la ruta de clase de la aplicacin) entonces el cargador de clase de la aplicacin no encoentrar las clases. Si desea volver a implementar un servicio existente cambiando algunas de sus clases, necesita trabajar teniendo en cuenta las restricciones de seguridad, las cuales le impiden a un cargador de clase existente el volver a cargar las clases. La meta es crear un nuevo cargador de clases que conozca la ubicacin de las clases del nuevo servicio o que pueda cargar nuevas versiones de las clases de un servicio ya existente con el fin de implementar los beans del servicio. JBoss Microcontainer usa el elemento <classloader> en el descriptor de implementacin para lograr esto. La distribucin client-cl contiene el archivo listado en el Ejemplo 4.5, Listado del directorio commandLineClient/target/client-cl . 27
|-- 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 llamado otherLib. Ya no est disponible para los cargadores de clase de extensin o de la aplicacin, coya ruta 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 implementacin del servicio, crguela en las clases del servicio y cree instancias de los beans. Para ver cmo se logra esto vea el contenido 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>
28
1.
Primero cree una instancia de java.net.URL llamada URL, usando la inyeccin de parmetros en el constructor para especificar la ubicacion del archivo humanResourcesService.jar en el sistema local de archivos. Luego, cree una instancia de un URLClassLoader inyectando el bean URL en el constructor como nico elemento en el array. Incluya un elemento <classloader> en su definicin de bean HRService e inyecte el bean customCL. Esto especifica que la clase HRManager necesita ser cargada por el cargador de clase customCL.
2. 3.
Necesita una manera de decidir cul cargador de clase utilizar para los otros beans en la implementacin. Todos los beans en la implementacin utilizan el cargador de clase del contexto del hilo actual. En este caso el hilo que maneja la implementacin es el hilo principal de la aplicacin, el cual tiene su cargador de clase de contexto establecido para el cargador de clase de la aplicacin durnate el arranque. Si desea puede especificar un cargador de clase diferente para toda la implementacin utilizando un elemento <classloader> como se puede ver en Ejemplo 4.6, Especificar un 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>
29
... </deployment>
Esto sera necesario para permitir la reconfiguracin del service al borrar los comentarios de los beans AgeBasedSalary o LocationBasedSalary. Los cargadores de clase especificados a nivel del bean sobreescriben el cargador de clase a nivel de la implementacin. Para sobreescribir el cargador de clase a nivel de implementacin y utilizar el cargador de clase predeterminado para un bean, 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 los descriptores de implementacin
Si crea un nuevo cargador de clase para su servicio utilizando el descriptor de implementacin es posible que no pueda acceder las clases cargadas por este desde el cargador de clase de la aplicacin. En el ejemplo HRManager, el cliente ya no puede poner en cach una referencia directa a la instancia del bean al utilizar el controlador del microcontenedor. Para ver este comportamiento inicie el cliente usando el comando run.sh y luego trate de implementar el servicio. Se presenta una excepcin java.lang.NoClassDefFoundError y la aplicacin termina. En este escenario debe usar el bus para acceder el servicio indirectamente y proporcionar acceso a cualquier clase compartida por el cliente en la ruta de clase de la aplicacin. En este ejemplo, las clases afectadas son Address, Employee y SalaryStrategy.
30
Procedimiento 5.1. Creacin del POJO 1. El constructor chequea a ver si hay un directorio log en el directorio actual de trabajo y lo crea si no lo encuentra.
32
Configuracin del microcontenedor para AOP 2. Luego se define un aviso. Se llama a este aviso cuando se llama al constructor de la clase de destino. Esto crea un nuevo archivo de registro dentro del directorio log para registrar la llamadas de mtodos realizadas en diferentes instancias de la clase destino en archivos separados. Finalmente se define otro aviso. Este aviso aplica a cada llamada de mtodo realizada en la clase destino.El nombre del mtodo y los argumentos se almacenan junto con el valor de retorno. Esta informacin se utiliza para construir un registro de auditora y escribirlo en el archivo de registro actual. Cada aviso llama a inv.invokeNext(), el cual encadena los avisos si se ha aplicado ms de un asunto de corte transversal o para llamar el constructor/mtodo destino.
3.
Nota
Cada aviso se implementa utilizando un mtodo que toma un objeto de invocacin como parmetro, presenta Throwable y retorna Object. En el momento del diseo no se sabe a qu constructores o mtodos se aplicarn estos avisos as que haga los tipos tan genricos como sea posible.
Para compilar la clase y crear un archivo auditAspect.jar que lo puedan utilizar otros ejemplos, escriba mvn install desde el directorio auditAspect.
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-`-|-`-`--
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
33
Captulo 5. Agregar comportamiento con AOP Primero, se necesita lib/auditAspect-1.0.0.jar para crear una instancia del aspecto en tiempo de ejecucin con el fin de ejecutar la lgica. Luego el archivo jar para JBoss AOP (jbossaop.jar) junto con sus dependencias javassist y trove, agrega la funcionalidad AOP. Finalmente, se necesita la jar jboss-aop-mc-int ya que contiene una definicin de esquema XML que le permite definir aspectos dentro de un descriptor de implementacin XML. Tambin contiene cdigo de integracin para crear dependencias entre beans normales y beans de aspecto dentro del microcontenedor, permitindole agregar comportamiento durante las fases de implementacin y de borrado de la implementacin. Ya que est utilizando Maven2 para montar la distribucin cliente-aop, debe agregar estos archivos JAR declarando las dependencias apropiadas en su archivo pom.xml y creando un descriptor de ensamblaje vlido. Puede ver un ejemplo de pom.xml en Ejemplo 5.3, Extracto de ejemplo pom.xml para AOP. Para realizar su construccin 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>
34
Aplicacin de un aspecto
... </deployment>
Procedimiento 5.2. Explicacin del cdigo para aplicar un aspecto 1. 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 mtodo de fbrica en lugar de llamar un constructor convencional ya que solo es necesario una instancia del AspectManager en la MVJ en tiempo de ejecucin. 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 class que se utilizan de la misma manera. Sin embargo, tambin tiene los atributos method y pointcut que puede utilizar para aplicar o enlazar un consejo dentro del aspecto para los constructores y mtodos dentro de otras clases. Estos atributos enlazan el consejo de auditora a todos los constructores y mtodos pblicos dentro de la clase HRManager. Slo es necesario especificar el mtodo audit ya que ha sido sobrecargado dentro de la clase AuditAspect con diferentes parmetros. JBoss AOP sabe cul seleccionar en tiempo de ejecucin dependiendo de si se est realizando una invocacin de mtodo o constructor.
Esta configuracin adicional es todo lo que se necesita para aplicar el aspecto de auditora en tiempo de ejecucin agregando un comportamiento de auditora al servicio Human Resources. Puede probar esto ejecutando el cliente utilizando el script run.sh. Se crea un directorio log al iniciar junto con el directorio lib cuando el microcontenedor crea el bean AuditAspect. Cada implementacin del servicio de recursos humanos hace que aparezca un nuevo archivo de registros dentro del directorio log. El archivo de registro contiene un registro de las llamadas realizadas del cliente al servicio. Se llama algo como auditLog-28112007-163902 y contiene salidas similares a Ejemplo 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 auditora, comente los fragmentos relevantes de XML en el descriptor de implementacin y re-inicie la aplicacin.
35
Aviso
El orden de la implementacin s importa. Especificamente cada aspecto debe ser declarado antes 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 cdigo byte de la clase bean para agregar la lgica cross-cutting, antes de crear una instancia y almacena una referencia a esta en el controlador. Si ya se ha creado una instancia normal del bean entonces no es posible.
Importante
Los estados CREATE y START estn includos por razones de legado. Esto le permite a los servicios que estaban implementados como MBeans en versiones anteriores de la plataforma empresarial el funcionar correctamente cuando se implementan como beans en la plataforma empresarial 5.1. Si no define ningn mtodo crear/inicar correspondientes en su bean, pasar derecho por estos estados.
36
Callbacks del ciclo de vida Estos estados representan el ciclo de vida del bean. Puede definir un nmero de callbacks para que se 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 atributos name y class. El microcontenedor usa estos atributos para crear una instancia de la clase callback, nombrndola de manera que se pueda utilizar cuando los beans entren o salgan del estado relevante durante la implementacin y durante el borrado de la implementacin. Puede especificar cules beans son afectados por el callback utilizando el atributo clases como se puede ver en Ejemplo 5.5, Uso del atributo 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 cdigo especifica que la lgica adicional en la clase lifecycleCallback se aplica a cualquier clase de bean que est anotada con @org.jboss.test.microcontainer.support.Install antes de que entren y luego de que han dejado el estado INSTALLED. Para que la clase callback funcione, debe contener los mtodos install y uninstall que toman ControllerContext como parmetro, como se puede ver en Ejemplo 5.6, Mtodos de instalacin y desinstalacin. Ejemplo 5.6. Mtodos de instalacin y desinstalacin
import org.jboss.dependency.spi.ControllerContext; public class LifecycleCallback { public void install(ControllerContext ctx) {
37
El mtodo install se llama durante la implementacin del bean y se llama al mtodo uninstall durante el borrado de la implementacin.
Nota
Aunque se est agregando comportamiento al proceso de implementacin y de borrado de la implementacin utilizando callbacks, AOP de ehcho no se utiliza aqu. La funcionalidad pointcut expression de JBoss AOP se utiliza para determinar a cules clases bean se aplican los comportamientos.
El entregar referencias del kernel a todos los clientes que buscan un servicio es un riesgo de seguridad ya que proporciona un amplio acceso a la configuracin del microcontenedor. Para mayor seguridad aplique el patrn ServiceLocator y utilice una clase para realizar bsquedas de parte de los clientes. Incluso puede pasar las referencias del bean junto con sus nombres al ServiceLocator en el momento de la implementacin utilizando un callback del ciclo de vida. En ese escenario, el ServiceLocator puede buscarlos sin llegar a saber del microcontenedor. El borrado de la 38
Agregar bsquedas de servicios por medio de JNDI implementacin posteriormente borrara las referencias del bean del ServiceLocator para evitar ms bsquedas. No sera dificil es escribir su propia implementacin ServiceLocator. En integrar una ya existente tal como JBoss Naming Service (JBoss NS) es incluso ms rpido y tiene el beneficio adicional de cumplir con la especificacin de JNDI - Java Naming and Directory Interface. JNDI habilita a los clientes para acceder diferentes y posiblemente mltiples servicios de nombrado utilizando una API comn. Procedimiento 5.3. Escritura de su propia implementacin ServiceLocator 1. Primero cree una instancia de JBoss NS usando el microcontenedor. 2. 3. 4. Luego, agregue un callback del ciclo de vida para realizar el enlace y des-enlace de las referencias bean durante la implementacin y durante el borrado de la implementacin. Marque las clases bean a las que desea enlazar sus referencias, utilizando anotaciones. Ahora puede ubicar los beans en tiempo de ejecucin utilizando la expresin como se mostr anteriormente.
39
40
Modelos de componentes
El JBoss Microcontainer funciona dentro de varios modelos de componentes POJO populares. Los componentes son programas de software re-utilizables que puede desarrollar y ensamblar fcilmente para crear aplicaciones sofisticadas. Una de las metas clave del microcontenedor es la integracin efectiva con estos modelos de componentes. Algunos modelos de componentes populares que se pueden utilizar con el microcontenedor son JMX, Spring y Guice.
43
El espacio de nombre del archivo es diferente del archivo del bean del microcontenedor. El espacio de nombre urn:jboss:spring-beans:2.0 apunta a su versin del puerto del esquema Spring, el cual describe el estilo Spring de su bean. El microcontenedor implementa los beans a manera opuesta de la nocin de fbrica 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 la implementacin de la interfaz BeanNameAware, su nico propsito es exponer e imitar algo del comportamiento del callback de Spring.
44
Uso de Guice con el microcontenedor Dos partes importantes de observar en este archivo son PojoModule y GuiceKernelRegistryEntryPlugin. PojoModule configura sus beans tal como en Ejemplo 6.5, Configuracin de Beans para Guice. GuiceKernelRegistryEntryPlugin proporciona integracin con el microcontenedor tal como se puede ver en Ejemplo 6.6, Integracin mock con el microcontenedor. Ejemplo 6.5. Configuracin 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")); } }
45
Nota
Se crea un Injector desde la clase Modules luego realiza una bsqueda en este para ver si hay beans que coincidan. Consulte Seccin 6.5, MBeans de legado y mezcla de diferentes modelos de componentes para encontrar mayor informacin sobre la declaracin y uso de MBeans de legado.
Para implementar MBeans por medio del microcontenedor debe escribir un manejador nuevo por completo para el modelo de componentes. Consulte system-jmx-beans.xml para obtener mayores detalles. El cdigo de este archivo se encuentra en el cdigo fuente del servidor de aplicaciones JBoss: sub-proyecto system-jmx.
46
Este descriptor presenta un POJO existente como un MBean y lo registra en un servidor MBean. Para exponer un POJO como un MBean finalcelo con una anotacin @JMX asumiendo que ha importado org.jboss.aop.microcontainer.aspects.jmx.JMX. El bean se puede exponer directamente o en su propiedad. Ejemplo 6.9. Presentacin 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 bsqueda de inyeccin ya sea buscando un POJO simple u obteniendo un MBean del servidor MBean. Una de las opciones de inyeccin es utilizar la inyeccin de 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>
47
Captulo 6. Modelos de componentes El bean FromGuice inyecta el bean Guice por medio de la correspondencia de tipos, en donde PlainPojo se inyecta con una inyeccin de nombres comn. Ahora puede probar a ver si el enlace Guice funciona como se esperaba como se puede ver en Ejemplo 6.11, Prueba de la funcionalidad de 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 componentes alias. El alias es una funcionalidad trivial pero necesaria. Se debe introducir como un modelo nuevo de componentes dentro del microcontenedor con el fin de implementarlo como una dependencia verdadera. Los detalles de la implementacin se pueden ver en Ejemplo 6.12, Cdigo fuente de AbstractController. Ejemplo 6.12. Cdigo 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 aliases como verdaeros modelos de componentes es que el momento de la implementacin del bean se vuelve menos importante. El alias espera en un estado no-instalado hasta que el bean real lo dispara.
48
49
Captulo 7. Inyeccin avanzada de dependencias y ldC Ejemplo 7.2, PortsConfig muestra la manera en que el bean PortsConfig usa el bean de enlace para obtener sus valores por medio de la invocacin del mtodo 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. Callbacks
El descriptor que se puede ver en Ejemplo 7.3, Callbacks para reunir y filtrar beans le permite reunir todos los beans de un cierto tipo e incluso limitar el nmero de beans que coincidan. Junto con el descriptor en Ejemplo 7.3, Callbacks para reunir y filtrar beans, el cdigo Java que se puede ver en Ejemplo 7.4, Un analizador sintctico para reunir todos los editores muestra un Parser, 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"/>
50
Observe que incallback y uncallback usan el nombre del mtodo para buscar.
<incallback method="addEditor" cardinality="4..n"/> <uncallback method="removeEditor"/>
Un lmite inferior controla cuntos editores de hecho hacen que el bean progrese de un estado configurado: cardinality=4..n/> Eventualmente se crea Checker y corrige el analizador sintctico. Esto se ilustra en Ejemplo 7.5, El corrector para el analizador sintctico. Ejemplo 7.5. El corrector para el analizador sintctico
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); }
51
Aqu un valor de cadena se configura como un campo de cadena privado: Ejemplo 7.7. Configuracin de BeanAccessMode
<bean name="FieldsBean" class="org.jboss.demos.ioc.access.FieldsBean" access-mode="ALL"> <property name="string">InternalString</property> </bean>
52
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 con anotaciones 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(); } }
53
public class SimpleExecutor implements Executor { private static Random random = new Random(); public void execute() throws Exception { Thread.sleep(Math.abs(random.nextLong() % 101)); } }
Despus de agregar los beans invocadores del ejecutor, puede ver los ejecutores en accin durante el 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. Autowire
Autowiring o la inyeccin contextual, es una funcionalidad comn con con marcos de trabajo IdC. Ejemplo 7.14, Incluir y excluir con autowiring le muestra cmo utilizar o excluir beans con autowiring. Ejemplo 7.14. Incluir y excluir con autowiring
<bean name="Square" class="org.jboss.demos.ioc.autowire.Square" autowirecandidate="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"/>
54
Fbrica de beans En ambos casos - ShapeUser y ShapeChecker - solo Circle se debe utilizar ya que Square se excluye en el enlace contextual.
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
55
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) { } }
56
ClassLoader personalizado Utilizando este concepto no expone su cdigo a ninguno de los detalles de implementacin del microcontenedor.
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"); } }
Ejemplo 7.19, Prueba del cargador de clase personalizado muestra una prueba para verificar que el bean 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 {
57
Nota
Usando el atributo fromContext de la clase inject puede inyectar beans as como su representacin de componentes del microcontenedor inmodificables.
Revise el cdigo de OptionalServiceUser y ManualServiceUser para ver cmo se utiliza la API del microcontenedor para el manejo de beans ON_DEMAND y MANUAL.
7.11. Ciclo
Los beans pueden depender entre ellos en un ciclo. Por ejemplo, A depende de B en la construccin, pero B depende de A durante la configuracin. Debido a la separacin del ciclo de vida del estado detallado del microcontenedor, este problema se puede resolver fcilmente.
58
Oferta y demanda
7.13. Instalaciones
A medida que el bean se mueve a travs de diferentes estados es posible que quiera invocar algunos mtodos en otros beans o en el mismo bean. Ejemplo 7.23, Invocacin de mtodos en diferentes estados muestra cmo Entry invoca a los mtodos add y removeEntry del RepositoryManager pararegistrar y desregistrarse a s mismo. Ejemplo 7.23. Invocacin de mtodos 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>
59
60
61
Tambin hay muchos problemas con el bloqueo de archivos en los sistemas Windows, lo cual ha forzado a los desarrolladores a copiar todos los ficheros de implementacin en vivo a otra ubicacin para prevenir el bloqueo de aquellos que se encuentran en las carpetas de implementacin (lo cual evitara el borrarlos y el borrado de la implementacin con base en el sistema de archivos). El bloqueo de archivos es un problema importante, cuya nica solucin sola ser el centralizar todo el cdigo de carga de recursos en un lugar. El proyecto VFS se cre para resolver todos estos problemas. VFS son las siglas en ingles de Virtual File System - sistema virtual de archivos.
62
63
64
65
Todas las operaciones del sistema de archivos de slo lectura estn disponibles adems de unas pocas opciones para limpiar o borrar el recurso. El manejo de la limpieza o el borrado se necesita al tratar con algunos archivos internos temporales tal como archivos creados para manejar jars anidadas. Para cambiar el manejo de recursos File o URL de JDK al nuevo VirtualFile necesita un VirtualFile raz, el cual los proporciona la clase VFS con la ayuda de la URL o el parmetro 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
66
Los tres mtodos diferentes se ven similares. getVFS createNewRoot getRoot getVFS retorna una instancia VFS pero todava no crea una instancia VirtualFile. Esto es importante ya que hay mtodos que ayudan con la configuracin de una instancia VFS (consulte la clase VFS API javadocs) antes de ordenarle que cree una raz VirtualFile. Por otro lado, los otros dos mtodos usan configuraciones predeterminadas para la creacin de root. La diferencia entre createNewRoot y getRoot es en los detalles de cach, los cuales abordaremos ms adelante. Ejemplo 8.4. Uso de getVFS
URL rootURL = ...; // get root url VFS vfs = VFS.getVFS(rootURL); // configure vfs instance VirtualFile root1 = vfs.getRoot(); // or you can get root directly VirtualFile root2 = VFS.crateNewRoot(rootURL); VirtualFile root3 = VFS.getRoot(rootURL);
Otra cosa til de la API VFS es su implementacin de un patrn visitante apropiado. Es muy simple el reunir recursos de manera recursiva, una tarea dificil de realizar con la carga de recursos JDK simple. Ejemplo 8.5. Reunin de recursos de manera recursiva
public interface VirtualFileVisitor { /** * Get the search attribues for this visitor * * @return the attributes */ VisitorAttributes getAttributes(); /**
67
68
Ganchos de extensin Otra implementacin son los archivos en-memoria. Esta implementacin surgi de la necesidad de manejar fcilmente bytes generados por AOP. En lugar de utilizar archivos temporales, puede poner bytes en VirtualFileHandlers en la memoria. Ejemplo 8.7. Implementacin de VirtualFileHandlers en memoria
URL url = new URL("vfsmemory://aopdomain/org/acme/test/Test.class"); byte[] bytes = ...; // some AOP generated class bytes MemoryFileFactory.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.5. Funcionalidades
Uno de los problemas principales que los desarrolladores del microcontenedor enfrentaron fue el uso apropiado de los recursos anidados, ms 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 opcin es ms fcil de implementar, pero consume mucha memoria, lo cual requiere potencialmente que las aplicaciones grandes residan en la memoria. El otro enfoque deja atrs un gran nmero de archivos temporales, los cuales deben ser invisibles para el usuario y por lo tanto deben desaparecer despus del borrado de la implementacin. Considere el siguiente escenario: un usuario accede uns intstancia URL VFS, la cual apunta a algun recurso anidado. La manera en que el VFS simple manejara esto es re-creando toda la ruta desde el principio: desempacara los recursos anidados y de nuevo. Esto crea un gran nmero de archivos temporales. El microcontenedor evita esto utilizando VFSRegistry, VFSCache y TempInfo. Cuando solicita VirtualFile sobrer VFS (getRoot no createNewRoot), VFS le pide a la implementacin VFSRegistry que proporcione el archivo. El DefaultVFSRegistry existente primero chequea si extiste un VFSContext raz que coincida para la URI dada. Si s existe entonces DefaultVFSRegistry primero trata de navigar al TempInfo existente (enlace a un archivo temporal), regresando a la navegacin normal si no existe dicho archivo temporal. De esta manera reutiliza completamente cualuqier archivo temporal que ya hayan sido desempacados, ahorrando 69
Captulo 8. El sistema virtual de archivos tiempo y espacio en el disco. Si no se encuentra un VFSContext que coincida en el cach entonces el cdigo crear una nueva entrada VFSCache y continuar con la navegacin predeterminada. El determinar la manera en que el VFSCache maneja las entradas VFSContext en cach depende de la implementacin utilizada. VFSCache es configurable por medio de VFSCacheFactory. Por defecto, nada va en el cach, pero hay unas pocas implementaciones VFSCache tiles existentes, utilizando algoritmos tal como Least Recently Used (LRU) o timed cache.
70
La capa ClassLoading
JBoss siempre ha tenido una manera nica de tratar con la carga de clase y la nueva capa classloading que viene junto con el microcontenedor no es la excepcin. ClassLoading es una funcionalidad agregada que puede utilizar cuando prefiera la carga de clase no predeterminada. Con una mayor demanda por la carga de clase de estilo OSGi y un nmero de especificaciones nuevas de carga de clase Java en el horizonte, los cambios a la capa ClassLoading de EAP 5.1 son tiles y muy oportunos. La capa ClassLoading del microcontenedor es una capa de abstraccin. La mayora de los detalles se esconden detrs de mtodos privados y de paquetes privados sin comprometer la extensibilidad y funcionalidad disponibles por medio de las clases y mtodos pblicos que hacen el API. Esto significa que usted escribe cdigo frente a la poltica 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 extensin java.lang.ClassLoader personalizada sin ninguna poltica de carga de clase especfica. Una poltica de carga de clase incluye el saber desde dnde carga y cmo cargar. Classloading es una extensin de los mecanismos de dependencia del microcontenedor. Su implementacin respaldada por VFS es classloading-vfs. Consulte Captulo 8, El sistema virtual de archivos para obtener mayor informacin sobre VFS.
9.1. ClassLoader
La implementacin ClassLoader soporta polticas enchufables y es una clase final, se supone que no se debe alterar. Para escribir sus propias implementaciones ClassLoader, escriba una ClassLoaderPolicy, la cual proporciona una API ms simple para ubicar las clases y recursos y para especificar otras reglas asociadas con el cargador de clase. Para personalizar la carga de clase, instance una ClassLoaderPolicy y regstrela con un ClassLoaderSystem para crear un ClassLoader personalizado. Tambin puede crear un ClassLoaderDomain para realizar la particin en el ClassLoaderSystem. La capa ClassLoader tambin incluye la implementacin de cosas como el modelo DelegateLoader, la carga de clase, filtros de recursos y polticas de delegacin padre-hijo. El tiempo de ejecucin est habilitado para JMX para exponer la poltica utilizada para cada cargador de clase. Tambin proporciona estadsticas de carga de clase y mtodos de depuracin para ayudar a determinar desde dnde se cargan las cosas. Ejemplo 9.1. La clase ClassLoaderPolicy La ClassLoaderPolicy controla la manera en que funciona la carga de clase.
public abstract class ClassLoaderPolicy extends BaseClassLoaderPolicy { public DelegateLoader getExported() public String[] getPackageNames()
71
Los siguientes dos ejemplos de ClassLoaderPolicy. El primero recupera los recursos con base en expresiones 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; }
72
ClassLoader
} 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)
73
RegexpClassLoaderPolicy usa un mecanismo simplistico para encontrar los recursos que coinciden. Las implementaciones del mundo real seran ms 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 patrn de la expresin regular config/[^.]+\\.[^.] {1,4} para listar los recursos bajo el directorio config// . La longitud del sufijo es limitado de tal manera que los nombres de archivos tal como excluded.properties se ignorarn. Ejemplo 9.3. ClassLoaderPolicy con soporte para codificacin
public class CrypterClassLoaderPolicy extends VFSClassLoaderPolicy { private Crypter crypter;
74
ClassLoader
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 codificacin muestra cmo encriptar JARs. Puede configurar cules recursos codificar especificando un filtro apropiado. Aqu todo est encriptado a excepcin 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");
75
Este servicio imprime el contenido de dos archivos de configuracin. Muestra que se esconde la decodificacin de cualquier recurso encriptado detrs de la capa de carga de clase. Para probar esto apropiadamente puede encriptar el mdulo de poltica usted mismo o puede utilizar uno que ya est encriptado. Para poner esto en accin es necesario que uan apropiadamente EncryptedService con ClassLoaderSystem y los programas de implementacin. Ms adelante en este captulo abrodamos el particionamiento del ClassLoaderSystem.
9.2. ClassLoading
En lugar de utilizar la abstraccin ClassLoader directamente puede crear mdulos ClassLoading, los cuales contienen declaraciones de dependencias ClassLoader. Una vez se especifican las dependencias se construyen las ClassLoaderPolicys y se conectan de manera respectiva. Para facilitar la definicin de los ClassLoaders antes de que existan, la abstraccin incluye un modelo ClassLoadingMetaData. El ClassLoadingMetaData se puede presentar como un objeto administrado dentro del nuevo servicio de perfil JBoss EAP. Esto le ayuda a los administradores de sistemas a tratar con los detalles de la poltica abstracta en lugar de los detalles de la implementacin. 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;
76
ClassLoading
/** 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"/>
Puede agregar ClassLoadingMetaData a su implementacin ya sea programticamente o declarativamente 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"
77
El DefaultDomain se comparte entre todas las aplicaciones que no definen sus propios dominios. Ejemplo 9.8. Aislamiento tpico a nivel de dominio
<classloading xmlns="urn:jboss:classloading:1.0" domain="IsolatedDomain" export-all="NON_EMPTY" import-all="true"> </classloading>
Las implementaciones .war usan este mtodo por defecto. En lugar de realizar buqeudas de padres primero por defecto primero chequea sus propios recursos. Ejemplo 9.11. Implementacin tpica 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-Grained Packages
<classloading xmlns="urn:jboss:classloading:1.0"> <requirements> <module name="jboss-reflect.jar"/> </requirements>
78
ClassLoading
<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>
Tambin puede mezclar los requerimientos y los tipos de funcionalidades usando paquetes y mdulos. El sub-proyecto de carga de clase usa una implementacin muy pequea del patrn recurso-visitante. En el proyecto ClassLoader, la conexin entre implementacin y carga de clase se realiza por medio de la clase Module, la cual mantiene toda la informacin requerida para aplicar restricciones apropiadamente en el patrn 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 mdulo, instancie su instancia ResourceVisitor y psela al mtodo Module::visit. Esta funcionalidad se utiliza en el marco d etrabajo de la implementacin para indexar los usos de anotacions en las implementaciones. 79
La clase VFSClassLoaderFactory transforma el programa de implementacin XML en un VFSClassLoaderPolicyModule, el cual luego crea la instacia real del ClassLoader. Luego puede utilizar directamente esta nueva instancia ClassLoader con sus beans.
Nota
VFSClassLoaderFactory extiende ClassLoadingMetaData as que todos los ejemplos relacionados con ClassLoadingMetaData aplican en este caso tambin.
80
10.2. Separacin del reconocimiento de la estructura de la lgica del ciclo de vida de la implementacin
Con el fin de realizar cualquier trabajo real encima de una implementacin primero debe comprender su estructura incluyendo sus rutas de clase y la ubicacin de sus metadatos. La ubicacin de los metadatos incluye los archivos de configuracin tal como my-jbossbeans.xml, web.xml, ejb-jar.xml. Las rutas de clase son races del cargador de clase tal como WEB-INF/classes o myapp.ear/lib. Teniendo esta estructura en mente puede proceder al manejo de la implementacin. Ciclo de vida de una implementacin tpica 1. El MainDeployer le pasa la implementacin al grupo de StructuralDeployers para un reconocimiento y recibe un contexto de implementacin. 2. Luego, el MainDeployer le pasa el contexto de implementacin que resulta a los Deployers para que el Deployer apropiado lo maneje. De esta manera, el MainDeployer es un agente con la responsibilidad de decidir qu programas de implementacin utilizar. En el caso de una implementacin virtual o programtica, una informacin StructureMetaData predeterminada ya existente lee la informacin de la estructura y la maneja de una de las maneras que se explic en Manejo de la informacin StructuredMetaData. Manejo de la informacin StructuredMetaData Implementaciones basadas en VFS el reconocimiento de la estructura se re-enva a un grupo de StructureDeployers. estructuras definidas de la especificacin JEE tenemos implementaciones StructureDeployer que coinciden: EarStructure 81
Captulo 10. Marco de trabajo de la implementacin virtual WarStructure JarStructure DeclarativeStructures busca el archivo META-INF/jboss-structure.xml dentro de su implementacin y lo analiza sintcticamente para construir un StructureMetaData apropiado. FileStructures solo reconoce los archivos de configuracin 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 implementacin a nivel superior y luego procese recursivamente las sub-implementaciones. Puede implementar un StructureDeployer personalizado con la ayuda de la clase genrica GroupingStructure proporcionada por la interfaz genrica StructureDeployer. Despus de tener una estructura de implementacin reconocida se la puede pasar a los programas de implementacin reales. El objeto Deployers sabe cmo encargarse de los programas de implementacin reales, utilizando una cadena de programas de implementacin por DeploymentStage. Ejemplo 10.2. Etapas de la implementacin
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 */
82
La etapas de implementacin pre-existentes se mapean a los estados del controlador incorporado del microcontenedor. Proporcionan una vista cntrica del ciclo de vida de la implementacin de los estados del controlador genrico. Dentro de los programas de implementacin, la implementacin se convierte en el componente DeploymentControllerContext del microcontenedor. La mquina de estado del microcontenedor maneja las dependencias. Las implementaciones se manejan secuencialmente por etapa de implementacin. Para cada porgrama de implementacin se maneja todo el orden de la jerarqua implementada usando la propiedad parent-first del programa de implementacin. Esta propiedad se configura como true por defecto. Tambin puede especificar los niveles de jerarqua que el programa de implementacin 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 las dependencias tambin aplica aqu. Si hay dependencias no resueltas entonces la implementacin empezar en el estado actual, potencialmente reportando un error si el estado actual no es el estado requerido. El agregar un nuevo programa de implementacin se logra extendiendo uno de los muchos programas de implementacin de ayuda que existen. Algunos programas de implementaciin de hecho necesitan una implementacin respaldada por VFS mientras que otros pueden utilizar una implementacin general. En la mayora de los casos los programas de instalacin de anlisis sintctico son los que necesitan respaldo de VFS.
Aviso
Tambin tenga en cuenta que los programas de implementacin ejecutan recursivamente en toda implementacin, sub-implementacin y componentes. Su cdigo necesita determinar tan pronto como sea posible en el proceso, si el programa de implementacin debe manejar la implementacin actual o no.
Ejemplo 10.3. Programa de implementacin simple, el cual presenta informacin sobre su implementacin
public class StdioDeployer extends AbstractDeployer {
83
Agregue esta descripcin 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 de implementacin por medio del manejo callback loC del microcontenedor. Ejemplo 10.4. Descriptor de implementacin simple
<bean name="StdioDeployer" class="org.jboss.acme.StdioDeployer"/>
Aviso
Aunque se soporta el ordenamiento relativo, este se considera como mala prctica y es posible que no haya soporte para este en lanzamientos futuros.
84
Note las llamadas artificiales en el XML: (1) y (2). (1) muestra cmo describir la dependencia en otro servicio. Este ejemplo requiere el crear un TransactionManager antes de que la implementacin se encuentre en la etapa 'real'. (2) es un poco ms complejo ya que le falta informacin adicional. Por defecto, los nombres de las implementaciones dentro del microcontenedor son nombres URI, lo cual hace que el escribirlos a mano sea un proceso propenso a errores. As que con el fin de declarar dependencias fcilmente en otras implementaciones, necesita un mecanismo de alias para evitar nombres URI. Puede 85
Captulo 10. Marco de trabajo de la implementacin virtual agregar un archivo de texto simple llamado aliases.txt en su implementacin. Cada lnea del archivo contiene un alias, dndole al fichero de implementacin uno o ms nombres simples utilizados para referirse a este.
Este ejemplo muestra una descripcin simple de rutas relativas para incluir o excluir cuando se escanea en busca de informacin de metadatos anotados para Java Enterprise Edition versin 5y posteriores.
86
87
88