701 86 53MB
Spanish Pages [1206]
Sobre 10s autores Subrahmanyam Allamaraju Subrahmanyam Allamaraju es Ingeniero y trabaja desde hace afios para BEA Systems Inc. Trabaja en las ireas de tecnologias de empresa/distribuidas, modelos de objeto basados en XML y otras ireas relacionadas. Si desea mis informaci6n sobre sus actividades, inquietudes y otros trabajos, consulte su pigina Web enwww.Subrahmanyarn.com. Subrahmanyam desearia dar las gracias a Varaa por su colaboraci6n en las pruebas de c6digo (enfrentindose a estrictos plazos) y por compartir su frustration y su euforia.
Cedric Beust Cedric Beust es ingeniero de software y trabaja para el equipo de EJB en BEA Systems Inc. H a participado en la puesta en marcha de la versi6n 2.0 del contenedor WebLogic EJB. Doctorado en Informitica por la Universidad de Niza, Francia. Antes de doctorarse. trabai6 , Dara Sun Microsvstems donde se centr6 principalmente en CORBA. A lo largo de 10s aiios,'~edricha participado en diversas comisiones dedicadas, Sus intereses abarcan desde todo lo relacionado con la informitica por ejemplo, a EJB, CORBA y C + distribuida y la ingenieria de software en general, hasta aficiones como el golf, el squash, el tenis y el voleibol.
.
+.
John Davies John Davies trabaja como Director Jefe de Tecnologia ( C T O ) para Century 24 Solutions Ltd. (C24), www.C24Solutions.corn, una compafiia de software con sede en Londres que ofrece soluciones basadas en Java y J2EE para el mercado financiero. El ultimo product0 de C24, Elektra, disefiado para proporcionar una unica visi6n de las transacciones financieras complejas, hace extensivo el uso de todas las tecnologias J2EE. John esti embarcado en la actualidad en el proyecto de BNP-Paribas a la cabeza del grupo Technology Consulting Grup, recornendando el uso de tecnologias para proyectos actuales y futuros de todo el mundo. John comenzo en el mundo de las tecnologias de la informaci6n a finales de 10s setenta trabajando en el area de hardware, mis tarde en ensambladores, en C , C + + en el afio 87 y finalmente en Java desde principios del 96. Trabaj6 durante catorce afios como asesor principalmente en el sector bancario. Diez de estos afios 10s pas6 fuera del Reino Unido en diversos paises, incluido Estados Unidos, Asia y gran parte de Europa, donde aprendi6 a hablar algunos idiomas. En el tiempo que le queda libre entre su trabajo y escribir, John imparte clases de Java y XML para Learning Tree y es editor ttcnico de su curso de EJB 2.0. Sus aficiones incluyen viajar, la fotografia, la guitarra clisica, pilotar avionetas, el buen vino, la buena cerveza, la comida picante y socializar. John quisiera dar las gracias a su compaiiero licenciado en Astronomia Steve Miller por corregir sus trabajos y le gustaria saludar a su madre y pedirle perd6n por lo ma1 que se comport6 en el colegio.
Una vez ma's, nada de esto hubiera sido posible sin el carilio y el apoyo de m i fantastica esposa Rachel, Siento mucho las noches que te ha tocado pasar sola y gracias por L u c y James, os quiero Puede ponerse en contact0 con en [email protected].
Tyler Jewell Tyler Jewell trabaja corno "predicador" para BEA Systems Inc., donde escribe y alaba sobre las tecnologias de empresa para programadores. Es un experto preparador y mentor, especializado en arquitecturas a gran escalade e-business. Tyler es el autor de 19 cursos de preparacion sobre tecnologias de e-business y ha impartido mis de 200 seminarios sobre tecnologia a clientes y public0 en general. Es co-autor del libro Mastering Enterprise
JavaBeans 2.0 (O'Reilly 2001) y en la actualidad trabaja en el proyecto Java Web Services (O'Reilly 2002). Tyler mantiene una columna habitual sobre J2EE en www.onjava.com, es miembro de la editorial O'Reilly's Editorial Masthead y es asesor de la pigina www.theserverside.com, Tu Comunidad J2EE. Tyler dedica su tiempo libre a su familia y amigos. Su afici6n favorita es el pdquer Texas Hold 'Em en el que dos cartas cualquiera pueden ganar, per0 siempre que caigan en sus manos.
Rod Johnson Rod Johnson es arquitecto de Java de empresa especializado en aplicaciones Web reajustables. Ha pasado 10s dos dltimos arios diseriando una soluci6n J2EE para FT .corn, el portal de empresa mis grande Europa y en la actualidad esti escribiendo un libro para Wrox Press sobre diserio y desarrollo de J2EE. Despues de sus estudios, en 10s que se especializ6 en musica e informitica, Rod r e a h 6 un doctorado en musicologia antes de volver a dedkarse a1 desarrollo de software. Rod ha trabajado con Java tanto en ireas de cliente como en ireas de senidor desde su lanzamiento y se ha centrado en el desarrollo de Internet desde 1996. Su principal inter& es la arquitectura JZEE, EJB y el desarrollo Web 00. Rod reparte su tiempo entre Londres y Sydney, y le gusta el tenis, el esqui, la historia y tocar el piano. Puede ponerse en contacto con el en [email protected].
Gracias a Keriy por su amor y su apoyo, ahora que comenzamos nuestra nueva aventura.
Andy Longshaw Andy Longshaw es asesor independiente, escritor y educador especializado en JZEE, XML, tecnologias y componentes de base Web, en particular en las decisiones de diserio y arquitectura necesarias para utilizar estas tecnologias satisfactoriamente. Andy ha estado explicando tecnologia durante la mayor parte de la ultima decada en sus funciones principales de Director de Tecnologia de Content Master Ltd. y Q A Training. Tambien ofrece conferencias sobre JZEE, XML y arquitecturas de componentes de grada media. Circula un rumor sin confirmar que dice que algunas personas consiguen no dormirse durante estas sesiones. Esti dispuesto a responder a cualquier comentario, pregunta o critica sobre el capitulo de diserio que ha escrito para este libro en la pigina www.blueskyline.com.
A Sarah, Adam y Joshua que son la inspiracidn de todo lo que hago, y a rnis padres que se aseguraron de que yo recibiera una educacidn lo suficientemente buena como poder escribir este libro.
Ramesh Nagappan Ramesh Nagappan es Arquitecto de Tecnologia especializado en Java y en arquitecturas de aplicacidn de distribucidn de base CORBA. Es un predicador de Java y tambien un activo contribuyente a las especificaciones e implementaciones de fuente abierta. Antes de enpncharse a Java y a CORBA, trabaj6 como ingeniero de Investigacidn para desarrollar soluciones CAD/CAM y de dinimica de fluidos computational para aplicaciones aeroespaciales. En su tiempo libre le gusta disfrutar de 10s deportes de agua y jugar con hijo Roger. Puede encontrarle en su direcci6n de correo [email protected]. ils
Dedicado a mi esposa Joyce y a nuestro hijo Roger, por su carifio, apoyo e inspiracidn, y tambie'n a rnis queridos padres por alegrar m i vida.
Dr. P. G. Sarang Como contratista de Sun Microsystems, el Dr. Sarang forma a 10s clientes de la compafiia con diversos cursos del programa oficial de Sun. Tambien dirige el programa "Formar a formadores" y las "Pruebas de autorizacidn de instructores" en representacidn de Sun.
Como Director Jefe Ejecutivo ( C E O ) de A B C O M Information Systems Pvt. Ltd, el Dr. Sarang esti especializado en formacidn y en el desarrollo de proyectos sobre la plataforma Java/CORBA. Con casi 20 aiios de experiencia en el sector, el Dr. Sarang ha desarrollado diversos productos y ha completado con Cxito varios proyectos industriales. Es orador habitual en muchas conferencias de Lmbito nacional e internacional y contribuye regularmente con articulos tecnicos a la edicidn de revistas y diarios de tirada internacional. Sus intereses actuales incluyen la plataforma .NET y C#.
Me gustaria dedicar este libro a m i madre por su constante apoyo y paciencia.
Alex Toussaint Alex Toussaint es Director de Ingenieria para Vignette Corporation en Austin, Texas. Cuenta con mas de diez afios de experiencia en desarrollo de software y tiene una amplia experiencia en el manejo de Java desde 1996 y de las tecnologias J2EE desde 1998. Alex ha colaborado en articulos sobre aplicaciones Web y comercio electrdnico para revistas on-line, tales como Microsoft M S D N , y es coautor del libro Professional Site Server publicado por Wrox. Alex tambiin ha sido invitado a impartir clases en la Universidad de Texas en Austin Red McCombs School of Business sobre temas como Comercio Electrdnico y Desarrollo de Software de Empresa. Alex reside en Austin, Texas, en la actualidad con su esposa Danielle y su perro Sasha. Alex e s t i a su disposicidn en la direcci6n [email protected].
Sameer Tyagi Sameer escribe regularmente para publicaciones on-line e impresas. Cuenta con mas de cuatro afios de experiencia en diseiio y desarrollo de software y esti especializado en aplicaciones distribuidas de lado del servidor de base Java (arquitecturas n-Grada, JDBC, JNDI, EJB, JMS, RMI, JSP, Servlets, et al.). Es licenciado en Ingenieria Electrdnica y tiene una amplia formacidn sobre el tema. Es un adicto a Java y consigue su dosis saltando de cabeza a casi cualquier cosa que se compila en c6digos de bytes y se le conoce como el culpable de esa nueva area del cerebro Ilamada Javaesfera por dichos estimulos. Cuando no estC disfrutando de un cafC, puede encontrarle volando a unos 15000 pies de altura en una pequeria Cessna.
Gary Watson Gary Watson ha estado desarrollando el uso de Java durante 10s ultimos 4 arios. Es asesor independiente de Tecnologias de la Informacidn y, en la actualidad, trabaja como Arquitecto TCcnico en el Financial Times, FT. com, en el desarrollo de una importante soluci6n J2EE. Graduado por la Universidad de Teeside en 1993, Gary es Licenciado en Ciencias de la Informltica. Siempre que le es posible, Gary disfruta del windsurf, del esqui y de 10s aviones en miniatura. N o participa en estas actividades tan a menudo como le gustaria. Puede encontrarle en [email protected].
A m i esposa Angela por su amor, apoyo y aliento mientras luchamos juntos en la vida diaria.
Marc Wilcox Marc trabaja en el grupo de servicios profesionales de W e b C T Inc., la principal compafiia del mundo de desarrollo de Sistemas de Gestidn/Entornos de Aprendizaje Virtual. La prdxima version de su producto, cuyo nombre en clave es Cobalt, estari basada en un entorno de aplicaci6n J2EE.
Me gustaria dedicar este libro a Doug y a Sammy, 10s mejores peluqueros del mundo.
Alan Williamson Alan Williamson es todo un veterano del mundo Java, con un lenguaje que todavia intenta encontrar su lugar en el mundo. Alan cuenta con mis de 15 ahos de experiencia en el mundo del desarrollo de software. Se graduo con Honores en Ciencias de la Informitica por la Universidad de Paisley. Alan trabaj6 principalmente en tareas de investigaci6n y desarrollo hasta que establecio la primera compahia del Reino Unido dedicada Gnicamente a1 asesoramiento en Java hace 4 ahos, especializandose en Java en lado del servidor (http://www.n-ary.com). Alan t a m b i h ha llegado hasta lo mis alto convirtihdose en Editor Jefe de la revista mis importante del mundo sobre Java, Java Developers Journal y puede encontrarle dando conferencias por todas partes.
Me gustaria dar las gracias a m i querida Ceri y a m i nuevo hijo Cormacpor guardar el fuerte mientras yo trabajaba e investigaba para escribir este capitulo. Buen trabajo. Adernas, me gustaria dar lax gracias a Keith y Marion por realizar sus tareas de profesor y leer m i capitulo corrigiendo mis errores de gramatica. Finalmente, me gustaria dar las gracias a Wrox por hacer de este proceso de escritura algo alegre y no algo doloroso.
37
Introduccion
J2EE Edici6n 1.3 .......................................................................................................................................... 37 iQuk ha cambiado en esta edicion del libro? ....................................................................................... 38 ?A quiin va dirigido este libro? ................................................................................................................
38
tCubles son 10s contenidos de este libro? ...............................................................................................
39
Lo necesario para utilizar este libro ......................................................................................................... 39 Contenedor Web ............................................................................................................................. 39 Contenedor EJB .............................................................................................................................. 39 Bases de datos ................................................................................................................................... 39 Software adicional .......................................................................................................................... 40
.............................................................................................................................................. Atenci6n a1 cliente .................................................................................................................................... C6mo cargar el c6digo de muestra para el libro .................................................................................... Erratas ........................................................................................................................................................... Apoyo via e-mail ......................................................................................................................................... p2p.wrox.com .............................................................................................................................................. Convenciones
iPor quk esre sistema ofrece el rnejor apoyo?
40 41 41 41 41 42
.....................................................................................42
.
45
..
46
Capitulo 1 Plataforma JZEE Programac~onpara empresas .....................................................................................................................
La empresa actual ........................................................................................................................................ 46 iEs Java la respuesta? .............................................................................................................................49 Independiente de la plataforma ....................................................................................................... 49 Objetos gestionados ........................................................................................................................49 Reusabilidad ...................................................................................................................................... 49 Modularidad ......................................................................................................................................50
..........................................................................................................
Estilos de arquitectura de empresa 50 Arquitectura de dos niveles ................................................................................................................... 50 Arquitectura de tres niveles ................................................................................................................... 51 52 Aquitectura de n niveles ....................................................................................................................... Arquitectura de empresa ........................................................................................................................ 53 La plataforma JZEE ..................................................................................................................................... 55 Period0 de ejecuci6n de J2EE ............................................................................................................... 55 Los API de J2EE .................................................................................................................................... 56 Contenedores ........................................................................................................... 58 Arquitectura JZEE . Arquitectura de contenedor ....................................................................................................................... 60 Contratos de componentes ............................................................................................................ 61 API de servicio de contenedor ....................................................................................................... 62 63 Servicios declarativos ....................................................................................................................... Otros servicios de contenedor ....................................................................................................... 65
.........................................................................................................................................
Tecnologias JZEE 65 Tecnologias de componentes ................................................................................................................ 66 Componentes Web .......................................................................................................................... 66 Componentes Enterprise JavaBean ............................................................................................... 67 XML ........................................................................................................................................................ 68 ......................................................................................................................... 69 Tecnologias de servicio . JDBC ................................................................................................................................................ 69 Java Transaction API y Servicio .................................................................................................... 69 JMS .................................................................................................................................................... 70 JavaMail ............................................................................................................................................ 70 lava Conector Architecture ............................................................................................................ 70 70 JAAS ................................................................................................................................................. 70 Tecnologias de comunicaci6n ............................................................................................................... 70 Protocolos de Internet .................................................................................................................... TCPIIP .............................................................................................................................................. 71 SSL ...................................................................................................................................................... 71 71 Protocolos de objeto remoto .........................................................................................................
...............................................................................................................
Desarrollo de aplicaciones JZEE 71 . . Funciones de desarrollo e implementaci6n de apl~caclones................................................................ 72 Desarrollo de componentes de aplicaci6n ........................................................................................... 73 Composici6n de componentes de aplicaci6n en m6dulos ................................................................ 73 Composicibn de m6dulos en aplicaciones ........................................................................................... 73 74 Implementaci6n de la aplicaci6n ........................................................................................................... Resumen .......................................................................................................................................................
75
.
Canitulo 2 Servicios de directorio y JNDl
.................................................................................................
Servicios de designaci6n y de directorio 77 Servicios de designaci6n ........................................................................................................................ 78 Servicios de directorio ........................................................................................................................... 79 80 LDAP ...................................................................................................................................................... Datos LDAP .................................................................................................................................... 81
Las concesiones ................................................................................................................................ 85 85 iPor qu6 utilizar J N D I cuando tenemos LDAP? ......................................................................... LDAP sin J N D I ................................................................................................................................ 86 86 J N D I sin LDAP ................................................................................................................................ iY XML? ............................................................................................................................................ 86 Uso de J N D I ............................................................................................................................................... 86 Instalaci6n de J N D I .............................................................................................................................. 87
.................................................................................................................
Proveedores de servicios J N D I 87 88 C6mo obtener poveedores de semicios J N D I .................................................................................. 88 C o m o desarrollar su propio proveedor de servicios ..........................................................................
.................................................................................................................................................
Java y LDAP 89 Control de acceso .................................................................................................................................. 89 Autentificacion ................................................................................................................................. 89 90 Autorizaci6n .................................................................................................................................... 90 Semicios de piginas blancas .................................................................................................................. 91 Directorio de procesamiento distribuido ............................................................................................ Configuraci6n de la aplicaci6n ........................................................................................................ 91
Operaciones LDAP ..................................................................................................................................... 92 92 Operaciones LDAP estindar ................................................................................................................ 92 Conexion a1 semidos LDAP con J N D I .............................................................................................. 93 Asociacion .............................................................................................................................................. 94 Seguridad simple, SSL/TLS y SASL ................................................................................................ 94 Simple .................................................................................................................................................
95 SASL ................................................................................................................................................... 95 Autentificacion en LDAP v2 y LDAP v3 ......................................................................................
...............................................................................................................
95 Busqueda en u n s e n i d o r LDAP 96 Filtros LDAP de ejemplo ...................................................................................................................... 96 Determinar el alcance de LDAP ........................................................................................................... LDAP-SCOPE-SUBTREE ........................................................................................................... 96 LDAP-SCOPE-ONELEVEL ....................................................................................................... 97 LDAP-SCOPE-BASE .................................................................................................................... 97 Ejecucion de una b6squeda J N D I ......................................................................................................... 98 100 Cbmo funciona el programa de bhqueda .................................................................................... Restringir 10s atributos presentados .................................................................................................. I03 Aiiadir entradas .................................................................................................................................... 105 111 Modificar una entrada .......................................................................................................................... 113 Eliminar una entrada ........................................................................................................................... Almacenar y recuperar objetos Java en LDAP ....................................................................................... 114 115 LDAP tradicional ........................................................................................................................... 116 Java serializado .............................................................................................................................. Referencias Java .............................................................................................................................. 116
.........................................................................................................................
116 Volver a J N D I sin LDAP Ejemplo de aplicacidn D N S ................................................................................................................. 117
lndice Resumen
.....................................................................................................................................................
.
Capitulo 3 Procesamiento distribuido con RMI
119
121
La arquitectura RMI ................................................................................................................................. 122 Capa de Stub y Skeleton ....................................................................................................................... 123 Stubs ................................................................................................................................................ 124 Skeletons ......................................................................................................................................... 124 Capa de referencia remota ................................................................................................................... 125 Capa de transporte ............................................................................................................................... 125 Localizaci6n de objetos remotos ............................................................................................................ 126 Archivos de politica ...................................................................................................................... 128 Excepciones RMI ..................................................................................................................................
129
Desarrollo de aplicaciones con RMI ...................................................................................................... 130 Definir la interfaz remota ............................................................................................................131 Implementar la interfaz remota .......................................................................................................... 131 Grabar el cliente que utiliza 10s objetos remotos .........................................................................133 Generar stubs y skeletons ................................................................................................................... 134 Registrar el objeto ................................................................................................................................ 134 Ejecutar el cliente y el servidor ........................................................................................................... 135 Pasar parimetros e n RMI ......................................................................................................................... 136 Parimetros de primitivas ..................................................................................................................... 136 Parimetros de objeto ........................................................................................................................... 136 Parimetros remotos ............................................................................................................................ 137
.................................................................................................. Clases de carga dinimica ..................................................................................................................... Retrollamadas remotas ............................................................................................................................ Activaci6n de objeto ............................................................................................................................... El recolector de residuos distribuidos
138 141 146
149 El grupo de activaci6n ......................................................................................................................... 150 ActivationID .................................................................................................................................. 151 Descriptor de activacion ................................................................................................................ 152 Convertir objetos en activables ......................................................................................................... 153 Paso 1: Crear la interfaz remota .............................................................................................. 154 Paso 2: Crear la implementacih del objeto .........................................................................154 Paso 3: Registrar el objeto con el sistema ...............................................................................154 Alternativa a ampliar la clase Activatable ..................................................................................... 156 Iniciar mGltiples JVMs sin recurrir a rmid ..............................................................................157 Desactivaci6n ....................................................................................................................................... 159
................................................................................................................... RMI. cortafuegos y H T T P ....................................................................................................................... Sockets de adaptaci6n y SSL
160
172 Tunelado HTTP ................................................................................................................................... 172 H T T P a puerto ............................................................................................................................... 172 H T T P a C G I .................................................................................................................................. 173
lndice El protocolo SOCKS ..................................................................................................................... 173 174 Factorias de sockets descargados ........................................................................................................ RMI sobre I I O P ........................................................................................................................................ 174 175 Interoperatividad con CORBA .................................................................................................... Escribir programas con RMI-HOP ...............................................................................................176 176 En el servidor ................................................................................................................................. 176 HelloServer.java ............................................................................................................................... 177 En el cliente ................................................................................................................................... 177 HelloClient.java ...............................................................................................................................
..............................................................................................................................
180 RMI-IIOP y Java IDL 180 El archivo IDL ............................................................................................................................... 180 La implernentacion de servidor ..................................................................................................... 182 La implementacibn cliente ............................................................................................................. RMI-IIOP y J2EE ..................................................................................................................................... 184 Ajustar aplicaciones RMI ......................................................................................................................... 185 Resumen .....................................................................................................................................................
189
.
Capitulo 4 Programacion de bases de datos con JDBC Drivers de bases de datos ..................................................................................................................... 193 Puente JDBC-ODBC .......................................................................................................... 193 Tipo 1 . Parte Java, parte driver nativo ............................................................................................. 194 Tipo 2 . Servidor intermediario de acceso a bases de datos ............................................................. 195 Tipo 3 . Drivers Java puro ................................................................................................................ 196 Tipo 4 . 196 Cdmo comenzar ..................................................................................................................................
El paquete java.sq1 ...................................................................................................................................... 197 197 Gesti6n de conexion ........................................................................................................................... 198 Acceso a bases de datos ....................................................................................................................... 198 Tipos de datos ...................................................................................................................................... 199 Metadatos de base de datos .................................................................................................................. 200 Excepciones y advertencias ................................................................................................................. 201 Cargar un driver de base de datos y abrir conexiones ...................................................................... 201 Los URL de JDBC ......................................................................................................................... DriverManager ............................................................................................................................... 202 203 Mitodos para gestionar drivers ...................................................................................................... 203 Mitodos para obtener conexiones ................................................................................................. 204 MCtodos de registro ........................................................................................................................ 205 Driver .............................................................................................................................................. 205 Establecer una conexion ...................................................................................................................... 208 Crear y ejecutar instrucciones SQL ................................................................................................... 209 U n ejemplo: catdogo de peliculas ................................................................................................. 210 Crear la tabla Movie ........................................................................................................................ 210 Insertar datos .................................................................................................................................. 211 Mitodos para el manejo de excepciones ......................................................................................... 214 Consultar la base de datos ................................................................................................................... 214 Mktodos para recuperar datos ........................................................................................................ Interfaz ResultSetMetaData ............................................................................................................ 216
Instrucciones preparadas ..................................................................................................................... 217 219 Representar tipos S Q L en Java ........................................................................................................... 221 Apoyo a transacciones ....................................................................................................................... 223 Puntos de salvaguardia ......................................................................................................................... Listas de resultados desplazables y actualizables ................................................................................ 225 225 Listas de resultados desplazables ................................................................................................... Metodos relacionados con la posici6n del cursor ......................................................................... 227 227 Metodos para desplazamiento ........................................................................................................ 227 Direcci6n y tamafio de toma .......................................................................................................... Listas de resultados actualizables .................................................................................................. 230 230 Actualizar una fila ............................................................................................................................ Eliminar una fila .............................................................................................................................. 231 231 Insertar una fila ............................................................................................................................... Actualizaciones de lotes ....................................................................................................................... 231
.................................................................................................................................... Fuentes de datos JDBC ............................................................................................................................
El paquete javax.sql
232
234 La interfaz javax.sql.DataSource ......................................................................................................... 234 El mCtodo getconnection() ......................................................................................................... 234 235 El metodo getLoginTimeout() ..................................................................................................... El metodo setLoginTimeout() ...............................................................................................235 El metodo getlogwriter() ........................................................................................................... 235 235 El metodo setlogwriter() ............................................................................................................ J N D I y fuentes de datos ...................................................................................................................... 236 237 Crear una fuente de datos .............................................................................................................. Recuperar un objeto Datasource .................................................................................................. 238 Caracteristicas clave ....................................................................................................................... 238 239 Revisi6n del catilogo de peliculas .......................................................................................................
.............................................................................................................................
240 Reserva de conexiones Resewa de conexiones tradicional ...................................................................................................... 241 Resewa de conexiones con el paquete javax.sq1 ...........................................................................243 La interfaz javax.sql.ConnectionPoolDataSource...................................................................... 244 244 La interfaz javax.sql.PooledConnection ...................................................................................... 245 La interfaz javax.sql.ConnectionEventListener.......................................................................... La clase javax.sq1.ConnectionEvent ............................................................................................. 245 Implementaci6n de reservas de conexi6n .............................................................................245
......................................................................................................................
246 Transacciones distribuidas i Q d es una transacci6n? .................................................................................................................... 246 247 Antecedentes ........................................................................................................................................ Procesamiento de transacciones - Conceptos ...........................................................................248 248 Demarcaci6n de transacciones ..................................................................................................... Contexto de transacciones y propagaci6n .............................................................................249 249 Alistamiento de recursos ............................................................................................................... Aceptar en dos fases ...................................................................................................................... 249 Construcci6n de bloques de sistemas de procesamiento de transacciones .....................................250 250 Componentes de aplicaci6n .......................................................................................................... 250 Gestores de recursos ..................................................................................................................... Gestor de transacciones ................................................................................................................ 251 251 Transacciones distribuidas JDBC ......................................................................................................
La interfaz javax.sq1.XADataSource ............................................................................................. 252 La interfaz javax.sql.XAConnection ............................................................................................ 252 La interfaz javax.Transaction.UserTransaction ......................................................................... 252 Pasos para la irnplementaci6n de transacciones distribuidas ............................................................ 253 Configuraci6n ................................................................................................................................ 254 Iniciar una transacci6n .................................................................................................................. 254 Operaciones de base de datos ....................................................................................................... 254 Finalizar una transaction .............................................................................................................. 255 Precauciones especiales .................................................................................................................. 255
.........................................................................................................................................
Objetos RowSet 256 La interfaz javax.sql.RowSet ............................................................................................................... 257 Propiedades ..................................................................................................................................... 257 Eventos ........................................................................................................................................... 258 Ejecuci6n de comandos y resultados ............................................................................................ 258 Tipos de objetos RowSet ..................................................................................................................... 258 La implementacidn CachedRowSet .................................................................................................... 259 La implementacidn RowSet JDBC ..................................................................................................... 261 La implementacidn RowSet Web ........................................................................................................ 261 Resurnen .....................................................................................................................................................
262
.
Capitulo 5 Introduccion a 10s contenedores Web
..................................................................................................................................
El protocolo H T T P 266 MCtodos de solicitud H T T P ............................................................................................................... 266 El metodo de solicitud GET ......................................................................................................... 266 El mitodo de solicitud POST ....................................................................................................... 267 El metodo de solicitud H E A D ..................................................................................................... 267 La respuesta H T T P ............................................................................................................................. 267
..................................................................................................
Contenedores Web y aplicaciones Web 268 Sewlets Java .......................................................................................................................................... 269 Piginas JavaServer ............................................................................................................................... 272 Descriptores de despliegue .................................................................................................................. 273 Estructura de aplicaciones Web .......................................................................................................... 274 Tipos de contenedores Web ................................................................................................................ 274
....................................................................................................................
Una sencilla aplicaci6n Web 275 Prepara el contenedor Web ................................................................................................................. 275 Crear el archivo H T M L ...................................................................................................................... 275 Crear un servlet .................................................................................................................................... 276 Construir la aplicacion Web ................................................................................................................ 277 Desplegar la aplicaci6n Web ............................................................................................................... 281 Ejecutar la aplicaci6n Web ................................................................................................................... 283 C6mo funciona la aplicaci6n ............................................................................................................... 283 El servlet Greeting ......................................................................................................................... 284 Importar 10s paquetes de servlet ..................................................................................................... 284 Declaraci6n de clase ......................................................................................................................... 285 Revisar la solicitud POST HTTP ................................................................................................... 285 Extraer parametros de HttpServletRequest ................................................................................... 285 Generar respuesta ............................................................................................................................ 285
El descriptor de despliegue
............................................................................................................ 287
Resumen .....................................................................................................................................................
288
.
Capitulo 6 Programacion de servlets
................................................................................................................. Implementacidn de servlet ......................................................................................................................
Analisis del API Java Servlet
292
296 La interfaz servlet ................................................................................................................................ 296 El metodo init () ............................................................................................................................. 297 297 El metodo service() ....................................................................................................................... El metodo destroy() ...................................................................................................................... 297 El metodo getServletConfig() ...................................................................................................... 298 El metodo getServletInfo() .......................................................................................................... 298 La clase GenericServlet ........................................................................................................................ : La interfaz SingleThreadModel .......................................................................................................... La clase HttpServlet ............................................................................................................................. Los metodos service() ................................................................................................................... Los metodos doXXX() ................................................................................................................. El metodo getLastModified() .......................................................................................................
........................................................................................................................
Configuracidn de servlets La interfaz ServletConfig .................................................................................................................... El metodo getInitParameter() ...................................................................................................... El metodo getInitParameterNames() .......................................................................................... El metodo- getServletContext () .................................................................................................... El mitodo getServletName0 ........................................................................................................ Obtener una referencia a ServletConfig ............................................................................................ Durante la inicializaci6n del servlet .............................................................................................. Utilizar el metodo getServletConfig() .........................................................................................
...................................................................................................................................
Excepciones servlet La clase ServletException .................................................................................................................... La clase UnavailableE~ce~tion ............................................................................................................
................................................................................................................. El ciclo de vida de u n servlet . FreakServlet ......................................................................................... El ciclo de vida de 10s servlets
Instanciaci6n ........................................................................................................................................ Inicializaci6n ........................................................................................................................................ Servicio ................................................................................................................................................. Destruir ................................................................................................................................................
...........................................................................................................................
Solicitudes y respuestas Lainterfaz ServletRequest ................................................................................................................... Metodos para solicitar parametros .................................................. :............................................ El mktodo getparameter() .............................................................................................................. 319 319 El metodo getParameterValues() ................................................................................................... El metodo getParameterNames0 .................................................................................................. 320 320 El mktodo getParameterMap0 ................................................................................................. Metodos para atributos de solicitud ............................................................................................. 320 El metodo getAttribute() ................................................................................................................ 320
El metodo getAttributesNames() .................................................................................................. 320 El metodo setAttribute() ................................................................................................................ 320 El metodo removeAttribute0 ........................................................................................................ 320 Metodos de entrada ....................................................................................................................... 321 El metodo getInputStream() .......................................................................................................... 321 El metodo getReader() .................................................................................................................... 321 El metodo getCharacterEncoding0 .............................................................................................. 321 El metodo setCharacterEncoding() .............................................................................................. 321 La clase ServletRequestWrapper ......................................................................................................... 321 La interfaz HttpServletRequest .......................................................................................................... 321 Metodos para solicitar ruta y URL ............................................................................................... 323 El metodo getPathInfo0 ................................................................................................................ 323 El metodo getPathTranslatedO ...................................................................................................... 323 El metodo getQueryString() .......................................................................................................... 324 El metodo getRequestURI0 .......................................................................................................... 324 El metodo getRequestURL0 .......................................................................................................... 324 El metodo getsewletpath() ............................................................................................................ 324 Metodos para cabeceras HTTP ..................................................................................................... 324 El m6todogetHeaderO .................................................................................................................... 324 El metodo getHeaders() ................................................................................................................. 324 El metodo getHeaderNames0 ....................................................................................................... 324 El metodo getMethod() ................................................................................................................ 324 La~laseHtt~ServletRequestWrapper ..........................................................................................325 La interfaz ServletResponse ................................................................................................................ 325 Metodos para tip0 de contenido y longitud ................................................................................ 325 El metodo setContentType() .................................................................... ....................................325 El metodo setcontentlength() ..................................................................................................... 325 Metodos de salida ........................................................................................................................... 326 El metodo getOutputStream() ....................................................................................................... 326 El metodo getwriter() .................................................................................................................... 326 Metodos para salida en bfifer ........................................................................................................ 326 El metodo setBufferSize0 .............................................................................................................. 326 El mktodo getBufferSize0 .............................................................................................................. 326 El metodo resetBuffer() ................................................................................................................. 326 El metodo flushBuffer() ................................................................................................................. 327 El metodo isCommitted() .............................................................................................................. 327 El metodo reset() ............................................................................................................................ 327 La clase ServletResponseWrapper ...................................................................................................... 327 La interfaz H t t p S e w l e t R e ~ ~ o n s....................................................................................................... e 327 MCtodos para el manejo de errores .............................................................................................. 328 El metodo sendError() .................................................................................................................. 328 El metodo sendError() .................................................................................................................. 328 El metodo setstatus() ..................................................................................................................... 328 El metodo sendRedirect() ............................................................................................................. 328 La clase HttpServletResponseWrapper .............................................................................................. 328 Funci6n de las clases envoltorio ......................................................................................................... 328
Programacidn de servlets . Aplicacidn de apoyo tkcnico ................................................................... 329
Configurar la pigina HTML ......................................................................................................... 330 Preparar la base de datos ................................................................................................................ 332
Escribir el servlet ........................................................................................................................... 333 Extraer datos del formulario .......................................................................................................... 334 Insertar la solicitud de apoyo tecnico ............................................................................................. 334 335 Generar la respuesta ........................................................................................................................ Compilar la fuente ....................................................................................................................... 336 Construir la aplicaci6n Web .......................................................................................................... 336 340 El descriptor de despliegue .............................................................................................................. 340 Configurar la fuente de datos ....................................................................................................... Desplegar la aplicaci6n Web ......................................................................................................... 341 Apoyo tecnico en marcha ............................................................................................................. 344 Resumen .................................................................................................................................................... 346
.
Capitulo 7 Sesiones de servlets. context0 y colaboracion
349
.............................................................................................................. Enfoques del registro de sesi6n ..............................................................................................................
Protocolo sin estado y sesiones
350
352 Reescritura de URL .............................................................................................................................. 353 Campos de formulario ocultos ........................................................................................................... 354 Cookies ................................................................................................................................................. 354
..
.........................................................................................
Registro de seslon con el API Java S e n l e t 356 Creaci6n y registro de sesiones .......................................................................................................... 357 357 La interfaz HttpSession ...................................................................................................................... Metodos para vida de sesion ......................................................................................................... 358 El metodo getCreationTime0 ........................................................................................................ 359 El mitodo getId() ........................................................................................................................... 359 El mitodo getLastAccessedTime() ................................................................................................. 359 El mitodo getMaxInactiveInterval() ............................................................................................. 359 El metodo setMaxInactiveInterval() ............................................................................................. 359 El metodo isNew() ......................................................................................................................... 359 360 El metodo invalidate() .................................................................................................................... 360 Demostrar el ciclo de vida de la sesion con cookies ................................................................... Ciclo de vida de sesion sin cookies .............................................................................................. 364 365 Metodos para gestionar el estado ................................................................................................. El metodo getAttribute() ................................................................................................................ 365 El metodo getAttributeNames0 .................................................................................................... 365 El mCtodo setAttribute() ................................................................................................................ 365 366 El metodo removeAttribute() ........................................................................................................ Demostrar la gesti6n de estado .................................................................................................... 366 Manejo de eventos de ciclo de vida de sesi6n .................................................................................... 369 369 La interfaz HttpSessionListener .................................................................................................. La interfaz HttpSessionActivationListener ................................................................................ 370 El mitodo sessionDidActivate() .................................................................................................... 370 370 El metodo sessionWillPassivate() .................................................................................................. 370 La clase HttpSessionEvent ............................................................................................................ El mCtodo getsession() .................................................................................................................. 370 Manejo de eventos de atributos de sesi6n ......................................................................................... 371 371 La interfaz HttpSessionBindingListener..................................................................................... El metodo valueBound() ................................................................................................................ 371 El metodo valueUnbound() ........................................................................................................... 371
La interfaz HttpSessionAttributeListener ................................................................................... 371 El metodo attributeAdded0 ........................................................................................................... 372 El metodo attributeRemoved0 ...................................................................................................... 372 El metodo attributeReplaced0 ........................................................................................................ 372 La clase HttpSessionBindingEvent .............................................................................................. 372 El mitodo getName() ..................................................................................................................... 372 El mitodo getvalue() ...................................................................................................................... 372 El metodo getsession() .................................................................................................................. 372 U n sencillo carro de la compra utilizando sesiones ........................................................................372 El senlet del catilogo .................................................................................................................... 373 El senlet Shoppingcart ................................................................................................................ 374 Contexto de sewlet ................................................................................................................................... 377 La interfaz Senletcontext .................................................................................................................. 378 El mttodo getMimeType0 .............................................................................................................. 378 El mttodo getResource0 ................................................................................................................ 378 El metodo getResourceAsStream() ............................................................................................... 378 El metodo getRequestDispatcher() ................................................................................................ 379 El metodo getNamedDispatcher ................................................................................................. 379 El metodo getRealPath0 ................................................................................................................ 379 El metodo getcontext () ................................................................................................................. 379 El mitodo getSenerInfo() ............................................................................................................. 379 El metodo getSenletcontextName() ............................................................................................ 379 El metodo getResourcePaths() ...................................................................................................... 379 Los metodos getInitParameter0 y getInitParameterNames() ....................................................380 Los metodos getAttribute0, getAttributeNames0, setAttributes0 y removeAttribute0 ........380 Los metodos log() .......................................................................................................................... 380 El manejo de eventos de ciclo de vida de Senletcontext ..............................................................380 La interfaz Senlet Context Listener .............................................................................................. 380 SenletContextAttributeListener.................................................................................................. 381 Una aplicacion de chat que utiliza context0 y sesiones ..................................................................381 La clase ChatRoom ........................................................................................................................ 384 La clase ChatEntry ........................................................................................................................ 384 El senlet de administracion .......................................................................................................... 385 Servlets para chat .......................................................................................................................... 388 La clase ListRoomsSenlet .............................................................................................................. 388 La clase ChatRoomSenlet .............................................................................................................. 391 Configuration del chat .................................................................................................................. 396 Una pigina de bienvenida ................................................................................................................ 396 Descriptor de despliegue ................................................................................................................. 396 Desplegar y probar .......................................................................................................................... 397
..
Colaboracion de sewlet ............................................................................................................................ 399 Encadenado de senlet ...................................................................................................................399 Lanzamiento de solicitudes ........................................................................................................... 400 La interfaz RequestDispatcher ...................................................................................................... 400 El metodo forward() ...................................................................................................................... 401 El metodo include() ........................................................................................................................ 401 Obtener un objeto R e q ~ e s t D i s ~ a t c h ........................................................................................ er 401 Revision de Apoyo Tecnico ................................................................................................................ 401 La pigina techsupp.html ................................................................................................................ 402
TechSupportSe~let....................................................................................................................... 404 La pagina register.htm1 .................................................................................................................. 406 RegisterCustomerSe~let.............................................................................................................. 407 ResponseSe~let............................................................................................................................. 408 BannerServlet ................................................................................................................................. 409 Configuracion de Apoyo Tkcnico y despliegue ........................................................................... 411 Utilizar RequestDispatcher para colaboraci6n ............................................................................412 Reenviar una solicitud a ResponseSemlet ...................................................................................... 412 Reenviar solicitud a regiter.htm1 ..................................................................................................... 412 Incluir insignia en ResponseSemlet ............................................................................................... 413 Resurnen ................................................................................................................................................. 413
.
Capitulo 8 Filtros para aplicaciones Web
415
..................................................................................................................................... Filtro de rnuestra .................................................................................................................................. i Q u i es u n filtro?
416
418 Despliegue ....................................................................................................................................... 421
El API filtro .............................................................................................................................................. 422 La interfaz de filtro .............................................................................................................................. 422 El mktodo init () .............................................................................................................................. 423 El metodo doFilter() ....................................................................................................................... 423 El metodo destroy() ....................................................................................................................... 423 La interfaz Filterconfig ...................................................................................................................... 424 El metodo getFilterName() ............................................................................................................ 424 El mitodo getInitParameter0 ........................................................................................................ 424 El metodo getInitParameterNames() ............................................................................................ 424 El metodo getSemletContext() ...................................................................................................... 424 La interfaz Filterchain ........................................................................................................................ 424 El metodo doFilter() ....................................................................................................................... 425 Descriptor de despliegue para filtros ................................................................................................. 425 La aplicacidn de chat con filtros ............................................................................................................. 427 Registro de mensajes ........................................................................................................................... 428 Moderaci6n de mensajes ..................................................................................................................... 430 Descriptorde despliegue ...................................................................................................................... 434 Despliegue ....................................................................................................................................... 436 Chat con registro y moderaci6n ........................................................................................................ 437 Resurnen ..................................................................................................................................................... 438
.
Capitulo 9 Despliegue Web. autentificacion y empaquetado 4 4 1 Estructura de aplicacidn Web .................................................................................................................. 441 Estructura de directorio ...................................................................................................................... 442 Ficheros en archivo Web .......................................................................................................................... 444 Desplegar un archivo WAR .......................................................................................................... 445 i C u i n d o deben utilizarse 10s archivos WAR? ............................................................................ 446 Asociar de solicitudes a aplicaciones y servlets .................................................................................... 446
lndice Asegurar aplicaciones Web ....................................................................................................................... 451 Seguridad programada ..................................................................................................................454 El mitodo getAuthtype() ............................................................................................................... 454 El metodo getRemoteUser() ................................................................................................... 454 El metodo getUserPrincipal() ..................................................................................................454 El mCtodo isUserRole() ................................................................................................................. 454 Autentificacibn basada en un formulario ....................................................................................454
..
...................................................................................................................
Configuraclon de despliegue 457 Parimetros de inicializaci6n de context0 .......................................................................................... 458 Parimetros de inicializaci6n de servlet ............................................................................................459 Cargar servlets en el arranque ............................................................................................................ 459 Tiempo limite de sesi6n ....................................................................................................................... 460 Asociaciones MIME ............................................................................................................................ 460 Archivos de bienvenida ....................................................................................................................... 461 Piginas de error ................................................................................................................................... 462 Enviar errores ............................................................................................................................463 Lanzar ServletException .........................................................................................................463 Manejar errores y excepciones HTTP ......................................................................................... 464 Aplicacionesdistribuibles .................................................................................................................... 465 Resumen ....................................................................................................................................................
.
Capitulo 10 Fundamentos y arquitectura de JSP
........................................................................................................................ Presentaci6n de JSP ................................................................................................................................ Los aspectos pricticos ............................................................................................................................. La especificaci6n JSP 1.2
468
471 471 472
476 Directrices JSP ..................................................................................................................................... 477 La directriz page ............................................................................................................................. 477 Ejemplo ............................................................................................................................................ 479 La directriz include ......................................................................................................................... 479 Ejemplo ............................................................................................................................................ 480 La directriz taglib ......................................................................................................................482 Elementos de directivas ....................................................................................................................... 482 Declaraciones ................................................................................................................................. 483 Ejemplo ............................................................................................................................................ 483 Scriptlets ......................................................................................................................................... 484 Ejemplo ............................................................................................................................................ 484 Expresiones .................................................................................................................................... 486 Ejemplo ............................................................................................................................................ 487 Comentarios .................................................................................................................................. 487 Acciones estindar ................................................................................................................................ 488 ............................................................................................................................... 488 ........................................................................................................................ 490 ..................................................................................................................492 .................................................................................................................................. 495 ................................................................................................................................. 495 ..........................................................................................................................500 .................................................................................................................................. 502 Objetos implicitos ............................................................................................................................... 505
lndice El objeto Request ........................................................................................................................... 505 505 El objeto Response ........................................................................................................................ 505 El objeto Pagecontext .................................................................................................................. El objeto Session ........................................................................................................................... 505 506 El objeto Application ..................................................................................................................... 506 El objeto O u t ................................................................................................................................. 506 El objeto Config ............................................................................................................................ 506 El objeto Page ................................................................................................................................. Alcance .................................................................................................................................................. 506 507 Alcance de pigina ........................................................................................................................... 507 Alcance de solicitud ........................................................................................................................ 507 Alcance de sesi6n .......................................................................................................................... 507 Alcance de aplicacion ..................................................................................................................... 507 Piginas JSP como documentos XML ................................................................................................ 508 Directrices ...................................................................................................................................... 508 Elementos de directivas ................................................................................................................. Acciones ......................................................................................................................................... 509 509 Una pigina de ejemplo ................................................................................................................... 509 Sintaxis JSP ...................................................................................................................................... 509 Sintixis XML ................................................................................................................................... Apoyo tecnico JSP .................................................................................................................................... 509 511 Disefio de aplicacih ............................................................................................................................ 511 La pigina de bienvenida ....................................................................................................................... La pagina JSP de procesamiento de solicitudes ...............................................................................512 513 La clase JDBCHelper .......................................................................................................................... 514 TechSupportBean ................................................................................................................................. 516 Formulario de registro ........................................................................................................................ 517 JSP de registro ...................................................................................................................................... 517 Las piginas JSP de respuesta y de anuncio ......................................................................................... 518 La pigina de error ................................................................................................................................ 519 Desplegar la aplicacidn ......................................................................................................................... Estrategias de disefio JSP ......................................................................................................................... 520 521 Disefios centrados en la pigina o cliente-servidor ........................................................................... 521 Vista de pigina ...................................................................................................................................... 522 Vista de pigina con bean ..................................................................................................................... 523 El patron de controlador frontal ....................................................................................................... Implementaci6n de una arquitectura de controlador frontal .......................................................524 524 Servlet controlador ........................................................................................................................ 525 Manejadores de solicitud ............................................................................................................... 525 Beans de pigina .............................................................................................................................. 525 Vistas JSP ....................................................................................................................................... Implementation ............................................................................................................................. 526 534 Ventajas .......................................................................................................................................... 535 Utilizar un sistema de controlador genkrico ............................................................................... Resumen ................................................................................................................................................... 535
.
Capitulo 11 Extensiones de etiaueta de JSP Extensiones de etiqueta ............................................................................................................................. 539
Mejoras de la extensi6n de etiqueta JSP 1.2 ....................................................................................... 542 Una sencilla etiqueta ................................................................................................................................. 542 Anatomia de una extensidn de etiquetas ................................................................................................ 546 Manejadores de etiqueta ....................................................................................................................... 547 La interfaz javax.se~let.jsp.tagext.Tag.............................................................................................. 547 ......................................................................550 La interfaz javax.se~let.js~.ta~ext.IterationTag La interfaz javax.se~let.jsp.tagextBodyTag.........................................................................550 La clase javax.servlet.jsp.tagextBodyContent .............................................................................. 552 Clases de conveniencia .................................................................................................................. 553 554 Objetos de disposici6n de 10s manejadores de etiqueta .............................................................. Revisi6n del sencillo ejemplo ........................................................................................................ 555 Descriptores de biblioteca de etiqueta ................................................................................................ 556 Utilizar extensiones de etiqueta en piginas JSP ................................................................................ 558 Despliegue y empaquetado de bibliotecas de etiquetas ....................................................................... 559 Asociaciones en Web.xm1 ............................................................................................................. 560 561 Paquete JAR de biblioteca de etiquetas ......................................................................................... Asociaci6n por defect0 .................................................................................................................. 561 Combinaciones de asociaci6n ....................................................................................................... 561 Escribir extensiones de etiqueta ............................................................................................................. 561 Atributos de procesamiento ................................................................................................................ 561 Contenido de cuerpo ........................................................................................................................... 565 Variables de directivas introducidas por etiquetas ............................................................................. 567 Cambios en el manejador de etiqueta ........................................................................................... 568 Ejemplo de variables de directiva .................................................................................................. 568 Definici6n programitica de variables de directiva ....................................................................... 571 573 Iteraci6n y manipulaci6n de contenido de cuerpo ............................................................................ 573 Evahaci6n repetida con la interfaz IterationTag ........................................................................ Etiquetas de cuerpo que filtran su contenido ............................................................................... 576 Anidamiento de etiqueta ...................................................................................................................... 578 Validar el uso de extensiones de etiqueta en piginas JSP .................................................................. 583 Manejo de errores ................................................................................................................................ 584 TryCatchFinally: ?un peligro para el disefio? .............................................................................. 590
................................................................................................... Locuciones de extensiones de etiqueta ................................................................................................... Resumen ..................................................................................................................................................... Eventos de ciclo de vida de aplicacidn
590 595 597
.
Capitulo 12 Escribir aplicaciones JSP con bibliotecas de etiquetas
599
............................................................... Ejemplos de bibliotecas de etiquetas existentes ..................................................................................... Introducci6n de la Biblioteca de Etiquetas Estindar JSP (JSPTL) .................................................... Ventajas de utilizar bibliotecas de etiquetas personalizadas
600 601
602 602 Obtener JSPTL .................................................................................................................................... r y. j ; c l a s s JNDISearzhAttrs {
/ / 1 m p l e r r t e r ~ t a c i ; ~ rd~e z ~ ) n t e x t o i n i c i a l p u b l i c s t a t i c S t r i n g INITCTX = "corn. s u n . j r d i . l d a p . L d a p C t x F a c t o r y Y ' ; MY-HOST = " l d a p : / / l o c a l h o s t : 3 8 9 " ; MY-SEARCHBASE = " o = A i r i u s . corn";
public public
statlc static
String String
public
static
S t r i n g MY-FILTER
=
" ( s n = C a r t e r )";
/ / E s p e c i f i c a r quk a t r i b u t ~ se s t 6 b u s c a n d o p u b l i c s t a t i c S t r i n g MYpATTKSII = [ " c n " , " r n a i l " ] ; public s t a t i c void rnain(String a r g s [ ] ) [ try i / / H a s h t a b l e p a r a i n f o r m a c i 6 n d e l rnedio H a s h t a b l e e n v = new H a s h t a b l e ( ) ; / / E s p e c i f i c a r qu6 c l a s e u t i l i r a r para nuestro proveedor e n V . p u t ( C o n t e x t . INITIALpCONTENTpFACTORRi, I N I T C T S ) ;
JNDI
e n v . p u t ( C o n t e x t . PROVIDERpURL, MY-HOST) ; / / O b t e n e r u n a r e f e r e n c i a a un c o r j t e x t o d e d i r t c t o r i o D i r C o n t e x t c t x = new I n i t i a l D i r C o n t e x t ( e n v ) ; SearchControls
constraints
=
new
SearchControls ( ) ;
cor~strair~ts.setSearct~Scope(SearchCor~trols.SUBTREE-SCOPE); Namir~gEnurneratim r e s u l t s = c t x . s e a r c h ( M Y SEAKCHBASE,MY FILTER, c o n s t r a i n t s ) ; w h i l e ( 1 - e s u i t s ! = r ~ u l l & & r e s u l t s . hasMcre ( ) ) { SearchResult s r = (SearchResult) r e s u l t s . n e x t ( ) ; S ~ L - i n gijrl = s r . g e t N a m e ( ) + ", " + MY-SEARCHBASE;
i f
" + dn);
S y s t e r r 1 . 5 u t . p r i r ~ t l r (j " D i s t i n g u i s h e d Name
is
Attributes
M Y ATTKS);
(ar
==
ar
null )
=
ctx.getAttributes (dn,
{
Systern.out.println("Entry " + d n " h a s none a f
1 else for
t
the
specified
attributes\nM);
{
( i n t i =O;i capplet (:debase=". "
/ t, t 11, i ?
~ : ~ : ~ d e = " C a l l b a c l . : A p p lcel ta. s c "
width=300
heigt,t=266>
Ejecute el ejemplo despuks de iniciar el registro y el servidor desde el mismo directorio como el archivo H T M L y 10s archivos de clase. applttviewer
-J-Pjava.
security.poiicy=reglsttrit . p o l i c y A p ~ , l e t V i e w e r h . tml
Finalmente, a1 ejecutar este ejemplo, obtenemos algo parecido a esto:
Applet
(
I
Hello World, the current system time is Fn Aug 1 7 1 g:57:ll BST 2001
This is a message from the sewer!
Procesamiento distribuido con RMI
Activacion de objeto Los objetos remotos que hemos analizado hasta el momento son instancias de la clase j a v a . r m i .U n i c a s t R e m o t e O b j e c t y tienen una caracteristica principal. Son accesibles en todo momento, incluso cuando no hay clientes ejecutando. Consideremos un marco hipotktico en el que el numero de objetos remotos, o de recursos utilizados por ellos en un servidor sea alto. Esta situaci6n fue identificada como un importante cue110 de botella en Java 2 , por lo que se introdujo el concept0 de activaci6n. La activacion de objetos permite ejecutar objetos remotos dependiendo de la necesidad. Es decir, cuando se accede a u n objeto remoto "activable" (via invocacion de metodo), si ese objeto remoto n o estd siendo ejecutado en ese momento, el sistema inicia la ejecuci6n del objeto e n una JVM apropiada. RMI utiliza la activaci6n lenta: es aquella en la que la activaci6n de u n objeto es aplazada hasta el primer uso de u n cliente, la primera invocaci6n de mitodo. Entonces, icuil es la diferencia entre un objeto activable y el habitual objeto remoto desde la perspectiva de un cliente? Ninguna. Para el cliente, todo el mecanismo de activacion es transparente y el cliente nunca es consciente de lo que esti ocurriendo detris de la escena. Las referencias a1 objeto remoto pueden ser consideradas referencias lentas o imperfectas. Las referencias a objetos activables contienen informacion persistente de descripci6n que permite la activation del subsistema para saber que el objeto deberia estar iniciado si no esti ya siendo ejecutado. Despuks de que una referencia activable sea utilizada por primera vez, la capa de referencia remota cambia a referencia remota regular de mod0 que no tenga que pasar por el sistema de activaci6n posteriormente. Puesto que el sistema de activaci6n puede cambiar la referencia lenta a referencia remota activa, las referencias a objetos activables estin siempre disponibles. Sin embargo, las referencias a un objeto remoto no sobreviven despuks de un fallo del sistema o de reiniciar. Para comprender la verdadera semintica de utilizar el modelo de activacibn, debemos familiarizarnos con algunos tkrminos utiles:
O Activador El activador es un componente principal en el sewidor. Facilita la activaci6n del objeto remoto registrando toda la informacidn necesaria para activar un objeto y es responsable de iniciar instancias de las JVM en el sewidor si es necesario. 0
G r u p o de activaci6n U n grupo de activacion crea instancias de objetos en su grupo e informa a su monitor sobre 10s diferentes estados activos y pasivos. La analogia mas cercana a un grupo de activation es un grupo thread (hebra). U n grupo de activaci6n es en esencia una instancia cornpleta, independiente de la JVM que existe unicamente para albergar grupos de objetos activados. Esta nueva JVM es iniciada por el activador cuando asi se requiere. Pueden existir multiples grupos de activaci6n.
O Monitor de activaci6n Cada grupo de activaci6n tiene un monitor de activaci6n que registra el estado de un objeto en el grupo y el estado del grupo en su conjunto. El monitor de activaci6n es creado cuando se activa el grupo. O Sistema de activaci6n El sistema de activaci6n proporciona un medio para registrar grupos y objetos activables para ser activados dentro de esos grupos. Trabaja en estrecha relaci6n con el activador, que activa objetos
Capitulo 3 registrados mediante el sistema de activaci6n y con el monitor de activacibn, y obtiene informacidn sobre objetos activos e inactivos, y grupos inactivos. El modelo de activaci6n y sus implementaciones asociadas aparece resumido en la siguiente tabla:
I
Entidad
Implementaci6n
Implementado como
Activador
java. rmi. activation-Activator
Interfaz (observe que el activador es en si mismo un objeto remoto).
Grupode activaci6n
java.rmi.activation.ActivationGroup
Claseabstracta.
Monitor de activaci6n
j a v a . r m i . activation.ActivationMonitor
Interfaz.
Sistemade activaci6n
java.rmi.activation.ActivationSystem
Interfaz.
El mecanismo de activacion utiliza identificadores y descriptores. Aunque pueda parecer excesivo, merece la pena recordar estos puntos:
0 Cada objeto activable tiene un I D y un descriptor.
o
Cada objeto activable pertenece a un grupo de activacion. El grupo mismo tiene un I D y un descriptor.
El grupo de activacion U n grupo de activaci61-1,como ya hemos dicho anteriormente, se utiliza para mantener un grupo de objetos activables. El grupo de activaci6n esti asociado a un identificador de grupo ( j a v a . r m i . A c t i v a t i o n . ~ c t i v a t i o n ~ r o uypa ~ n~d)e s c r i ~ t o r d e g r u p o ( j a v a . r m i .a c t i v a t i o n . A c t i v a t i o n ~ r o u p D e s c queidentifican ) y describenelgrupodeactivaci6n respectivamente. U n grupo de activaci6n es creado explicitamente como resultado de invocar el mktodo ActivationGroup.createGroup(): public
static ActivationGroup createGroup(ActivationGroup1D id, ActivationGroupDesc desc, long incarnation)
donde:
0 i d e s el identificador del grupo de activacih 0
d e s c es el descriptor del grupo de activaci6n
0 i n c a r n a t i o n es el n ~ m e r ode personification del grupo de activaci6n (cero en la creaci6n inicial de un grupo) A c t i v a t i o n G r o u p I ~ademis , de identificar el grupo de forma exclusiva dentro del sistema de activacion, tambikn contiene una referencia al sistema de activacion del grupo. Esto permite al grupo interactuar con el sistema siempre y cada vez que sea necesario. Todos 10s objetos con el mismo A c t i v a t i o n G r o u p I D son activados en la misma JVM.
Procesamiento distri buido con RMI U n A c t i v a t i o n G r o u p D e s c contiene la informacidn necesaria para crear o recrear el grupo en el que activar objetos. Contiene: O
E l n o m b r e d e ~ l a s e d e l g r u ~Recuerdeque o. j a v a . r m i .a c t i v a t i o n . A c t i v a t i o n G r o u p e s una clase abstracts y el activador ( r m i d ) proporciona internamente su implementacidn concreta (par ejemplo, la clasesun. r m i . s e r v e r . A c t i v a t i o n G r o u p I m p l ) .
0 La ubicacibn de la clase del grupo. O
U n objeto escrito y transmitido (marshaled) que puede contener datos de inicializaci6n especificos del grupo.
que especifica las opciones A c t i v a t i o n G r o u p D e s c contiene una clase interna~ommand~nvironment de entorno de arranque para las clases de implementaci6n de A c t i v a t i o n G r o u p . Esto permite un control exacto sobre las opciones de comando utilizadas para iniciar la JVM descendiente (un C o m m a n d E n v i r o n m e n t nulo hace referencia a 10s valores por defecto de r m i d ) . A c t i v a t i o n G r o u p D e s c puede ser creado utilizando uno de 10s dos constructores especificados a continuaci6n: O
Construir un descriptor de grupo que utilice la omisi6n del sistema para la implementaci6n de grupo y la localization de c6digo:
ActivationGroupDesc(Properties overrides, ActivationGroupDesc,CommandEnvironment cmd)
O Especificar una implementaci6n de grupo y un entorno de ejecuci6n alternativo para set utilizado por el grupo: ActivationGroupDesc(String className, String location, Marshalledobject data, Properties overrides, ActivationGroupDesc.CommandEnvironment cmd)
Hemos dado un ripido repaso a 10s grupos de activacidn. Veamos ahora algo de cddigo que resume la creacidn de grupos de activacibn: / / Crear el descriptor d e grupo Properties env = new Properties ( 1 ; env.put ("java.security.po1icyYY,"fi1e://%BOOKHOME%/Ch03/Activatable/ registerit .policy") ; ActivationGroupDesc mygroupdes = n e w ActivationGroupDesc(props, n u l l ) ;
/ / Obtener una referencia a1 sistema d e activaci6n ActivationSystem mysystem= ActivationGroup.getSystem();
/ / Registrar el descriptor de grupo con el sistema de activaci6n y obtener el id del grupo id ActivationGroupID groupid=y system.registerGroup(mygroupdes); / / Ahora que tenemos el id y el descriptor podemos crear el grupo explicitamente Activatior~Group.createGroup(groupid, mygroupdes, 0);
Igual que A c t i v a t i o n G r o u p I D es un I D para el g r u p o , A c t i v a t i o n I D es un I D para el objeto. Una vez que el objeto es registrado con el sistema de activacidn, se le asigna un A c t i v a t i o n I D . Contiene dos elementos esenciales de informacibn:
o Una referencia remota a1 activador del obieto
Procesamiento distribuido con RMI O
Invocando el mktodo e s t i t i c o ~ c t i v a t a b l .e r e g i s t e r ( A c t i v a t i o n D e s c d e s c )
.
o Instanciando el objeto mismo utilizando el primer o el segundo constructor de la clase A c t i v a t a b l e (que toma A c t i v a t i o n I D como parimetro). Este registra y exporta el objeto. O
Exportando el objeto explicitamente mediante el primer o el segundo mitodo e x p o r t o b j e c t de l a c l a s e A c t i v a t a b l e que toma u n A c t i v a t i o n I D , la implementaci6n de un objeto remoto y un numero de puerto como argumentos. Este registra y exporta el objeto.
()
Detris de las escenas esti ocurriendo lo siguiente:
o Cuando se genera un stub para un objeto activable, contiene information especial sobre el objeto. Esta informaci6n incluye el identificador de activaci6n e informaci6n sobre el tipo de referencia remota del objeto. 0 El activador localiza el descriptor de activaci6n del objeto y el grupo de activaci6n. Si el grupo de
activacion en el que deberia estar este objeto n o existe, el activador inicia una instancia de una JVM, crea un grupo de activacion y despuks envia la solicitud de activaci6n a ese grupo. El grupo de activaci6n carga la clase para el objeto y lo instancia (utilizando constructores especiales que toman varios argumentos, como veremos pronto). Cuando el objeto es activado, el grupo de activaci6n devuelve una referencia de objeto a1 activador (ksta es una referencia serializada o marshaled). El activador graba el identificador de activaci6n y el pareado de referencia y devuelve la referencia viva a1 stub. El stub envia entonces invocaciones de metodo mediante esta referencia viva directamente a1 objeto remoto (la referencia viva es como cualquier otra referencia). Resumamos todo lo que hemos visto hasta ahora volviendo a ejecutar el ejemplo H e l l o w o r l d para convertirlo en activable.
Convertir objetos en activables C o m o hemos visto, existen algunas entidades cooperantes en el marco de trabajo de la activacion que hacen todo sea posible:
o El objeto. O
El programa envoltorio que registra el objeto. Es similar al programa RegisterIt que utilizamos anteriormente. Normalmente realiza unas llamadas de metodo a1 sistema de activaci6n para proporcionar detalles sobre c6mo deberia ser activado el objeto.
O
La tercera entidad es el demonio (daemon) de activacidn que graba informacibn, igual que el registro, sobre cuindo y quk hacer con 10s objetos (este daemon es r m i d ) .
Teniendo en cuenta estas entidades, 10s pasos para convertir un objeto en activable pueden resumirse del siguiente modo: O
Elobjeto debeampliarlaclase j a v a . r m i . A c t i v a t i o n . A c t i v a t a b l e enlugardelaclase U n i c a s t R e m o t e O b j e c t (existe una alternativa a esto que examinaremos posteriormente).
0 El objeto debe incluir un constructor especial que tome dos argumentos, su identificador de
activaci6n de t i p o ~ c t i v a t i o ny~sus ~ , datos de activaci6n opcionales, un j a v a r m i .M a r s h a l l e d O b j e c t . Este es distinto de 10s objetos remotos no activables, que incluyen un constructor sin argumento. Este constructor especial es llamado por el sistema RMI cuando activa el objeto.
.
Capitulo 3 0 U n descriptor de activation (java . rmi .Activation.Activation~esc) debe ser creado y
registrado con el activador (rimd). Es importante destacar que la interfaz remota del objeto n o necesita ser cambiada o modificada en n i n g h caso. Es logic0 porque solo estamos cambiando la implementation de la instancia del objeto, n o la perception exterior del objeto.
Paso 1:Crear la interfaz remota N o se diferencia de lo que teniamos anteriormente: lrnprt
j ava
.r m i .
+
;
Paso 2: Crear la implernentacion del objeto Esta clase arnplia j ava. rmi .Activation .Activatable eimplementa la interfazremota (puesto que la clase Activatable amplia RemoteObj ect). Ademis, debe contener un constructor de dos argumentos que tomaActivationID yMarshaledObj ect como argumentos. Este constructor debe llamar a 10s constructores de superclase adecuados para asegurar la inicializacion: i m F > o r t j a v a . 1 - n i l . '; irnp(,rt j a v a . rnii. a c t i v a t i o n . * ; import j a v a . u t i 1 .Date; public
class
HelloServel-
e s t e r ~ d sActivatable
implenier~ts H e l l o I n t e r f a c e
H e l l o S e r v e r ( A c t i T ~ a t i o r ~ IiD d , Marshaledobject d a t a ) throws RemoteExceptior~ { / / R e q i s t r a e l o b j e t o c o n una a s t i T J a c i 6 n d e l s i s t e m a / / R e g i s t r a r l c ~ 7 e s p o r t a r l o en u r ~ p u e r t o a r ~ i r ~ i m o superiid, 0 ) ;
publiz
p ~ b l i i : S t r i n g s a y H e l l o ( ) thrt-.:h..- R e m o t e E x c e ~ ' t i i , n l l . e t ! l r r ~" H r l l ' - ~ W o r l d , t h e ' : u r r e n t system time i s
"
+ ~r.eh, D a t e ( ) ;
Paso 3: Registrar el objeto con el sistema Esta clase contiene toda la informacion necesaria para registrar el objeto, sin crear verdaderamente una instancia del objeto: import import import
j a T / a .r m i . * ; j a v a . rmi . a c t i v a t i o n . * ; j ava. u t i l . Properties;
~ , ~ ~ b cll ia sc s
RegisterIt
!
p u b l i c s t a t i c v o i d m a i r ~ ( S t r i r ~ a~rgg s [ ] ) t h r o w s E x c e p t i o r ~ ~{ try i / / I t n s t a l a r url g e s t o r d e s e g u r i d a d System. s e t S e c u r i t y M a n a g e r (new RMISezurityManager i ) ) ;
{
Procesamiento distribuido con RMI
/ / Crear el grupo Properties env = new Froperties ( ) ; env.put ("java.security.policy", "file://%BOOK HOME%/Ch03/Activatable/ activation/reqisterit.policy"); ActivationGroupDesc myqroupdes = new ActivationGroupDesc (ertv,null) ; ActivationGroupID mygroupid = ActivationGroup.getSysteni(). registerGroup(rnygroupdes);
Activatior~Group.createGroup(myqroupid,mygroupdes,
0);
/ / Crear los detalles sobre el objeto Activatior~Desc obj ectdesc = new ActivationDesc ("HelloServer", "file://%BOOK HOME%/Ch03/Activatable", null);
/ / Registrar el descriptor de activaci6n con el activador HelloIrlterface rnyobject = (HelloInterfacejActivatable .reqister(objectdesc); / / Asiiclar el stub a un r~ornbre del reqistro rmi Naming. rebind("helloObject", myobject); / / Salir Systern.out .println ( " D o r ~ e ";)
Casi hemos terminado. Ahora podemos utilizar el viejo cliente que grabamos para nuestro ejemplo inicial y ejecutarlo con 10s mismos argumentos de politica y arranque: import
]
a v a .rrni . * ;
public class HelloClient
[
public static void rnain(Strinq arqs[]) { if (arqs.length < 1) { System.out.println ("Usage: java HelloCllent "); System. eslt ( I ) ; 1 else { try I HelloIrlterface server
}
=
( H e l l v 1 n t e r f a c e ) N a r n i n g . lookup (
"rmi://" + arqs[O] + "/helloObject"); System.out.println(server.sayHello()); catch (Exception e ) [ e.printStackTrace ( ) ;
1 1
i I
Compile 10s archivos y despuis genere 10s stubs y 10s skeletons para el objeto remoto. Inicie el sistema de Activaci6n utilizando la utilidad r m i d y luego inicie nuestro programa que registra nuestros objetos activables: rmid J - D j a v a . s e c u r i t y . p o l i c y = r e q i s t e r i t . p o l i c y
Capitulo 3 Ahora podelnos ejecutar el a r c h i w Regis t e r I t: - P j - r ~ ~ . : : e , : ' ~ r i t ! ; . p ~ l i r 2 y = r ~ ~ t? .i p~r t. el ir ci y -Cmi ;1'.>a. r m i : : e ~ . i e r .r : . ~ . . l e b r 7 . c r . = f i 1//3;E?OOi':_ e: HOPlL'i/i'hlj?/A~:t i v ~ L a t , l ~ / Ke~i:?rcrIt
j
.
Finalmente, podemos utilizar el clientc, c o m o rnucstra la siguicnte pantalla de salida:
jese en que deberia tener tres o cuatro ventanas d e lineas de comandos abiertas para este ejemplo: J Rmiregistry
J Rmid
Ll RegisterIt 1 3 Helloclient
Las dos ultimas podrian ejecutarse en una ventana.
Alternativa a ampliar la clase Activatable En ocasiones puede que n o sea posible ampliar la c l a s e ~ civatable t si el objeto remoto necesita ampliar otra clase. Por ejemplo, si estamos escribiendo un applet que queremos convertir e n activable o e n objeto remoto, nuestro applet necesitaria ampliar j ava .applet .Applet y e n Java n o existe la herencia rndtiple.
Ya henios visto anteriurmente que era posible convertir un objeto en remoto exportando el objeto directamente utilizando uno de 10s mktodos d e exportaci6n de la clase j ava rmi .UnicastRemoteObj ect,envezdeamp~iar~ac~ase~nicast~ernote~bj ect.
.
Esiste una alternativa similar para 10s objetos activables. Al hablar sobre descriptores de activation hemos mencionadu un metodo exportob j ect ( ) Es posible registrar y exportar un objeto invocando cualquiera de los niCtodos de exportacion d e la clase j ava .Activation .Activatable.
.
Rescribamos nuestra clase activable Helloserver para demostrar esto, manteniendo igual el resto:
puhlic
class HelluServer
puhlic
impl.ements H e l l o I n t e r f a c e
H ~ l l o S e r v e r [ A c t i v a t i c ~ n Iid, t~ tht-ows RemoLeExcept l o r ] (
(
Marshaledobject
/ I R e q i ~ t r a r l o y e x p n r t a r l o e n u n puerto anbnlrno Activatable.export0bject [ t h i s , i d , 0 ) ; / / OF, /
&
data)
Procesamiento distribuido con RMI Activatable. r-xpsrt0bject(this, id, 0 , new S o r n e R M I C l i e n t S o c k e t F a c t ' 5 r y c s f 0 , new S n r n e R M I S e r v e r S o c k e t F a c t n r y ( ) ) //OR Activatable.exportObject(this, " . " , data, false, 0 ) ; //OR P.ctivata~le.exportObject(this, data, false, 0, new S o r n e R I ~ I I C l i e n t S o c k e t F a c t o r y( new S n r n t R M I S e r v e r S o c k e t F a c t o r y ( */ 'I.",
)
,
) ) ;
1
public Strir,g ~ a y H e l l ~ !ttlrk?ws ) RemoteExcey;tinr~{ return "Hello Igi'~-ld,the current system timr i-" i
t
r~ew Date ! ) ;
En el ejemplo anterior, dos de 10s constructores presentados tornan factorias de socket como argumentos. Trataremos las factorias de socket en breve. Por ahora, s610 recuerde que puede pasar factorias de socket como argumentos a sus objetos activables.
lniciar multiples JVMs sin recurrir a rmid r m i d o el activador mismo es un objeto remoto y se ejecuta en una JVM. Cada objeto que es activado es activado en su JVM del grupo de activaci6n pero, en ocasiones, puede ser deseable producir una JVM independiente para cada objeto activable (por ejemplo, en una gran aplicaci6n desearia eliminar el h i c o punto de fallo aislando objetos en diferentes JVM). Es muy sencillo si tenemos en cuenta lo que mencionarnos a1 referirnos a A c t i v a t i o n G r o u p I D , es decir, "Todos 10s objetos con el mismo A c t i v a t i o n G r o u p I D son activados en la misma JVM". Para iniciar mdtiples JVM, el objeto debe tener un A c t i v a t e G r o u p I D diferente o, en otras palabras, debe estar en un grupo de activaci6n independiente. El siguiente c6digo muestra c6mo el mismo objeto H e l l o S e r v e r es registrado de forrna distinta de mod0 que cada objeto tenga u n A c t i v a t e G r o u p I D diferente (y, por consiguiente, un grupo de activaci6n diferente). ~ s t es a la clase que registra nuestros objetos activables: import j ava. rmi. + ; import java. rmi. activation.+; import java.uti1. Properties; public class RegisterIt { public static void rnain(Strir1g [ 1 a r g s ) { try I //Instalar un gestor de seguridad S y s t e r r ~ . s e t S e c u r i t y M a r l a g e r( n e w RMISecurityl4anager (
) ) ;
//
crear otra para una nueva VM Properties erlv = new Properties ( ) ; env.put ( " java. s e c u r ~ t y Y p o 1 i c y Y ' , "file://%BOOK HOME%/Ch03/Activatable/MultiVM/ registerit.policy"); ActivationGroupDesc mygroupdes = new ActivationGroupDesc [er~v, r~~lll) ; ActivationGroupID mygroupid = A c t i v a t i o n G r o u p . g e t S y s t e r n ( ) .registerGroup(mygroupdes); ActivatinnGroup. createGroup (mygr~1upii3,rnygroupdes, 0 ); ActivatinnDesc objectdesc = new ActivationDesc ("HelloServer",
Capitulo 3 "file://%BOOK HOME%/Ch03/Activatable/MultiVM/", null ) ; HelloIrlterface myobject == (HelloIr~terface)Activatable.register( obj ectdesz); Naming. rebind ("hello0bjecttt,myobject) ; / / Registrar otro id de grupo ActivationGroupID mygroupid 2
ActivationGroup.qetSystem() . registerGroup (niygroupdes) ; ActivationDesc objectdesc 2 = new ActivationDesc("HelloServer", "file://%BOOK HOME%/Ch03/Activatable/MultiVM/", riul l ) ; HellcInterface myobject 2 = (HelloInterface)Activatable.rtqister( obj ectdesc 2) ; Naming. rebind ("helloobjectp2", myobj ect-2) ;
]
=
catch (Esceptior~t ) [ System.i'ut .prir~tlrj fe); e.prir~tStackTrace( ) ;
I
El cliente inicia la nueva JVM en el servidor debido a la activaci6n lenta (activaci6n la primera vez que el metodo es invocado): i m p f ~ r tj ava. rml. * ; public class HelloClient
{
public statiz void main(Strir1g args[l) 1 if (arqs.length < 1 ) { System.out.println ("IJsaqe: java HelloClient "); System.exit(l); try 1 Hellotr~terface obj
(HeLloInterface)Namlng.lookup( "rmi://" + args[O] + "/helloObjectn); System.out.println(,>bj.sayHeIlo()) ; =
/ / Producir la sequnda VM en el servidor HelloInterface obj 2 = (HelloInterface)tlaminq.lookup( "rmi://" t arqs[O] t "/helloObject 2"); 2;j)iolH ly e as.2jb oinltnirp. tu om e.tsy Sjb o( sayHe110 ( ) ) ; System.out .prir~tln }
catch (Exception e) { System.out .println ("HelloClier~texception: " e.printStackTrace ( ) ;
t
e.getMessage (
) ) ;
i 1
Si ejecutamos este ejemplo v observamos 10s procesos a1 ejecutar el cliente, veremos que se utilizan dos VM de Java:
Procesamiento distribuido con RMI
Archivo
-I
Opciones
--
---
Nombre de lmagen
--
--
Nombre de usuarlo
-
CPU
Uso de
...
A
explorer.exe java.exe
Isass.exe mstask. exe NAVAPSVC.EXE NAVAPW32.EXE NPSSVC.EXE ns-admin-exe ns-slapd.exe Psp.exe realplay .exe U M o s t r a r procesos de todos los usuarlos
3rocesos: 23
Uso de CPU: 13%
[xi&ETl
:
Carga de transacciones: 1740801
Desactivacion La activaci6n permite a un objeto ser iniciado a petici6n; sin embargo, no desactiva automiticamente un objeto. La decisi6n de desactivar un objeto queda en manos del mismo objeto. U n objeto activable puede desactivarse a si mismo invocando el metodo Activatable.inactive(ActivationID i d ) . Es importante saber la diferencia entre eliminar un objeto del registro y desactivar un objeto. La desactivaci6n es un estado temporal, permitiendo al sistema de activacih reiniciar el objeto mis tarde, mientras que a1 eliminarelobjeto m e d i a n t e ~ c t i v a t a b l e. u n r e g i s t e r ( A c t i v a t i o n I D i d ) , iste queda eliminado permanentemente del sistema de activaci6n. O t r o m i t o d o utilesel m e t o d o ~ c t i v a t a b l e. u n e x p o r t O b j e c t ( R e m o t e o b j , b o l e a n f o r c e ) que puede utilizarse para deshacer la exportaci6n del objeto. El b o o l e a n o es utilizado para forzar al objeto a ser no expoetarse incluso si hay llamadas pendientes o en progreso.
Caoitulo 3
Aunque la activation puede ser u n gran avance en rendimiento cuando el numero de objetos de u n sistema es alto, aliviando el drenaje de 10s recursos, debe tener cuidado a1 decidir corn0 y cuindo utilizarla. El sobregasto necesario para crear y reactivar un objeto inactivo es importante. Puede suponer crear una nueva JVM, cargar, verificar clases y deserializar u n estado de objeto persistente. U n objeto deberia normalmente decidir en tiempo seguro mantenerse vivo. Una buena estrategia de desactivacion podria basarse en el tiempo transcurrido desde la ultima Ilamada.
A continuacion, dirigiremos nuestra atencion a la capa Secure Sockets (SSL). Esta section presupone que el lector esti familiarizado con 10s Sockets T C P I I P y la redificacion en Java.
Sockets de adaptacion y SSL U n socket es un extremo de comunicacion. Dos sockets en colaboraci6n, uno en la miquina local y el otro en la miquina remota, forman una conexion. Esta distincion entre sockets y conexiones es muy importante. Hay dos tipos de sockets, sockets de conexi6n y sockets de escucha, tambiin conocidos como sockets cliente y servidor, respectivamente. U n socket de conexion existe en cada extremo de una conexion T C P abiertay es abstraido por las clases j a v a . n e t . S e r v e r s o c k e t y j a v a . n e t . s o c k e t . U n socket de escucha no e s t i asociado a ninguna conexi6n T C P per0 solo existe como una abstraction para permitir al nucleo T C P decidir q u i proximas conexiones son aceptadas y quiin obtiene el nuevo socket de conexion aceptado. En cualquier momento, RMI tiene algunos sockets de escucha, uno para cada puerto escuchador (normalmente solo uno porque RMI exporta todos 10s objetos en el puerto "por defecto" si n o se especifica un puerto concreto en el mitodo e x p o r t ( ) examinado anteriormente). RMI tambiin crea sockets de conexion para conexiones de salida y para conexiones de entrada. El numero de conexiones de salida solo depende del numero de llamadas de salida concurrentes. La sencilla regla es la siguiente:
o Si un hilo quiere realizar una llamada remota y todas las conexiones a1 extremo estin en uso, entonces el RMI abre una nueva conexion para transportar la llamada 0
Si una conexion e s t i libre (es decir, si n o hay ninguna llamada en progreso utilizando la conexion), entonces el RMI la reutilizari para la siguiente llamada remota
RMI produce un hilo para escuchar cada socket de escucha (normalmente tambiin uno). Cuando RMI acepta una nueva conexion, crea un nuevo hilo (y un hilo controla la nueva conexion y el otro vuelve para aceptar una nueva conexion). Cuando la conexion se cierra, su hilo asociado tambiin se cierra. Los hilos de control de conexiones producidos por RMI n o estin de ning6n mod0 serializados. Si las llamadas llegan a la vez, son ejecutadas en hilos concurrentes. Las llamadas todavia pueden sincronizar objetos Java per0 RMI n o realiza esa sincronizaci6n de forma automitica (el objeto remoto es responsable de su propia sincronizacion, ya sea por mCtodos sincronizados o por bloqueo sincronizado). U n punto habitual de confusion es que si el stub remoto es devuelto por una llamada remota, el cliente puede en ocasiones realizar dos conexiones a1 servidor. Esto ocurre porque el subsistema distribuido de recolecci6n de residuos necesita realizar una llamada D G c d i r t y ( ) para notificar a1 servidor que una nueva entidad alberga una referencia a1 objeto remoto.
.
Procesamiento distribuido con RMI Puede utilizar netstat para controlar 10s sockets de escucha. La siguiente captura de pantalla muestra 10s sockets justo despuis de que se inicie el registro en 1099. Helloserver es exportado a 2000 y esta' asociado a1 re~istro. La columna de la izauierda enunzera 10s sockets abiertos de la ma'nuina. La u primera linea es para el registro, la segunda para el objeto. La tercera muestra que un socket ha sido abierto por el objeto a1 registro y la riltinza linea nruestra el socket abierto por el registro a1 objeto.
Una n~ejoranotable que ha sido afiadida a RMI desde la entrega 1.2 de Java ha sido la capacidad de utilizar factorias de sockets de adaptaci6n basados en el modelo de disefio Factory. En lugar de utilizar 10s sockets convencionales en TCP/IP, cada objeto tiene la capacidad de utilizar su propio tip0 de socket. Esto permite al objeto procesar datos (cn vez dc pasnrlos simplemente), ya sen antes de ser enviado al socket o despues de ser recibido por Cste. En J D K l.l.x, fue posible crear un.1 subclase de adaptation j ava . rml .RMISocket Factory que produjo un socket d e adaptaci6n. difcrcnte a 1ava .net . Socket,para ser utilizado por la capa de transporte de RMI. Sin embargo, n o fue posible para la factoria de socket instalada producir diferentes tipos de sockets para diferentes objetos. Por ejemplo, en J D K 1.1, una factoria de socket de RMI n o podia producir sockets Secure Sockets Layer (SSL) para un objeto y utilizar el Java Remote Method Protocol (JRMP) directaniente sobre T C P / I P para un objeto diferente en la misma JVM. Adenlis, antes de la versi6n 1.2, era necesario que rmiregist ry utilizara hnicamente el protocolo de socket de adaptaci6n del usuario. La factoria d e socket afectaba a1 sistema completo y n o s61o a un objeto. Para entender q u i significa realmente esta afirmaci6n, veamos primer0 donde intervienen 10s sockets de arquitectura M I , sus tipos y sus prop6sitos: Posici6n
Socket d e servidor
Socket d e cliente
Rcgistro RMI
Abre un socket d e servidor (puerto por dcfecto 1099) y espera solicitudes de:
Utiliza un socket de cliente para establecer una conexi6n a un objeto servidor justo despues de haberse registrado.
U Servidores para asociar, reasociar,
y desasociar in~plementacionesde objeto. Clientes que desean localizar servidores. Servidores RMI (implementaci6n remota).
Abre un socket de servidor en un puerto especificado por el usuario via m i t o d o exportOb j ect ( ) o, por defecto, a un puerto local aleatorio; es utilizado para aceptar conexiones de las res uestas enwadas por el cliente (el s t u t ) .
U n socket d e cliente es utilizado mientrasseconectaalre istro,en concreto para registrar a implementaci6n del servidor.
Clientes RMI (objetos que invocan metodos remotos).
N o s e utiliza.
Los sockets de cliente son utilizados para la comunicacion con el registro RMI, ara localizar la implementacidn i e servidor araconseguirqueelrnktodoRd l a m e a1 servidor.
9
Capitulo 3
\
/'
,
-1 ,~Naming.bind('HelloSe~eV,obj;) \ >.
Objeto
'
,remOto I' _ , , '
,
1';
i
! I
Socket de S e ~ d 0 Ir
Socket de servidor
t
9I
i
Devuelve el stub
1
Socket de cliente
1
13
. Cl~ente 1 - - Invocac~onde metodo
-
-
.
-
Cuando un cliente ejecuta una operaci6n de "blisqueda", se realiza una conexi6n a1 socket de servidor en el r m i r e g i s t r y . En general, puede crearse o no una nueva conexi6n para una llarnada rernota. La capa de transporte RMI acumula conexiones para usos futuros. Si alguna conexi6n existente, y a1 menos una de ellas esti libre, entonces se reutiliza; de no ser asi, la implementaci6n actual crea sockets adicionales a peticibn. Por ejernplo, si un socket existente esti siendo utilizado por una llamada existente, entonces se crea un socket nuevo para la nueva Ilamada. Normalmente, hay como minimo dos sockets abiertos puesto que el recolector de residuos distribuidos necesita realizar llamadas remotas cuando 10s objetos remotos son devueltos desde el servidor. Un cliente no tiene control explicit0 sobre las conexiones a un servidor, ya que las conexiones son gestionadas en el nivel de la capa de transporte RMI. Las conexiones expirarin si se mantienen sin utilizar durante un tiempo. Corno puede ver, existe un numero de puntos de comunicacidn y sockets que son utilizados en este proceso de comunicacidn de tres vias entre el cliente, el registro y el objeto. Es tambikn importante destacar que el registro s61o es necesario para localizar un objeto por su nombre. Una vez que el objeto esti localizado, hay comunicaci6n directa entre el objeto y el cliente. U n objeto puede especificar que clases de factoria son necesarias para que alguien se comunique con este tipo de socket a travts del constructor j a v a . r m i . s e r v e r . U n i c a s t R e m o t e O b j e c t ( o j a v a . r m i .a c t i v a t i o n . A c t i v a t a b 1 e para ese asunto). Instancias de esas factorias s o n u t i h a d a s para crear instancias de 10s tipos de sockets deseados: protected UnicastRernoteObject(int port, RMIClientSocketFactory RMIServerSocketFactory ssf)
csf,
C o m o hemos explicado en la tabla anterior, una vez que el cliente ha localizado un objeto, utiliza un socket de cliente para conectar a1 socket de cliente que esti escuchando el objeto. La factoria de socket de cliente debe implementar la interfaz j a v a . r m i . s e r v e r . m I S o c k e t F a c t o r y . Elsocket de cliente es creado desde esta instancia d e ~ ~ ~ ~ o c k e t ~invocando a c t o el r ~ m k t o d o c r e a t e s o c k e t ( ) que devuelve una instancia del tip0 de socket adaptado al servidor y a1 puerto especificados: public
Socket createsocket (String host, int port)
La factoriadesocket deservidordebeimplementarlainterfazj a v a .r m i .s e r v e r . R M I S e r v e r S o c k e t F a c t o r y y proporcionar una implernentaci6n para el metodo c r e a t e s e r v e r S o c ke t ( ) . El socket de servidor es creado (para empezar a escuchar llamadas entrantes) invocando la implernentacion de rnetodo en la clase de factoria de socket de servidor:
Procesamiento distribuido con RMI public Serversocket createServerSocket(int port)
Esto es especialmente fitil cuando se desea cifrar la comunicaci6n entre 10s objetos. Por ejemplo, utilizando SSL o TLS. Examinemos un ejemplo de c6mo se puede realizar. Primero necesitariamos un par de cosas, siendo la principal un proveedor de seguridad que proporciona una implementaci6n del protocolo SSL en Java. Muchos productos terceros disponibles hacen esto. SSL y TLS proporcionan ambos cifrado y certificaci6n. En realidad, Transport Layer Security (TLS) es la nueva norma de Internet Engineering Task Force (IETF) y est6 basada e n SSL. Las especificaciones SSL puede encontrarlas en http:llhome.netscape.comlenglsecurityl y las especificaciones TLS se encuentran en RFC 2246 en http:llwww.ieff.org.lrfclrfc2246.&t. Los detalles sobre las implementaciones SSL de fuente abierta (SSLeaylOpenSSL) puede encontrarlas en http:llwww. opnessl. org. ,
Sun ofrece Java Secure Sockets Extension USSE) que implements una versi6n Java de 10s protocolos SSL y TLS e incluye funcionalidad para el cifrado de datos, autentificacidn de servidor, integridad de mensaje y autentificacion optional del cliente. El ejemplo examinado aqui utiliza JSSE. Necesitara' descargarlo de f o n a independiente para J2SE (1.2 o 1.3) y sera'n incluido en J2SE (1.4), vkase http://java.sun.com/products,!jsse/para ma's infonacidn.
Se va producir un rendimiento suplementario y la comunicaci6n va a ser muy lenta debido a la complejidad del acuerdo inicial y el cifrado que supone. El mod0 en el que el proveedor implementa el algoritmo afectari tambiin el rendimiento. Por ejemplo, una implementation nativa como GoNative Provider (http:/ /www.rtfm.corr\/puretls/gonative.html) es mis ripida que su equivalente Java. Intenternos primer0 analizar quC parte de la comunicaci6n queremos/necesitamos cifrar. El registro de designaci6n es implementado como un servicio RMI estindar por lo que 10s intentos de registrar y buscar servicios supondrin el establecimiento de conexiones de red. Si necesita que la comunicaci6n con el registro tenga lugar en sockets seguros, el registro de designaci6n obviamente necesitari escuchar sobre sockets seguros de servidor. U n mod0 muy direct0 de conseguirlo es que el servidor inicie su propio registro de designacion. Este registro se beneficiari entonces del apoyo SSL del servidor. El servidor necesitari invocar y configurar explicitamente una factoria de socket e iniciar el registro: RMISocketFactory.setSocketFactory (some vendor provided factory); LocateRegistry.createRegistry(somep~rt);
La factoria de socket SSL puede entonces ser instalada en el cliente antes de buscar el objeto y todo quedari asegurado por SSL. Puesto que el mismo socket n o puede escuchar en dos puertos, seria necesario ejecutar dos registros: u n o seguro y u n o normal, si necesitara buscar e n diferentes protocolos. La mayoria d e 10s vendedores proporciona u n registro seguro con la implementaci6n Java-SSL que puede ser utilizado si n o estd iniciando el registro programdticamente. En la mayoria de 10s casos, s6lo es importante y necesita cifrado la comunicaci6n entre 10s objetos, no la bGsqueda; esto es lo que estudiaremos en el siguiente ejemplo. Para que la comunicaci6n tenga lugar sobre
Capitulo 3 SSL o TLS, necesitamos dos cosas: claves y certificados. Para mis informaci6n sobre estos dos elementos, consulte 10s vinculos a la documentaci6n SSL y TLS. Antes de seguir adelante, generamos4as claves y certificados utilizando la utilidad JDK k e y t o o l . ~ s t es a una herramienta de gesti6n de certificados utilizada para gestionar pares de claves pfiblicas/privadas y certificados asociados que deben ser utilizados en auto-autentificacih y en servicios de integridad y autentificacidn de datos, utilizando firmas digitales. En un entorno comercial, probablemente utilizaria k e y t o o l para generar una solicitud de certificado y utilizaria esa solicitud para obtener un certificado de una Autoridad de Certificados (CA) como Verisign (http://www.verisign.com). Para nuestros prop6sitos, generaremos un certificado autofirmado (un certificado de la CA autentificando su propia clave pliblica). En otras palabras, utilizaremos nuestras propias claves y certificados utilizando la opci6n - g e n k e y en k e y t o o l . Ejecute la utilidad k e y t o o l con parimetros similares a istos:
Podemos coniprobar el certificado utilizando k e y t o o l de un mddo distinto:
Esto genera un almacin de claves llamado " w r o x " que contiene las claves y el certificado auto-firmado y contiene la contraseiia "secreta".
Consulte la documentacidn adjunta a J D K para m i s detalles sobre c6mo utilizar kqytool, las claves y 10s certificados en la arquitectura de seguridad de Java 2. Finalmente, tambiCn exportamos el certificado generado a un archivo c l i e n t i m p o r t . cer para el uso de clientes que u t i l i c e n k e y t o o l : L : e y ~ c ~ , =-~elx ~ ' r . i t -t:eystore %BOOK_HOME%\Ch03\SSL.\. k e y s t o r e s e c r e t - f i l e c l l e n t i m p o r t . c e r -alias w r o x
-store$ass
Recuerde que n o estamos utilizando SSL basado en navegador en ningkn fragment0 de estos ejemplos. Si desea utilizarlo, necesitard generar certificados con el algoritmo RSA (utilice la opcidn -keya lg en keyt 001).Para esto, necesitard instalar un proveedor que ofrezca la implementacidn del algoritmo RSA puesto que J D K 1.2 n o se ajusta a esta implementacidn. Para nuestros propdsitos, el proveedor JSSE contiene una implementacidn y el apoyo RSA estd incorporado en J D K 1.3. Tambibn, la implementaci6n J C E de libre distribuci6n disponible en http://www.openjce.orges un buen proweedor de API de seguridad. Volvamos ahora a1 ejemplo H e l l o w o r l d que utilizamos anteriormente y rescribimoslo, para asegurar la comunicaci6n de objeto a objeto. D e nuevo, la interfaz remota se mantiene igual:
Procesamiento distribuido con RMI import java.rmi.Remote; import java.rmi.RemoteException; public interface HelloInterface extends Remote { public String sayHello ( ) throws RernoteException;
Ahora rescribimos la implementaci6n remota de esta interfaz: import j ava. rmi . * ; import java.rmi.server.UnicastRemoteObject; import java.uti1. Date; public
class HelloServer extends UnicastRemoteObj ect implements HelloIrjterface { public H e l l o S e r v e r O throws RemoteException { super ( 0 , n e w MyClientSocketFactory ( ) , n e w MyServerSocketFactory
( ) ) ;
I public String sayHello() { return "Hello World, the current system time is
"
t new Date();
I 1
Observe que la h i c a diferencia es que pasamos nuestras propias factorias de adaptaci6n que serin utilizadas para este objeto en lugar de las factorias por defecto. Ahora utilizamos el mismo programa que utilizamos antes para registrar este objeto remoto: import j ava. rmi. + ; public class RegisterIt
{
public static void main(String a r g s [ ] ) [ try 1 / / Ir~stanciar el objeto HelloServer obj = n e w HelloServer ( ) ; System. o u t .println ("Object instantiated" tobj ) ; Naming. rebind ("/HelloServer", obj ) ; System. o u t .println ("HelloServer bound i n registry" ) } catch (Exception e) { System.out.println(e);
;
1
I I
Estas sentencias que hemos pasado tan ficilmente son las factorias de sockets. Examin6moslas ahora en detalle. La c l a s e ~ ~ ~ e r v e r ~ o c k e t y~ es a cutilizadapara tor crear instancias del socket de servidor en el puerto a1 que fue exportado el objeto. Esta clase debe implementar la interfaz j a v a . rmi .server. ~ ~ ~ ~ e r v e r ~ o c k e t ~ a debeserserializable ctoryy (parafacilitarposibles transportes en la red). El intercambio seguro entre el cliente y el servidor conlleva un intercambio de claves y certificados y el socket creado debe primer0 inicializar la comunicacidn con el cliente antes de intercambiar ningGn dato. La implementaci6n JSEE nos permite realizar esto en unas cuantas lineas de c6digo. Abrimos el almacin de claves (que hemos generado) del archivo utilizando su contraseiia, inicializamos la implementaci6n SSLITLS y devolvemos una instancia de un socket seguro: import import import import import
j a v a .i o . + ; j ava. net. + ; j a v a . rmi. server. + ; java.security.+; javax.net. s s l . + ;
Capitulo 3 import javax.security.cert.*; import com.sun.net . s s l . + ; publlc class MyServerSocketFactory
implements RMIServerSocketFactory, Serializable { / / Implementar el metodo d e interfaz publlc Serversocket createServerSocket(int port)throws IOException { SSLServerSocketFactory s s f = null; try i / / Configurar el gestor de seguridad para la autentlficacibn de servldor char [ I passphrase = "secret". toCharArray ( ) ; //
Obtener un contexto para el protocolo. Podemos utilizar SSL o TLS seg6n sea necesario SSLContest ctx = SSLContext. getIr~stance( " T L S " ); KeyManagerFactory k m f = K e y M a n a g e r F a c t o r y . g e t I n s t a r ~ c e( " S u n X 5 0 9 " ); / / Abrir el almacen d e claves con la contraseAa / / e inicializar el contexto SSL con este alrnackn d e claves KeyStore k s = KeyStore.getInstance ( " J K S " ); ks. load ( n e w FileInputStrearn keystore"), passphrase) ; kmf.init(ks, p a s s p h r a s e ) ; ctx. init (krnf.getKeyMar1agers ( ) , null, null); s s f = ctx.getServerSocketFactory ( ) ; catch (Exception e ) { e.printStackTrace0; ( ' I .
}
I r e t u r n ssf.createServerSocket(port);
1
La factoria de socket de cliente es utilizada para crear instancias de 10s sockets de cliente que conectan alas instancias de 10s sockets de servidor generados en la factoria anterior. Se supone que el proveedor JSSE tarnbikn esti instalado en la rniquina cliente: import import import import
j ava. io. + ; j ava . net. * ; java.rrni.server.*; javax.net.ssl.*;
public class MyClientSocketFactory public
implemerlts RMIClientSocketFactory, Serializable {
Socket createsocket (String host, int port) throws IOException
{
/ / Obtenemos la factoria d e socket SSL por defecto. SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault(); SSLSocket socket = lSSLSocket)factory.createSocket.(host, port); return socket;
El cliente se rnatiene igual: import java.rmi.Narning; import ]ava.rmi.RemoteExceptian; public class Helloclient
{
public static void main(String a r g s [ ] ) { if (args.length < 1 ) {
Procesamiento distribuido con RMI System.uut .println ( " U s a g e : j a v a System.exit{l);
Helloclient
" ) ;
1 try{ HellaIntetfacr
1
nb]
= ! H e l l o I r ~ t e r f a c e ) E l a m i n gl .u o k u p (
"rmi://" t args[O] + "/HelloServer"); S y z t e m . o i ~ t . p r i n t l n["Got a r e m o t e r e f e r e n c e " + obj ) ; S y s t e r n . o u t . p r l n t l r ~ i o b j. s a y H e l l o ( ) ) ; catch (Exception e ) 4 System.out.println(e);
I
El archivo ssl .policy que utilizarnos aqui es en realidad el misrno que utilizarnos en 10s ejemplos an teriores: grant [ permission
I
java. secutity.Al1Permission;
;
Ahora podemos cornpilar las clases y generar 10s stubs para Helloserver utilizando el rmic ernpaquetado con el JDK.
Es preciso exarninar dos pequeiios detalles antes de ejecutar el ejernplo. Para que el cliente interactue e intercarnbien contraseiias y certificados con el servidor, debe confiar en el proveedor del certificado digital. En otras palabras, conio nuestro certificado es auto-generado, la mdquina virtual cliente debe: Importar explicitarnente el certificado en el almacen de claves que esti utilizando y rnarcarlo corno certificado confiable Utilizar el rnisrno alrnackn de claves que utilizanios en el servidor Para la segunda opcibn, el proveedor JSEE debe ser instalado en la rndquina cliente (si es diferente del servidor) en uno de dos rnodos posibles: 0 Estiticarnente en el archivo j ava .security 0 Dinirnicamenteutilizando~ecurity. addprovider (new com.sun.net.ssl.internal.ss1.Provider 0 ) ;
Para detalles m b espec$cos sobre estos me'rodos de ins&alnci6n, el lector puede recwrrir a la docwmenmcicin JSSE.
El cliente puede iniportar el certificado desde el archivo que hernos generado anteriormente, clientimport. cer, al alniacCn de claves que esti utilizando y rnarcarlo corno confiable utilizando keyt ool con la sentencia -import:
Capitulo 3 Una vez realizado esto, primero necesitamos iniciar el registro en el servidor (ejecutar rmiregistry): r n i i r e < ~ i . s t r y- J - D j a v a . s e c u r i t y . ~ ~ r . l i c y = s s l . ~ " ~ L i c y
registrar entonces el objeto con el registro:
-
1;1.:a - c l a s s ~ a t h % C L A S S P A T H S - U j a v a . . s e c u r i t y . ~ c ~ l i c ~ ~ = . pc, '?~Lli c y E s ] a v a . r r n i . s ~ r v e r . c ~ ~ ~ e k a i l ~ = f i 1 r : / / r ( -l H BOOMOE +~/ 1 3 h O ? / S - C L / R?qi~trrIt
Recuerde instalar con cuidado JSEE. Ponga 10s archivos jar en su localizaci6n \lib\exte instale el proveedor en su archivo java. Security (viase el archivo INSTALL.txt dentro del lote JSEE para rnis detalles). Si tiene mliltiples entornos de period0 de ejecucion, aseglirese de editar el archivo de seguridad correcto. La solucion rnis sencilla es configurar el PATH para que s61o apunte el JDK que esti utilizando.
Ahora ejecute el cliente y especifique,el aln~acende claves a utilizar utilizando la propiedad JSSE j a v a x . net. ssl . truststore. Este es el~lmacknde claves en el que ha sido importado el certificado o el mismo almacen de datos como servidor.
Si queremos que el cliente sea un applet, necesitamos primer0 resolver algunos puntos de configuration: 3 El cliente debe tener una JVM J2SE 1.2 (o posterior). En el momento de publicaci6n de este libro, Netscape 6 y 6.1 son 10s Gnicos navegadores con soporte J2SE 1.2. Por lo tanto, probablemente
necesitemos instalarel mddulo complementario de Java. (Este mddulo es de descarga Gnica y actualiza automiticamente laJVM del navegador a la Gltima versi6n. Funciona tanto con IE como con Netscape.) U La JVM cliente debe tener el almacen de claves y 10s certificados adecuados instalados.
0 La JVM cliente deberia tener la politica correcta, permitiendo que 10s sockets sean abiertos de nuevo al servidor. 0 La JVM cliente deberia tener el proveedor de seguridad instalado o tener 10s permisos de seguridad adecuados de mod0 que pueda instalarse un proveedor de seguridad dinimicamente.
O Puede acceder a mls informaci6n y descargas para el modulo complementario de Java en http:// java.sun.com/products/pluginl.
Procesamiento distribuido con RMI Examinemos el siguiente applet. Es sencillo, similar a1 ejemplo que hemos visto antes, except0 que se trata de un applet. Es importante captar que el applet n o tiene nada que ver con la configuraci6n SSL del navegador. La conexi6n SSL tiene lugar a nivel del socket RMI. La clase de factoria de socket de cliente es descargada dinimicamente y se realiza la conexi6n segura a1 servidor: import import import import
java.applet.*; j ava. awt . * ; j ava. rmi. * ; j ava. security. * ;
public class SSLHelloApplet extends Applett String message
=
"-n/a-";
HelloInterface obj
=
null;
/ / Obtener una referencia a1 objeto durante el inicio del applet public void init ( ) [ try I Security. addprovider ( n e w com. sun. net. ssl. internal. ssl. Provider ( ) ) ; String host="rmi://" + getCodeBase().getHost() + "/Helloserver"; HelloInterface obj = (HelloInterface)Naming.lookup( "rmi://localhost/HelloServer"); message = obj . sayHello ( ) ; 1 catch (Exception e ) { System.out.println(e);
1 / / Mostrar un mensaje en el applet public void paint(Graphics g)[ g.drawString(message, 25, 5 0 );
1 1
A continuaci6n, la pigina HTML ( i n d e x . html) para el applet anterior. Esta pigina es convertida utilizando la herramienta conversora HTML empaquetada con el m6dulo complementario de Java. Cuando un cliente se encuentra con esta pigina, si no existe una versi6n compatible, el JRE 1.3 seri descargado del URL especificado. (La pigina Web de Sun en este caso):
The message from the Helloserver is:
Capitulo 3 < p a r a m n a m e = " s c r i p t a b l e n VALUE="false">
Cuando se accede a la pigina anterior desde el navegador, el navegador determina a partir de 10s etiquetas que un plug-in URE 1.3) es necesario para cargar este componente y le insta a descargarlo desde la ubicacibn especificada en el parimetro pluginspage ( o codebase, dependiendo del navegador); esto es asi, por supuesto, asumiendo que n o esti ya instalado:
Hello World The mcssaae born OK HelloServu is:
-._.
.
1
A
Una vez descargado e instalado el plug-in y una vez lo hayamos habilitado desde su consola en nuestra miquina, podemos acceder a la misma pigina. El navegador lo cargari entonces en la nueva JVM Java 1.3 (y no en la JVM por defect0 del navegador). Llegados a este punto, necesitamos asegurarnos de que afiadimos 10s padmetros de period0 de ejecucibn necesarios para el plug-in utilizando el applet J a v a P l u g - i n en C o n t r o l P a n e l . Necesitamos aAadir 10s parimetros-Djava. S e c u r i t y . p o l i c y y - D j a v a . n e t .ssl.trustStore.Enesteejemplosedn:
Procesamiento distribuido con RMI
Enable Java Plug-in
B Snow Java Console Ei Cache JARS in memory
Java Run Tittle Parameters
I
~-0)arasecuritypolic~C:I~roJaaSe~e~ChO3ISSL'r~~lpolic~
Finalmente, debemos obtener u n resultado similar al siguiente:
Hello World, Me current system lime 15Wed Aug 22 15-1100 FmT*OI 00 2001
Se puede acceder al m i s m o URL u t i l i z a n d o a p p l e t v i e w e r :
Capitulo 3
Hello World, the current system time is Wed Aug 22 12:24:11 GMT+01:00 2001
Applet starled.
RMI, cortafuegos y HTTP Si ha trabajado en cualquier empresa redificada, probablemente estC familiarizado con como 10s cortafuegos bloquean t i d o el thfico de la red, a'excepci6n de 10s destinados a ciertos puertos "conocidos". Sin embargo, son necesarios para proteger la seguridad de la red. Puesto que la capa de transporte RMI abre conexiones dinimicas de socket entre el cliente y el servidor, el trifico JRMP es normalmente bloqueado por la mayoria de las implementaciones de cortafuego. RMI proporciona un rodeo para esto. Hay tres metodos principales para evitar 10s cortafuegos: Tunelado H T T P 0 SOCKS
Factorias de socket descargadas Examinaremos cada uno de estos mitodos sucesivamente.
Para cruzar cortafuegos, RMI hace uso del tunelado H T T P encapsulando las llamadas RMI en una solicitud H T T P POST. Este mttodo esti muy extendido ya que no requiere apenas configuraci6n y funciona bastante bien en entornos de cortafuego que permiten el manejo de HTTP a travCs de un proxy, pero rechaza las conexiones T C P salientes regulares. Existen dos formas de tunelado HTTP:
H l l P a puerto Si un cliente esti detris de un cortafuegos y RMI no consigue realizar una conexibn normal a1 servidor, la capa de transporte RMI lo reintenta automiticamente encapsulando 10s datos de llamada JRMP en una solicitud H T T P POST.
Procesamiento distribuido con RMI Puesto que casi todos 10s cortafuegos reconocen el protocolo HTTP, el servidor proxy especificado deberia poder enviar la llamada directamente a1 puerto en el que el servidor remoto esti escuchando. Es importante que la configuration del servidor proxy sea pasada a la JVM cliente. Una vez que 10s datos JRMP encapsulados en H T T P son recibidos en el servidor, -RMI puede desenvolver automiticamente la solicitud tunelizada H T T P y decodificarla. La respuesta es enviada entonces de vuelta a1 cliente como datos encapsulados en HTTP. La configuraci6n del servidor proxy puede ser pasada utilizando propiedades tales corno: java
-Dhttp.proxyHost=hostname
-Dhttp.proxyPort=portriumber
Helloclient
El tunelado H T T P puede ser inutilizada configurando la propiedad:
HTTP a CGI Si n o se puede contactar con el servidor desde el cliente, incluso desputs de el tunelado, porque tambitn este se encuentre detris de un cortafuegos, la capa de Transporte RMI utiliza un mecanismo similar en el servidor. La capa de Transporte RMI sitGa las llamadas JRMP en las solicitudes http y envia esas solicitudes, del mismo mod0 que el mttodo anterior. Sin embargo, en lugar de enviarlas a1 puerto servidor, las envia a http://hostname:80/cgi-binljava-rmi?fo~ward=. Debe haber un servidor H T T P escuchando en el puerto 80 en el proxy, que tiene el script j ava-rmi .cgi. El java-rmi.cgi a su vez invoca una JVM local, desenvuelve el paquete http y envia la llamada a1 proceso servidor en el puerto designado. Las respuestas basadas del servidor en JRMP RMI son enviadas de vuelta como paquetes H T T P a1 puerto cliente originario donde RMI desenvuelve de nuevo la informaci6n y la envia a1 stub RMI adecuado.
.
El script j a va -rmi cgi esta' empaquetado con J D K y puede encontrarlo en el directorio b i n Para evitar cualquier problema de resobcio'n DNS en el arranque, el nombre calificado completo del host debe ser especificado mediante una propiedad de sistema corno:
Una implementacio'n de serulet del CGI llamada manejador de serulet esta' disponible en Sun en: http:lljava.sun.comlj2sell.3/docslguidelrmilarchiveslrmise~/ethandler.zip.
Otra alternativa a j ava-rmi . cgi es utilizar un redirector de puerto (por ejemplo, DeleGate proxy) en el puerto 80 que acepte conexiones y las redirija inmediatamente a otro puerto. Aunque el tunelado H T T P es una alternativa, en general deberia evitarse por las siguientes razones: O
Hay una significante degradaci6n del rendimiento. Durante el tunelado, la aplicaci6n RMI n o podri multiplexar las llamadas JRMP en una dnica conexi611, debido a1 paradigma H T T P solicitudrespuesta.
o Utilizar el script java-rmi-cgi (o servlet) es una gran trampa de seguridad en el servidor. El script redirige cualquier solicitud entrante a cualquier puerto, circunvalando por completo el cortafuegos. 0 Las aplicaciones RMI tunelizadas sobre H T T P no pueden utilizar retrollamadas.
El protocolo SOCKS SOCKS (SOCKet Server) es un protocolo proxy de red que habilita a 10s hosts de un lado del servidor SOCKS para obtener acceso completo a 10s hosts del otro lado del servidor SOCKS sin requerir
Capitulo 3 accesibilidad I P directa. El servidor SOCKS redirige las solicitudes de conexi6n procedentes de hosts situados en lados opuestos de un servidor SOCKS (el servidor SOCKS autentifica y autoriza las solicitudes, establece un proxy de conexi6n y retransmite datos). Por defecto, 10s sockets JDK utilizan un servidor SOCKS si esti disponible y configurado. Sin embargo, 10s sockets de servidor no se ajustan a SOCKS por lo que este enfoque s61o es util para llamadas salientes desde el cliente a1 servidor.
Factorias de sockets descargados Ya hemos examinado con detenimiento c6mo pueden utilizarse 10s sockets de adaptaci6n. Las clases de factoria pueden codificarse para funcionar alrededor de un cortafuegos. Las factorias de sockets cargados dinimicamente ofrecen una buena alternativa a el tunelado HTTP, per0 para que el c6digo supere el cortafuegos debe ser codificado en las factorias. Esto es posible si tiene una configuraci6n de red fija y sabe c6mo funciona ese determinado cortafuegos. Sin embargo, diferentes clientes pueden tener diferentes cortafuegos y existen distintas cuestiones referentes a derechos de acceso para proporcionar este tunelado y, por supuesto, clases de factoria variables.
RMI sobre Internet Inter-Orb Protocol (IIOP) integra procesamiento distribuido sometido a CORBA (Common Object Request Broker Architecture) directamente en Java. RMI sobre IIOP, desarrollado conjuntamente por IBM y Sun, es una nueva versi6n de RMI para I I O P que combina las sencillas caracteristicas de programaci6n de RMI con la interoperatividad de CORBA. RMI y CORBA han evolucionado de forma independiente como modelos de programaci6n de objetos distribuidos. RMI fue introducido para proporcionar un sencillo modelo de programaci6n para desarrollar objetos distribuidos mientras que CORBA es un modelo de programacion de objetos distribuidos muy conocido que se ajusta a una serie de lenguajes. El protocolo I I O P conecta productos CORBA de diferentes vendedores, asegurando la interoperatividad entre ellos.
El Grupo de Gestidn de Objetos (Object Management Group, O M G ) , visite http:llwww.omg.orgl, es el guardirin oficial de informacidn para C O R B A y I I O P , incluido las especijicaciones C O R B A 2.0 disponibles en http:llwww. omg. orgltechnologyldocumentslspecifications. htm. Adicionalmente, el I D L para representacidn Java se encuentra disponible en http:llwww.omg.orgl technologyldocumentslformallcorba~languagemapping~specs.htm. RMI-IIOP es, hasta cierto punto, un matrimonio de RMI y CORBA, ya que las interfaces remotas pueden ser escrita's en Java e implementadas utilizando 10s API RMI de Java. Estas interfaces, sin embargo, pueden ser implementadas en cualquier otro lenguaje que se ajuste a una representaci6n O M G y a un O R B surtido por un vendedor para ese lenguaje. De un mod0 similar, 10s clientes pueden ser escritos en otros lenguajes, utilizando IDL derivados de las interfaces remotas Java.
Procesamiento distribuido con RMI
JRMP
Cl~enteRMI
Se~dorRMl
(solo Java)
Cl~enteCORBA (cualquler lenguaje)
*
C
llOP
(solo Java)
'
SeNldor CORBA
1
(cualqulerlenguaje)
ualquler lenguaje)
La figura anterior resume el rnatrirnonio RMI-IIOP. Puede parecer que las flechas que conectan 10s clientes /sewidores JRMP a 10s clientes /sewidores RMI-IIOP estin ma1 situadas porque son protocolos diferentes. Estas flechas estin realrnente donde deben estar porque RMI-IIOP se ajusta a 10s dos protocolos, JRh4P y IIOP. U n o de 10s objetivos iniciales de diseho era conseguir que la rnigracidn a I I O P fuera factible, y de hecho ficil, y evitar la necesidad de un tercer rnodelo distribuido a aprender por 10s desarrolladores. El objeto servidor creado utilizando el API Rh4I-IIOP puede ser exportado corno objeto que se ajusta aJRMP o corno objeto que se ajusta a I I O P sirnplernente carnbiando las propiedades de tiernpo de irnplernentaci6n (sin carnbiar o recornpilar c6digo). RMI-IIOP tarnbikn se ajusta a la exportaci6n dual, lo que significa que un linico objeto servidor puede ser exportado para ajustarse a JRh4P y a I I O P sirnultinearnente.
lnteroperatividad con CORBA U n cliente Rh4I-IIOP no puede necesariarnente acceder a todos 10s objetos C O M A existentes. La sernintica de 10s objetos C O M A definida en IDL es un grupo de la sernintica obedecida por 10s objetos RMI-IIOP, que es la raz6n por la que un IDL de objeto C O M A existente no puede siernpre ser representado en una interfaz Java RMI-IIOP. S61o cuando la sernintica de un deterrninado objeto C O M A resulta corresponder con la de RMI-IIOP, un cliente RMI-IIOP puede llarnar a un objeto C O M A . La conexi6n entre el cliente RMI-IIOP y el sewidor C O M A es en ocasiones (pero no siernpre) posible. Sin embargo, la cuesti6n no deberia exagerarse porque s61o se aplica a1 tratar con objetos CORBA ya existentes. Fijindonos en la parte inferior de la figura, si disefiarnos un objeto nuevo con una interfaz Java Rh4I-IIOP, podernos realizar las siguientes observaciones:
Capitulo 3 0 La implementacidn CORBA: puede automiticamente generar su correspondiente IDL con la herramienta r m i c . Desde este archivo IDL, puede implementarlo como un objeto CORBA en cualquier lenguaje aceptable, como C + po;ejemplo~~steobjeto C + + es un puro objeto CORBA que puede ser llamado por un cliente CORBA, asi como por un cliente RMI-IIOP sin ninguna limitacibn. Para el cliente RMI-IIOP, este objeto CORBA C + aparece como un puro objeto RMI-IIOP porque esti definido por una interfaz Java RM-IIOP.
+
+
0 La implementaci6n RMI-IIOP: el objeto aparece como un objeto CORBA a un cliente CORBA (porque un cliente CORBA puede acceder a 61 a travis de su IDL) y como un objeto RMI para clientes RMI (porque acceden a 61 a travis de su interfaz Java RMI-IIOP).
Resumiendo, la diferencia entre un objeto CORBA y un objeto RMI-IIOP es s d o una cuesti6n de implementacibn. Una de las razones de 10s ~roblemascon 10s obietos existentes mencionados anteriormente es aue dos mejoras significativas de las especificaciones CORBA 2.3 fueron realizadas en realidad para conseguir la interoperatividad de RMI-IIOP y CORBA. O M G acept6 estas especificaciones: 0
Especificaci6n de objetos por valor: este concept0 ya esti definido en Java en forma de Serializaci6n de objetos y esti destinado a conseguir que otros lenguajes implementen un protocolo similar.
0
Especificaci6n de representacibn Java e n IDL: ista es la representaci6n utilizada para convertir las interfaces de Java RMI en definiciones CORBA IDL. N o deberia confundirse con la representacidn IDL en Java definida en CORBA 2.2.
Ambas especificaciones estin disponibles en O M G y tambiin puede acceder a ellas en http://java.sun.com/ products/rmi-iiop/index.html.O M G ha aceptado oficialmente ambas especificaciones para CORBA 2.3 y JDK 1.3 para incluir RMI-IIOP y un compilador IDL en Java.
Escribir programas con RMl-llOP Existen algunas diferencias de desarrollo en sintaxis aunque el modelo en su totalidad sigue siendo el mismo; significativamente, RMI-IIOP utiliza el API J N D I para localizar y registrar objetos. Aunque el procedimiento de desarrollo para RMI-IIOP es pricticamente el mismo que el de RMI URMP), el entorno de period0 de ejecuci6n es notablemente diferente en cuanto que la comunicaci6n se realiza a travis de un ORB sometido a CORBA 2.3 aue utiliza I I O P Dara la comunicaci6n entre servidores v clientes. Examinemos brevemente estas diferencias.
En el servldor N o hay ning6n cambio significativo en el procedimiento de desarrollo para objetos RMI en RMI-HOP. Los pasos bisicos y su orden es el mismo que hemos descrito antes en nuestro ejemplo HelloWorld, con algunos cambios que tambiin reflejan el uso de J N D I para buscar y asociar objetos.
import j ava. rmi. + ; import java.uti1 .Date; import javax.rmi.PortableRemoteOb]ect;
La clase de implementaci6n de un objeto remoto: public
class Helloserver
extends PortableRemoteObject implements HelloInterface {
Procesamiento distribuido con RMI El objeto ~ o r t a b l e ~ e m o t ejoe bc t es similar a ~ n i c a s t ~ e m o t e joebc t pero proporcionala funcionalidad de base en el dominio IIOP. public Helloserver ( ) throws RemoteException { super ( ) ; / / Call the superclass constructor to export this object
I public Strirtg s a y H e l l o 0 thruws RemoteException { return "Hello World, the current system time is "
t
new Date();
1
I 0
Genere un vinculo para I I O P con r m i c - i i o p : con la opcibn -i i o p el cornpilador r m i c genera las clases de stubs y vinculos que obedecen el protocolo IIOP. Sin esta opcibn - i i o p , r m i c genera un stub y un skeleton para el protocolo JRMP, o hicamente stubs si tambikn utiliza la opcion - v 1 . 2 (recuerde que 10s skeletons no son necesarios en 1.2).
0
Ejecute t n a m e s e r v . e x e como un sewidor nombre: este sewidor proporciona 10s sewicios I I O P CosNaming para que 10s clientes busquen objetos.
0 Genere I D L con r m i c - i d 1 para clientes CORBA (si a nuestro objeto tambikn van a acceder
clientes CORBA). 0 A1 iniciar el sewidor, deben configurarse dos importantes variables de entorno para el contexto
JNDI.
a j a v a . n a m i n g . f a c t o r y . i n i t i a l . ~ s t es e el nombre de laclase autilizar como factoria para crear el contexto.
b.
j a v a . n a m i n g . p r o v i d e r . u r l . ~ s t es e el URLdel sewicio de designacibn, similar a1 formato URL rmi:// descrito anteriormente. El r m i : / / es reemplazado por i i o p : / / y el puerto por defect0 para el registro es el 900 en lugar del 1099.
Estas propiedades pueden ser especificadas bien a1 iniciar el sewidor, como se muestra a continuacibn, o bien codificando 10s valores en j a v a .r m i .P r o p e r t i e s y pasindolo a I n i t i a l c o n t e x t como hacemos en el siguiente ejemplo: j a v a -Djava.naminq. f a c t o r y .i r ~ i t i a l = c o m m s u rj~ndi. . cosr~amir~q.CNCtxFactory -Djava.namir~g.provider.url=iiop://129.112.1. 9: 0 ReqisterIt
En el cliente El cliente tiene la misma sentencia de importacibn y utiliza el contexto J N D I para obtener una referencia a1 objeto, en lugar de utilizar el registro. El mktodo J N D I l o o k u p ( ) devuelve un j a v a . l a n g . ~b j e c t , que debe ser entonces transmitido utilizando el m k t o d o n a r r o w ( ) de PortableRemoteObject.
import j ava. rmi. * ; import javax. rmi. PortableRemoteObject; i m p o r t javax.naming.1nitialContext; public class Helloclient
{
public static void main(String try {
args[] )
{
Cree el contexto J N D I y asdcielo a 61: InitialContext ctx Object obj
=
=
new Initialcontext
0;
//
Create the JNDI context
ctx. lookup ("/EgServert');
Asi se asocia el objeto a1 contexto JNDI igual que hizo el mktodo Naming. b i n d ( ) HelloInterface myobj
=
(HelloInterface) PortableRemoteObject .narrow(obj, Hel1oInterface.class);
String message = myobj . sayHello ( ) ; System.out .println ( m e s s a g e ); catch (Exception e ) [ System.out .println ("HelloClient exception:
)
+
"
e);
1
I 1 O t r a vez, las propiedades para el contexto JNDI (el nombre de factoria del contexto y URL proveedor) deben ser pasadas alas aplicaciones cliente en period0 de ejecucidn. Y, bisicamente, eso es todo. Sun proporciona una guia detallada empaquetada con JDK sobre la conversidn de programas RMI
y applets existentes. T a m b i b se puede acceder a ella online en http:lljava.sun.comlj2se/l.3/docsl guidelrmi- iioplrmi-iiopgg. htrn I. Observe que tambikn podemos escribir un servidor que se ajuste explicitamente a ambos clientes: 0 Exportindolo a ambos protocolos utilizando el mktodo e x p o r t o b j e c t ( ) . Obviamente, en este
caso n o necesitamos ampliar n i P o r t a b l e R e m o t e O b j e c t n i ~ n i c a s t ~ e m o t e ~ b j e c t . 0
Creando dos I n i t i a l c o n t e x t , uno para permitir la asociaci6n al registro RMI y uno para el servicio COSNaming, y asociando el servidor en ambos.
0 N o pasando el servicio de designaci6n como un argument0 de linea de comando utilizando la opcidn -D.
Por ejemplo, si quisikramos convertir a nuestro objeto Helloserver inicial en accesible sobre RMI (JRMP) y sobre RMI-IIOP, entonces se podria modificar como sigue: j ava . rmi. RemoteException; java. rmi .server.UnicastRemoteObject; java.uti1. Date; javax.rmi.PortableRemoteObject; class Helloserver implements HelloInterface
[
public void Helloserver() throws RemoteException
[
import import import import public
PortableRemoteObject. exportobject ( t h i s ); / / // UnicastRemoteObject. exportobject ( t h i s );
Export for I I O P Export for JRMP
I public String s a yHello ( ) throws RemoteException [ return "Hello World, the current system time is
"
+ new Date( ) ;
I El objeto puede ser registrado con ambos contextos modificando nuestro archivo ~ e g i s t e~ r t : import java.rmi.RMISecurityManager;
Procesamiento distribuido con RMI import java.uti1.Prnperties; i m p o r t javax. naming. InitialContext; public class RegisterIt
{
public static void main (String [ 1 args) [ try{ if(Systern.getSecurityManager0 == null) Systern.setSecurityManager ( n e w ~ ~ I S e c u r i t y M a n a g e r) ; O HelloServer obj
=
new HelloServer
0;
/ / Create the object
/ / Crear un JDNIContext para JRMP y asociar el objeto a1 registro / / Observe que estarnos utilizando el registro RMI via JNDI y no el / / registro por defecto. Properties p 1 = new Properties(); p l.put ("java.narning. factory. initial", "com. sun. j ndi. rrni. registry. RegistryContextFactory") ; InitialContext ctx 1 = n e w InitialContext ( ) ; ctx 1. rebind ("HellnServer", obj ) ; Systern.out .println ( "HelloServer bound in JRMP registry") ;
]
/ / Repita el rnismo paso para el registro IIOP Properties p 2 = new Properties( ) ; p 2.put ("java.narning. factory. initial", "corn. sun.jndi. c o s n a m i r ~ g . C N C t x F a c t o r y " ) ; InitialContext ctx 2 = new InitialCorltext ( p 2 ) ; ctx 2.rebind ("RernoteHelloServer", obj ) ; Systern.out.print1n ("HelloServer bound in IIOP registry"); catch(Exception e ) {]
I
I
Hemos abarcado muchos temas en esta section, asi que recapitulemos lo que acabamos de describir. Hemos hablado sobre 10s pasos a seguir en la escritura del servidor y del cliente RMI-IIOP, las diferencias entre ellos y c6mo el mismo objeto sewidor puede escribirse para ambos clientes RMI-JRMP y RMIIIOP. Sin embargo, lo que no hemos mencionado es corn0 un cliente CORBA puede solicitar sewicios de este objeto o como el cliente RMI-IIOP puede acceder a un objeto CORBA. Examinemos este punto. Una vez que tenemos una interfaz Java (estamos reutilizando el H e l l o I n t e r f a c e que escribimos antes), podemos utilizar el r m i c con la opci6n - i d 1 para generar su fuente IDL. ace. idl: Ennuestro c a s o , r m i c - i d 1 ~ello~nterfaceproduceelsiguientearchivo~ello~nterf /** HelloInterface. id1 Generated by rrnic -idl. Do not edit 2 0 August 2001 18:27:51 BST
+
+
/
#include #ifndef #define
"nrb. idl" HelloInterface HelloInterface
interface HelloInterface
[
: :CORBA: :WStringValue sayHello ( ) ;
I
;
#pragrna I D HelloInterface "RMI:HelloInterface:0000000000000000"
Este archivo .id1 puede ser utilizado por cualquier compilador IDL que se ajuste a CORBA 2.3 proporcionado por un vendedor, podemos generar un stub en nuestro lenguaje elegido (hablamos de C + + ya que es un lenguaje muy comun para objetos CORBA) para generar las clases de stub para ese lenguaje. El mismo compilador puede ser utilizado para generar clases skeleton/vinculo y 10s objetos de servidor C + + escritos para esas clases y se puede acceder a IDL con 10s clientes RMI-IIOP que hemos escrito.
RMI-IIOP y Java IDL Java I D L es un Object Request Broker (ORB) proporcionado con JDK y que puede ser utilizado para definir, implementar y acceder a objetos CORBA desde Java. Java IDL cumple con la especificaci6n CORBA/IIOP 2.0 y el Mapping de O M G IDL para Java. La primera cuesti6n relacionada con este tema que se plantean la mayoria de 10s desarrolladores es: "ise estl eliminando RMI progresivamente a favor de RMI-IIOP?". La respuesta es un rotundo no. Otra pregunta que a veces se plantea a "ies RMI-IIOP un sustituto para Java IDL?". Una vez mls, la respuesta es no. U n cliente RMI-IIOP n o puede necesariamente acceder a un objeto CORBA existente. Si queremos utilizar Java para acceder a objetos CORBA que ya hemos escrito, Java IDL es nuestra mejor elecci6n. C o n Java IDL, que es t a m b i h una parte central de la plataforma Java 2, podemos acceder a cualquier objeto CORBA desde Java. La recomendaci6n general de uso para RMI-IIOP y Java IDL es Csta: "Si desea utilizar Java para acceder a recursos CORBA existentes, utilice Java IDL. Si, por el contrario, quiere que 10s recursos Java RMI sean accesibles a usuarios CORBA, entonces deberia utilizar RMI-IIOP. Si su aplicaci6n va a ser toda Java, entonces utilice RMI-IIOP". J2SEv1.3 incluye una nueva versi6n del idlj compilador de IDL a Java que toma u n archivo IDL y genera el servidor Java y las asociaciones d e cliente a partir de 61.
El archivo IDL iRecuerda el IDL que acabamos de generar? Tomemos ese archivo (HelloInterfa c e . i d l ) como punto de partida para este ejemplo y veamos que podemos escribir objetos CORBA y utilizar Java IDL: # i n c l u d e "orb. i d l " #ifndef #define
HelloInterface HelloInterface
interface HelloInterface [ ::CORBA::WStringValue s a y H e l l o 0 ;
1; #pragma I D HelloInterface #endif
"RMI:HelloInterface:0000000000000000"
Dos cosas pueden ocurrir con un archivo IDL. Podemos escribir el servidor o podemos escribir un cliente (como ya hemos mencionado antes en el ejemplo RMI-IIOP). Experimentaremos ambas en este ejemplo utilizando el compilador i d 1 j .
La implernentacion de servidor Examinemos la secuencia de eventos asociados a la implementaci6n de servidor:
Procesamiento distribuido con RMI 0 Genere las asociaciones de lado servidor para el archivo IDL. Esto se realiza con el compilador i d 1 j : idlj -i %JAVA-HOME%\lib
-fserver HelloInterface.id1
Donde %JAVAPHONE%es el directorio de instalacion de J2SE 1.3. Inchimos el archivo o r b . i f 1con la opcion -i a1 compilador i d 1 j porque esti referenciado en el archivo I D L (recuerde que este I D L con el que empezamos fue autogenerado). La opci6n - £ s e r v e r indica a1 compilador que genere las asociaciones de lado servidor. 0
Escriba la implementaci6n. En terminologia CORBA, esto se denomina una clase sirviente.
El sirviente, H e l l o s i r v i e n t e , es la implementaci6n de la interfaz I D L y es una subclase de H e l l o I n t e r f a c e I m p l B a s e , que es generada por el compilador i d 1 j (para cada archivoxxx. i d 1 el compilador genera un archivo - x x x ~ m p l ~ a s.ej a v a ) . El sirviente contiene un metodo para cada operaci6n IDL. En este ejemplo, este es s61o el metodo s a y H e l l o ( ) . Observe que 10s metodos sirvientes son s61o metodos corrientes Java. import
java. util. Date;
public class HelloSirviente extends HelloInterfaceImplBase { public String sayHello( ) { returr, "Hello World, the current system time is " + new D a t e ( ) ;
0 Escriba la clase que asocia la implementaic6n (el sirviente) a1 servicio de designaci6n. Esta clase se
denomina el servidor en terminologia CORBA. Entonces, la clase H e l l o S e r v e r quedari como sigue: i m p o r t o r g . omg. CosNaming. * ; i m p o r t org.omg. C o s N a m i r ~ g . N a m i r ~ g C o r ~ t e x t P a c k a*g;e . import org.omg.CORBA.*; public class HelloServer { public static void main(String try 1
args[]) {
/ / crear e inicializar el ORB ORB orb = ORB.init(args, null); / / crear el sirvientey conectarlo con el ORB HelloSirviente helloRef = new HelloSirviente orb. connect (helloRef);
( ) ;
/ / obtener el contexto d e designaci6i-I raiz org.omg. CORBA.Object obj Ref = orb.resolve initial references("NameService"); NamingContext ncRef = NamingContextHelper. narrow (objR e f ) ; / / Asociar la referencia d e sirviente a1 Contexto d e Designaci6n ""); NameComponent n c = new NameComponent("He11o". NameComponent path [ I = { nc) ; ncRef. rebind (path, helloRef) ; / / Esperar las invocaciones d e clientes java. lang.0bject sync = new java. lang.0bject ( synchronized (sync) { sync.wait ( ) ;
) ;
Capitulo 3 J
c a t c h IException e ) { S y s t e m . o u t . p r i n t l n ("Exceptior1:
"
+
e );
! !
I Asi, queda claro en el c6digo anterior que el sewidor ejecuta las siguientes acciones: O
Instancia el O R B
O
Instancia el sirviente y lo conecta a1 O R B
O
Obtiene una referencia de objeto CORBA para un contexto de designacion en el que registrar el Nuevo objeto C O R B A
O Asocia el nuevo objeto en el contexto de designacion con el nombre " H e l l o " Espera las invocaciones del nuevo objeto
La implernentacion cliente Sigamos ahora el procedimiento asociado a la implernentacion cliente. Necesitaremos crear una subcarpera cliente antes de ejecutar este paso: O Genere las asociaciones de lado cliente para el archivo idlj
O
-i
%JAVA-H O M E % \ l i b - t d
client
IDL:
-fclient
HelloInterface.id1
Escriba la clase cliente. ~ s t puede a ser un applet o una simple clase Java.
import import
o r g . omg. C o s N a n l i n g . org.omg.CORBA.*;
*;
public class HelloClient{ p u b l i c s t a t i c v o i d main I S t r i n g try{
args [ 1 ) {
//
c r e a r e i n i c i a l i z a r e l ORB ORB o r b = O R B . i r ~ i (t a r g s , n u l l ) ;
/ / obterler e l contexto d e designaci6n r a i z o r g . omg. CORBA.Object o b j R e f = o r b . r e s o l v e i n i t i a l r e f e r e n c e s ( " N a m e S c r v i c e " ); N a m i n g C o n t e x t n c R e f = N a m i r ~ g C o n t e x t H e l p e r .n a r r o w ( o b j R e f ) ;
//
r e s o l v e r l a R e f e r e n c i a d e O b j e t o e r ~Designaci6n NameComponent n c = new NarneComponent ( " H e l l o " , " " ) ; NameCompor~ent p a t h [ 1 = { n c ) ; HelloInterface helloRef =
HelloInterfaceHelper.r~arrow(r~cRef.resolve(path) ); //
1
llamar a 1 o b j e t o s e r v i d o r Hello e imprimir S t r i n g h e l l o = helloRef .sayHello(); S y s t e m . o u t . p r i n t l n ( h e l l o ); catch (Exception e ) { System.out.println ("Exceptior~ : " + e ) ;
resultados
Procesamiento distribuido con RMI Finalmente, podemos ejecutar este ejemplo utilizando la siguiente secuencia: 1. Compilar todos 10s archivos java: javac * . java
2. Crear 10s stubs para el servidor: rrnic -iiop HelloServer
3. Ejecutar el servicio de Designaci6n t n a m e s e r v : tnameserv -0RBInitialPort
900
4. Iniciar el servidor: j ava
-Dj ava. naming. f actory. initial=com. sun. jndi . c o s n a r n i n g . C N C t x F a c t o r y -Djava.r1arnir1g.provider.ur1=iiop://10ca1host:900 HelloServer
5. Eiecutar el c l i e n t e ~ e l l o ~ e r v e r : java
-Djava.narning. factory.initial=corn.sun.jndi .cosnarning.CNCtxFactory -Djava.r~arning.provider.url=iiop://localhost:900 Helloclient
C o n 10s dos ejemplos anteriores hemos visto c6mo escribir un objeto RMI-IIOP y c6mo hacerlo accesible a otros clientes CORBA. Tambikn hemos visto c6mo tomar un archivo IDL y generar un objeto CORBA y acceder a 61 con un cliente Java-IDL.
i d 1 j esta' sujeto tanto a1 modelo de herencia como a1 de delegaci6n. Esto significa que dada una interfaz X X en su archivo IDL, i d 1 j genera XXImplBa se.java. La implementacidn para X X que escribe debe ampliar la clase -XXImplBa s e . Esto se conoce como modelo de herencia. En ocasiones esto puede no resultar ritil si su implementacidn se amplia desde otra clase. (Recuerde que una clase Java puede implementar cualquier nrimero de interfaces pero s61o puede ampliar una clase.) En tal caso, puede indicar a1 compilador i d 1 j que utilice en modelo Tie. Si asi ocurre para la interfaz X X de su archivo IDL, i d 1 j generard XX- T i e - j a va y el constructor para X X T i e tomara' un XX como argumento. La implementacidn para XX que proporciona s61o es necesaria para implementar la interfaz XX. Para que esta implementacidn la utilice con el O R B , debe envolver su implementacidn en x x T i e . Por ejemplo: XXImpl ohj = new XXImpl X X Tie tie = new XX Tie orb.connect ( t i e ); -
(1; (ohj) ;
Como puede ver, el inconveniente de utilizar el modelo Tie es que aiiade un paso extra y una llamada de me'todo extra. El modelo de lado servidorpor defect0 del compilador i d 1 j es el modelo de herencia. Para utilizar el modelo de delegacidn: idlj -fserverTIE Hello.id1
idlj
-fallTIE Hello.id1
RMI-IIOP y JZEE M I - I I O P ofrece las siguientes ventajas para desarrolladores de programas con relaci6n a RMI-JRMP: O Interoperatividad con objetos escritos en otros lenguajes via CORBA IDL independientes del
lenguaje
o Los contextos de transacci6n y seguridad pueden ser propagados implicitamente debido al uso de IIOP, que puede propagar implicitamente informacion de context0
O Mantenimiento de cortafuegos de base I I O P via proxy I I O P que pueden pasar trifico I I O P de un mod0 controlado y manejable C o n I I O P como protocolo de transporte, Java RMI encuentra el apoyo que necesita para fomentar el desarrollo de aplicaciones distribuidas de capacidad industrial, s61o en un entorno Java. N o obstante, M I - I I O P tiene algunos puntos dkbiles propios en comparaci6n con M I - J R M P : N o tiene asistencia de recoleccibn de residuos distribuidos. Las interfaces RMI D G C no representan 10s I D de objeto como lo hace CORBA, por lo que esas interfaces no son suficientes para CORBA/IIOP. N o puede confiar en las prestaciones de Java RMI/JRMP mientras utiliza MI-IIOP. El operador de conversi6n de clases no puede ser utilizado directamente en sus clientes despuks de obtener una referencia de objeto remoto. En su lugar, necesita utilizar un metodo especial para obtener el tip0 adecuado. N o le esti permitido heredar en mismo nombre de mktodo en su interfaz remota desde diferentes interfaces remotas base. Todas las definiciones constantes en interfaces remotas deben ser de tipos primitivos o Strings, y evaluadas en tiempo de compilaci6n. Entonces, ?quC idea esti detris de la intencidn de convertir M I - I I O P en el protocolo de facto en J2EE sustituyendo a RMI-JRMP?
Todos 10s contenedores J2EE son requeridos para mantener JRMP y RMI-IIOP y 10s contenedores t a m b i h deberian poder exponer todos 10s beans de empresa utilizando RMI-IIOP mediante las interfaces remotas de 10s beans. Enterprise JavaBeans (EJB) es un constituyente clave de J2EE; 10s componentes de EJB residen dentro de 10s contenedores EJB, que proporcionan 10s entornos de period0 de ejecuci6n para 10s componentes. 1-0s contenedores ETB son desarrollados Dor diferentes vendedores tomando como base las especificaciones EJB (que utilizan la semintica RMI). Los vendedores son libres para elegir la implementaci6n para sus contenedores. Para promover la interoperatividad para 10s entornos EJB que inchyen sistemas procedentes de diferentes vendedores, Sun ha definido una representaci6n estindar de EJB a CORBA, basada en la especificaci6n de la asociaci6n Java en IDL desde OMG. Es decir, las interfaces EJB son intrinsecamente interfaces RMI-IIOP. Puede acceder a la representacidn EJB en CORBA en http:lljava.sun.comlproductslejblindex.html.
Procesamiento distribuido con RMI Como veremos en este libro, EJB presenta un modelo de creaci6n de aplicaciones de empresa distribuidas que pueden ser desplegadas en un entorno heterogheo. RMI estindar con JRMP falla en algunos aspectos: 0
Es la unica solucion de Java y EJB tambiCn deberia ser accesible para otros clientes en una entorno de empresa
0 N o obedece a la propagation de contextos de transaction y seguridad en las JVM distribuidas (de
hecho, no obedece a la propagacion de context0 en absoluto)
o N o es tan reajustable como I I O P RMI-IIOP supera estas limitaciones de RMI-IIOP. La representacion de CORBA en EJB no solo permite la interoperatividad entre irnplementaciones de multiples vendedores del contenedor EJB, sino que tarnbikn capacita a clientes no Java para que accedan a aplicaciones de lado servidor como EJB a traves de 10s API CORBA estindar. La especificacion EJB 2.0 permite la operatividad entre contenedores utilizando RMI-IIOP.
Ajustar aplicaciones RMI El API de RMI ofrece rnuchas propiedades de sistema que puede ser ejecutadas dinimicarnente en el period0 de ejecucion con la opcion -D en la JVM. (Por ejemplo, j ava -D j ava. rmi .dgc . leaseValue=3OOOO ~ y ~ p pSon ) . muy 6 d e s para ajustar el rendimiento y depurar las aplicaciones. Estas propiedades estin catalogadas en las siguientes tablas, empezando con un resumen de todas las propiedades que pueden ser configuradas en las JVM cliente y servidor: Propiedad
Introducida primera vez (versi6n)
Descripci6n
j ava .rmi .dgc .leasevalue
La duration del alquiler concedido por el D G C a 10s clientes que acceden a objetos remotos en esta JVM. Los clientes normalmente renuevan un alquiler cuando ha expirado en su 50%, por lo que un valor muy corto aumentara el traf~coen la red y arriesgara renovaciones tardias a cambio de demora en llamadas a U n r e f e r e n c e d . unref erenced.Elvalorpor defectoes 600000 milisegundos (10 minutos).
java.rmi.server .codebase
Las osiciones desde las que las clases ubgcadas par esta JVMpueden ser descargadas. R e d e ser un URL o unallsta d e ~ ~ ~ s e ~ a r a d a ~ espacio (para 1.2) y puede ser configurada tanto en JVM cliente como en JVM serv~dor.
java.rmi.server .hos tname
El nombre de host que debe estar asociado a stubs remotos para objetos remotos creados localmente, ara permitir a 10s clientes invocar mktodos enefob'eto remoto. EIvalor or defect0 se esta propiedad es la direction IP defhost local.
java.rmi.server logcalls
.
1.1
Llamadas entrantes de metodo y excepciones serin registradas e n s y s tem. err siestees true.
La tabla continua en la pagina siguiente
185
-
- --
-
Propiedad
Introducida primera vez (version)
Description
java. rmi. server .randomIDs
1.1.8
Si este valor es true, 10s identificadores de objeto para objetos remotos exportados por esta JVM serin generados utilizando un generador criptogrifico seguro de numeros aleatorios. El valor por defecto es false. Si este valor es true, la JVM no puede cargar automiticamante desde otro lugar que no sea su classpath local y desde la propiedad j a y a . r m i . s e r v e r . codebasedel servidor. Esta p u e d e c o n f i g u r a r s e e n la J V M cliente y servidor.
java. rmi. server .use LocalHostName
1.1.7
RMI utiliza ahora una direccibn I P para identificar el host local cuando la propiedad j a v a . r m i . s e r v e r . h o s t n a m e no e s t i especificada no sepuede obtener un nombre de dominio caEficado para el host local. Si re configura en true, RMI estiobligado autilizar el nombre de dominio calificado por defecto. Si este valor es true, el tunelado HTTP es desactivada, incluso cuando se confi ura http. proxyHost.El valor por efecto es ahe y esta propiedad es util para JVM cliente.
f
La siguiente tabla describe las propiedades especificas de activacibn:
1-
Propiedad
Introducida primera vez (version)
Descripcidn
El valor de esta propiedad representa el puerto T C P en el que el demonio de sistemadeactivacibn, rmid, escuchari las llamadas remotas entrantes. El valor por defecto es 1098. java. rmi .activation .activator.class
1.2
La clase que implementa la interfaz iava.rmi.Activation.Activator. Esta ' ropicdad es utilizadainternamente para focalizar la impkmmtacibn residente del activador desde el que uede encontrarse el nombre de clase sut!.
Esta tabla final representa un resumen de propiedades que son especificas de la implementacibn JDK SUN de RMI:
Procesamiento distribuido con RMI Propiedad
Introducida primera vez (versi6n)
s u r ~ r. m i . a c t i v a t i o n .?x?cTirneout s u r ~ r.r n i . a c t i v a t i o n .sr~apshotInterval
sun. r m i . 1oq.debuq s u n . rrni . r m i d .m a x s t a r t q r o ~ l p
s u n . rrni. s e r v e r
.a c t i v a t i o n .debugExec
s u r ~ r. m i . d g c checkInterva1
1.1
s u n . rrni . d g i : . l . ~ q L e v e l
1.1
s u n . rrni . d g z . s e r v e r .g c I n t e r v a 1
1.2
.
Descripcidn
El tiempo que rimd esperari para que un grupo de activacidn generado arranque. El valor por defecto es de 30,000 milisegundos. El ndmero de actualizaciones por las que esperarien sistema de activacidn antes de que serialice una instantinea de su estado a1 archivo de registro rmid del disco. Una "actualizacidn" hace referencia a un cambio persistente en el estado de sistema de activacidn (por ejemplo, el registro de un objeto activable) desde que fue tomada la dltima instantinea. Cambiar el valor de esta propiedad puede utilizarse para hacer que rmid se reinicie mis ripidamente (tomando instantineas del registro con mis frecuencia) o conseguir que rimd sea eficiente (tomando instantineas del registro con menor frecuencia). El valor por defecto es 200. Si este valor es true, 10s detalles de la actividad de registro de rmid son enviados a System.err. El miximo numero de JVM de grupo de activacidn que rmid permitiri simultineamente en el estado de "generaci6n pero todavia inactivo". Si necesitamos iniciar mis JVM, 6stas estarin en cola hasta que uno de 10s intentos actuales de generacidn sea efectivo o caduque. Esta propiedad no limita el numero miximo de VMs activas; e s t i destinada a suavizar picos imprevistos de actividad para evitar alcanzar limites del sistema operativo. Fijar el valor de esta propiedad en un ndmero menor puede resultar en un mayor tiempo dearranque de rmid fijarelvaloraun ndmero mayor puede reducir el tiempo de arranque; fijar este valor demasiado alto puede hacer fallar el rmid porque su sistema puede quedarse sin recursos. El valor por defecto es 3. S; estevalores true, el sistemade activacidn imprimiri informaci6n de depuracidn a la linea de comando que se utiliza para grupos de activacidnde generacidn. Pordefecto, el valores false, por lo que lainformaci6n de depuracidn n o se imprime. La frecuencia con la que el periodo de ejecucidn de RMI comprueba 10s alquileres D G C que ha expirado. El valor por defecto es 300,000 milisegundos. Controla el registro de llamadas entrantes y salientes relacionadas c o n la c o n c e s i 6 n , renovacion y expiracidn de alquileres. Cuando es necesario certificar que 10s objetos remotos inalcanzables n o son exportados y son recogidos p o r el recolector de residuos o p o r tunamente, el valor de esta propiedad representa el interval0 m i x i m o que p e r m i t i r i el periodo de ejecucidn entre recolecciones de residuos en el curnulo local. El valor p o r defecto es 60,000 milisegundos.
tabla continua
Capitulo 3 Propiedad
Introducida primera vez (versidn)
Descripcidn
Controla el registro de cada nombre de clase y base de cddigo, siempre que el periodo de ejecucidn RMI intenta cargar una clase c o m o resultado d e unmarshaling un argument0 o un valor devuelto. La base de cddigo impresa es la base de cddigo anotada, per0 puede que no sea necesariamente la verdadera base de cddigo desde la que se carga la clase; el cargador de clase RMI difiere la carga de clase a1 cargador de clase de contexto de hilo, que puede que cargue la clase desde el classpath, . v, no desde la base de cddino anotada. Controla la salida de sefiales de pila de lado servidor procedentes de excepciones y errores lanzados por llamadas remotas entrantes lanzadas. Si este valor es t r u e , las seiiales d e pilas d e excepcidn s e r i n imprimidas. Por defecto (false), las seiiales de pilas de excepciones y errores n o son imprimidas. Controla el registro detallado a travks de la capa de transporte. Representa el tiempo que el periodo de ejecucidn RMI esperar6 para obtener un nombre de dominio calificado para el host local. El valor por defecto es 10,000 milisegundos. Controla el registro detallado para la subcapa de transporte especifica de T C P . Representa el tiempo invertido como tiempo limite de inactividad para conexiones RMI-TCP entrantes. El valor es pasado a Socket. setSoTimeout. Esta propiedad se utiliza s61o en casos en 10s que un cliente no ha suprimido una conexion sin usar como deberia. El valor por defecto es 7,200,000 rnilisegundos (2 horas). Representa el tiernpo miximo que el periodo de ejecucidn RMI esperari antes de reintentar una llamada D G C "limpia" fallida. El valor por defecto es 180,000 milisegundos. Cuando es necesario asegurar que las IlarnadasDGC limpias para referencias remotas inalcanzables son efectuadas oportunarnente, el valor de estapropiedad representa el interval0 miximo que el periodo de ejecucidn R M I permitir6 entre recolecciones d e residuos del cdmulo local. El valor por defecto es 60,000 milisegundos. Controla el registro de cada nombre de clase y base de cddigo, siempre que el periodo de ejecucidn RMI intenta cargar una clase c o m o resultados de lectura de un argument0 o un valor devuelto. La base de cddigo impresa es la base de c6digo anotada per0 puede que no sea necesariarnente la base de c6digo desde la que la clase se carga; el cargador de clase RMI difiere la carga de clase a1 actual cargador de clase de contexto del thread, que puede cargar la clase desde la ruta de clase, y n o desde la base de cddigo marcada. Controla el registro de informacidn relacionada con llarnadas salientes, incluido alguna informacion de reutilizacidn de conexiones.
-
s u n . mi . s e r v e r .? x c e p t i o n T r a c e
s u n . rrni. t r a n s p ~ r t .logLevel sun. rmi. t r a n s p o r t .tcp. localH?st NameTimeOut sun. rmi. t r a n s p o r t .tcp.loqLevel slli-1. r m l . t ~ a n s p o r t .tcp.readTirneout
s u r i . r m i .d g c .c l e a n I n t e r v a 1
sun. r m i .dgc. c l i e n t .g c I n t e r v a 1
sun. rmi. loader . 1ogLex.e 1
s u n . rmi .s e r v e r .l.igL?vel
Procesamiento distribuido con RMI Propiedad
Introducida primera vez (versi6n)
Descripcidn
s u n . rrni. t r a n s p o r t .connectlonTimeout
1.1.6
sun. rmi. transport .prosy.connectTimeout
1.1
s u n . rrni. t r a n s p o r t .proxy. logLevel
1.1
R e p r e s e n t a el p e r i o d 0 d u r a n t e el q u e las conexiones de socket RMI pueden residir en estado "sin usar", antes de que el periodo de ejecucidn RMI permita que se liberen (cierren) esas conexiones. El valor por defecto es 15,000 milisegundos. Representa el miximo tiempo qie el periodo de ejecucidn RMI esperari para que se complete un intento de conexidn (createsocket), antes de intentar contactar con el servidor a traves de HTTP. Esta propiedad s61o se utiliza c u a n d o la propiedad h t t p . p r o x y H o s t e s t i c o n f i p r a d a y el valor de java.rmi.server.disableHttp es false. El valor por defecto es 15,000 milisegundos. Controla el registro de eventos (createsocket y createserversocket) cuando la clase p o r defect0 RMISocketFactory es utilizada. Este tip0 de registro puede ser dtil para aplicaciones que utilizan RMI sobre HTTP. Los eventos en factorias de socket de adaptacidn n o son registrados en esta propiedad.
Las propiedades RMI de Sun descritas son utiles para depurar per0 es importante recordar que no son sostenidas oficialmente y que estin sujetas a cambios constantes. Las propiedades que terminan en " .logLevelWtiene salida redirigida a s ystem. err conposibles valores de "SILENT", "BRIEF" y "VERBOSE".
Resumen Hemos abarcado mucho terreno en este capitulo, desde la arquitectura bisica RMI hasta el tunelado H n P . Si se siente un poco abrumado por tanta informaci6n, t6meselo con calma. Repase 10s ejemplos y escriba algunas aplicaciones de prueba; eso le hari avanzar. En el capitulo, hemos tratado: O La arquitectura RMI. U Desarrollo de aplicaciones RMI. Las etapas necesarias para la creaci6n de aplicaciones efectivas.
o Pasada de parimetros en RMI, 10s tipos disponibles y su uso. o Activacion de objetos, 10s beneficios de ejecucidn basados en la necesidad. 0 RMI, cortafuegos y HTTP. Los diferentes mitodos disefiados para permitir el acceso del trifico JRMP a travis de cortafuegos. 0 El desarrollo de RMI sobre I I O P y la integraci6n de RMI sobre CORBA.
Recuerde que, aunque RMI-IIOP es el modelo para J2EE, JRMP esti todavia muy activo. Si su aplicaci6n requiere Gnicamente comunicaci6n Java-Java, entonces RMI-JRMP es una soluci6n viable. La inclusi6n de RMI-IIOP en el nucleo de JDK (desde la versi6n 1.3 de J2SE) y su intima asociaci6n con EJB, lo establece como una tecnologia de base para el software intermediario de empresa. En perspectiva, RMI ha realizado un largo recorrido desde sus primeros dias, cuando no existia ning6n modelo distribuido en Java. En la actualidad, es el nude0 del modelo distribuido de Java en J2EE y constituye la base para futuras tecnologias, como JINI, que estin transformando el mod0 en el que dispositivos y sistemas serin redificados conjuntamente. Aunque esti fuera del alcance de este capitulo, Jini esencialmente revoluciona de forma espectacular el modelo y la arquitectura RMI. El capitulo cuarto aborda el acceso alas bases de datos utilizando el API Java Database Connectivity (JDBC).
Programacion de bases de datos con JDBC Una base de datos relacional es normalmente el recurso primario de datos en una aplicaci6n de empresa. El API JDBC ofrece a 10s desarrolladores de programas un mod0 de conectar con datos relacionales desde el interior del c6digo Java. Utilizando el API JDBC, 10s desarrolladores pueden crear un cliente (que puede ser cualquier cosa, desde un applet a un EJB) que pueda conectar con una base de datos, ejecutar instrucciones de Structured Query Language (SQL) y que procese el resultado de esas instrucciones. Si esti familiarizado con SQL y las bases de datos relacionales, la estructura del API JDBC es ficil de entender y utilizar. El API proporciona conectividad y acceso a datos en toda la extensi6n de bases de datos relaciones. Puede conseguir este objetivo porque ofrece una serie de mktodos genkricos de acceso a bases de datos para bases de datos relacionales que se ajusten a SQL. JDBC generaliza las funciones de acceso a bases de datos mis comunes abstravendo 10s detalles es~ecificosde vendedor de una determinada base de datos. El resultado es un conjunto de clases e interfaces, localizadas en el paquete-j ava sql,que pueden ser utilizadas con cualquier base de datos que tenga un driver JDBC apropiado. Este permite que la conectividad JDBC sea suministrada de forma constante para cualquier base de datos. Tambikn significa que, asegurindose de que la aplicaci6n se ajusta alas caracteristicas de las bases de datos disponibles mis comunes, una aplicaci6n puede utilizarse con una base de datos diferente cambiando simplemente a un driver JDBC diferente.
.
Sin embargo, hay mucha mis en conectividad de bases de datos en un entorno de empresa que una simple conexi6n de bases de datos y ejecuci6n de instrucciones. Hay aspectos adicionales que deben ser resueltos incluido el uso de reserva de conexiones para optimizar 10s recursos de la red y la implementacidn de transacciones distribuidas. Aunque algunos de 10s conceptos que se encuentran detris de estos aspectos son avanzados, veremos que enfrentarse a ellos no es en si demasiado complejo. Estudiaremos el API JDBC 3.0 que, en el momento de publicaci6n de este libro, es la d t i m a versi6n de API JDBC. La versi6n 2.0 del API JDBC tiene dos partes: JDBC 2.1 Core API y JDBC 2.0 Optional
Capitulo 4 Package API, y aunque estos dos API han sido combinados en la versi6n 3.0, las clases e interfaces JDBC siguen encontrindose en dos paquetes Java: j a v a sql, y j a v a x sql.
.
.
O
java.sq1 Este paquete contiene clases e interfaces disetiadas teniendo en mente la arquitectura tradicional cliente-servidor. Su funcionalidad se centra primordialmente en servicios de programaci6n bisicos de bases de datos, como creaci6n de conexiones, ejecucion de instrucciones e instrucciones preparadas, y consultas por lotes (batch). Funciones avanzadas tales como actualizaci6n de lotes, listas de resultados desplazables, aislamiento de transacciones y tipos de datos S Q L tambitn estin disponibles.
O
javax.sq1 Este paquete introduce algunos cambios importantes de arquitectura en la programacion JDBC en comparacion con javasql y ofrece mejores transacciones para la gestion de conexiones, transacciones distribuidas y conectividad de legado. Este paquete tambitn introduce reserva de conexiones dirigidas por contenedor, transacciones distribuidas y filas.
N o intentaremos cubrir conceptos generales de programaci6n de bases de datos en este capitulo; se requieren conocimientos bisicos previos sobre S Q L y sobre el desarrollo de aplicaciones clienteservidor. U n finico capitulo n o es suficiente para abarcar la programaci6n de bases de datos de forma exhaustiva por lo que adoptaremos un enfoque de alto nivel para el API JDBC. En lugar de intentar analizar, construir y analizar grandes aplicaciones, estudiaremos pequefios fragmentos de codigo que ilustren el uso de varias clases e interfaces de j a v a . s q l y j a v a x . sql. En concreto, examinaremos 10s siguientes puntos: 0
Conectividad de bases de datos utilizando drivers JDBC
O C o m o pueden realizarse varias operaciones S Q L utilizando el A P I JDBC estindar incluido obtener conexiones de bases de datos, enviar instrucciones S Q L a una base de datos y recuperar resultados de consultas debases de datos 0
C 6 m o representar tipos S Q L en Java
O
Caracteristicas avanzadas del API JDBC, incluido listas de resultados desplazables y actualizaciones de lotes
O
Nuevas caracteristicas del API JDBC 3.0, incluidos puntos de salvaguardia
Entonces continuaremos para considerar temas de macro-nivel que incluyen:
O Utilizar el paquete javaxsql y J N D I para obtener conexiones de bases de datos 0
Reserva de conexiones, incluido un anilisis sobre reserva tradicional de conexiones versus reserva de conexiones basada en fuentes de datos
O Transacciones distribuidas (c6mo el paquete j a v a x . sql, junto con el API Java Transaction,
habilita las transacciones distribuidas)
n Los conceptos bisicos de una fila y c6mo proporcionan un alto nivel de abstracci6n para el acceso a bases de datos y la ficil serializaci6n de datos N o s centraremos principalmente en el paquete javasql, ademis de en la creaci6n de conexiones de bases de datos y el control programitico de transacciones. Empezaremos comprendiendo c 6 m o las aplicaciones Java pueden conectar y comunicarse con bases de datos.
Programacion de bases de datos con JDBC
Es importante comprender que JDBC abstrae la conectividad de bases de datos de las aplicaciones Java. U n vendedor de bases de datos proporciona normalmente un conjunto de APIs para acceder a 10s datos gestionados por el servidor de base de datos. Los vendedores de bases de datos populares como Oracle, Sybase, e InFormix ofrecen APIs de propiedad para el acceso de cliente. Las aplicaciones de cliente escritas en lenguajes nativos como C / C + puede utilizar estos APIs para obtener acceso directo a 10s datos. El API JDBC ofrece una alternativa a1 uso de estos APIs especificos del vendedor. Aunque este elimina la necesidad de que el desarrollador de Java acceda a APIs nativos especificos de vendedor, la capa JDBC puede todavia necesitar en dltima instancia realizar estas llamadas nativas. U n driver JDBC es una capa de software intermediario que traduce las llamadas JDBC a 10s APIs especificos del vendedor.
+
Dependiendo de si se esti utilizando el paquete j ava .sql o el paquete j avax .sql,existen diferentes enfoques para conectarse a una base de datos a travks del driver. Con independencia de esto, para acceder a datos necesitari un driver de base de datos, probablemente suministrado por el vendedor de base de datos o por un proveedor del servidor JZEE. U n driver no es mis que una implementaci6n de varias interfaces especificadas enlos paquetes j ava .sql y j avax .sql. Hay cuatro enfoques diferentes para conectar una aplicaci6n a un servidor de base de datos a travks de un driver de base de datos. La siguiente clasificaci6n es una norma de industria y 10s productos comerciales de driver estin clasificados segdn esta norma.
-
Tipo 1 Puente JDBC-ODBC O p e n Database Connectivity (ODBC) fue creado originalmente para proporcionar un API estindar para SQL en las plataformas Microsoft Windows, y fue mis tarde perfeccionado para proporcionar SDK a otras plataformas. O D B C esti basado, en parte, en la especificaci6n X/Open Call-Level Interface (CLI), que es un API estindar para el acceso a bases de datos. Este API proporciona asociaciones en 10s lenguajes C y Cobol para el acceso a bases de datos. CLI esti pretende ser neutral en cuanto a plataformas y bases de datos, ahi donde diverge O D B C de la especificaci6n. SQL integrado fue uno de 10s enfoques barajados para el acceso a bases de datos por SQL Access Group. Esto suponia integrar instrucciones SQL en aplicaciones programadas en lenguajes de alto nivel y preprocesarlas para generar llamadas de funci6n nativa. O D B C define un conjunto de funciones para acceso directo a datos, sin la necesidad de integrar SQL en aplicaciones cliente. La primera categoria de drivers JDBC proporciona un puente entre el API JDBC y el API ODBC. El puente traduce las llamadas JDBC estindar a llamadas O D B C correspondientes y las envia a la fuente de datos O D B C a travks de librerias ODBC:
Capitulo 4
1
Apl1cac16nJava
Fuente de
1
datOs
i
1
-
Puente JDBC-ODBC
' 4
'
'
AF? +
ODBC
1,
--
Capa ODBc
Los limites de proceso estin marcados por una linea discontinua. El Puente JDBC-ODBC traduce las llamadas de API JDBC en llamadas equivalentes ODBC. El driver delega entonces estas llamadas en la fuente de datos. Las clases Java para el API JDBC y el Puente JDBC-ODBC son invocadas en el proceso de aplicaci6n del cliente; la capa O D B C se ejecuta en otro proceso. Esta configuracibn requiere que cada cliente que ejecute la aplicaci6n tenga el API Puente JDBC-ODBC, el driver O D B C y el API de lenguaje de nivel nativo, como la libreria O C I para Oracle, instalado. Esta soluci6n para el acceso a datos no es eficiente para requisitos de acceso a bases de datos de alto rendimiento debido a las mdltiples capas de desreferencia para cada llamada de acceso a bases de datos. Ademis esta soluci6n limita la funcionalidad del API JDBC a favor de la funcionalidad del driver ODBC. El uso de JDBC-ODBC debe ser considerado dnicamente para prop6sitos experimentales. J2SE incluye clases para el Puente JDBC-ODBC y por el10 no es necesario instalar ningdn paquete adicional para utilizarlo. Sin embargo, si tiene que configurar el gestor de O D B C creando nornbres de fuente de datos, data source names (DNS). Los DNS son simplemente configuraciones nornbradas que vinculan una base de datos, un driver apropiado y algunas configuraciones adicionales. El puente JDBCO D B C debe funcionar con la mayoria de 10s drivers O D B C 2.0.
Tipo 2
- Parte Java, parte driver nativo
Los drivers Tipo 2 utilizan una combinaci6n de implementaci6n Java y API nativos especificos de vendedor para proporcionar acceso a datos. Hay una capa menos que atravesar que en el driver Tipo 1 por lo que, en general, un driver Tipo 2 seri mis ripido que un driver Tipo 1:
Programacion de bases de datos con JDBC
I
I I
I
I I
'
API JDBC
-1
-
1
;Drlver JDBC (delwdedor
API '
I I
-
I I
\
I
I
v
especlflco
datos
-
I
7 --
Las llarnadas de bases de datos JDBC son traducidas en llarnadas API especificas del vendedor. La base de datos procesari la solicitud y enviari de vuelta 10s resultados a travks del API, que a su vez la enviari de vuelta a1 driver JDBC. El driver JDBC traduciri 10s resultados a la norrna JDBC y 10s devolved a la aplicaci6n Java. Igual que 10s drivers Tipo 1, la parte Java, el driver de c6digo parte nativa y el API de lenguaje nativo especifico delvendedor deben estar instalados en cada cliente que ejecute la aplicaci6n Java. Corno el cbdigo nativo utiliza protocolos especificos de vendedor para cornunicar con la base de datos de forrna eficiente, 10s drivers Tipo 2 son rnis eficientes que 10s drivers Tipol. Adernb, ahora tenernos uso pleno del API del vendedor. Estos dos factores significan que 10s drivers Tipo 2 son, en general, preferidos a 10s drivers Tipo 1.
-
Tipo 3 Servidor intermediario de acceso a bases de datos Los drivers Tipo 3 utilizan un sewidor interrnediario (software interrnediario) de base de datos que tiene la capacidad de conectar rnliltiples clientes Java a rnliltiples sewidores de base de datos:
I
Aplicacldn
I
Java
I
Capitulo 4 Los clientes conectan a 10s servidores de base de datos rnediante un cornponente servidor interrnediario (corno un escuchador) que actua corno una puerta para multiples servidores de bases de datos. La aplicacion cliente Java envia una llarnada JDBC a travks de un driver JDBC a1 servidor interrnediario de acceso a datos, que cornpleta la solicitud a la Fuente de Datos utilizando otro driver (por ejernplo, un driver Tipo 2). El protocolo utilizado para cornunicar entre clientes y el servidor interrnediario depende del vendedor del servidor de software interrnediario pero el servidor interrnediario puede utilizar diferentes protocolos nativos para conectar con diferentes bases de datos. BEA WebLogic incluye un driver Tipo 3. U n o de las ventajas de utilizar un driver Tipo 3 es que concede flexibilidad a la arquitectura de la aplicacion, ya que el servidor interrnediario puede abstraer detalles de conexiones a servidores de bases de datos.
Tipo 4
- Drivers Java puro
Los drivers Tipo 4 son una alternativa Java puro a 10s drivers Tipo 2:
Apl~cacion Java
\
JDBC
1 Drwer JDBC
-
Los drivers Tipo 4 convierten las llarnadas de API JDBC en llarnadas de red directas utilizando protocolos de red especificos del vendedor. Lo realizan estableciendo conexiones de socket directas con la base de datos. Los driver Tipo 4 ofrecen generalrnente rnejor rendirniento que 10s drivers Tipo 2 y Tipo 2. Los drivers Tipo 4 son tarnbikn 10s drivers rnis ficiles de desplegar ya que n o hay librerias adicionales ni software interrnediario que instalar. Todos 10s principales vendedores de bases de datos proporcionan drivers JDBC Tipo 4 para sus bases de datos y tarnbikn estin disponibles en vendedores de terceros. Puede encontrar una lista de drivers JDBC, de 10s cuatro tipos, en http://industry.java.sun.com/products/ jdbcldriverd. En el mornento de escribir este libro, hay rnis de 160 drivers disponibles.
Como comenzar Para ernpezar a utilizar JDBC con nuestras aplicaciones, necesitarnos instalar un driver. Obviarnente, tarnbikn necesitamos un servidor de base de datos. Para mayor sirnplicidad, en este capitulo, utilizarernos la
Programacibn de bases de datos con JDBC base de datos Cloudscape para demostrar que el API JDBC, como servidor de Implementacidn de Referencia J2EE de Sun, incluye una versi6n de Cloudscape. Cloudscape esti escrito utilizando Java y puedeencontrarloen%~ 2 ~ ~ ~ ~ 0 ~ ~ % \ l i b \ ~ l o u d s c a p e \ ~ l oj aurd. s c a p e . Tambikn puede obtener una copia de evaluaci6n de Cloudscape en http://www.cloudscape.com. Para utilizar el API JDBC y la base de datos Cloudscape, afiada el archivo c l o u d s c a p e j a r a su CLASS PATH.Consulte la documentaci6n de Cloudscape para instrucciones sobre cdmo utilizar Cloudview, una interfaz grifica de usuario (GUI) para acceder a la base de datos Cloudscape.
.
Cloudscape es un sistema de gestidn de base de datos de pequefio contorno construido en Java y que puede ser utilizado de modo integrado o cliente-:emidor. Cuando es utilizado de modo integrado, Cloudscape se ejecuta dentro del proceso de aplicacidn. Este es el modo mis sencillo para la gestidn de base de datos puesto que, aparte de incluir las clases Cloudscape en su CLASSPATH, no supone ninguna configuracidn. El mod0 cliente-servidor le permite acceder a Cloudscape en la forma tradicional cliente-servidor. Como Cloudscape es implementado en Java, no se requieren drivers adicionales de bases de datos ya que 1as llamadas JDBC son representadas en llamadas API Java Cloudscape dentro del mismo proceso. En el modo cliente-senidor, estas llamadas son representadas en llamadas RMI en el proceso del servidor Cloudscape. Si desea crear otra base de datos, asegairese de que sigue las instrucciones para configurar la base de datos dadas por el vendedor de la base de datos e instale un driver de base de datos adecuado.
El paquete java.sql .
Las clases del paquete j a v a s q l pueden dividirse en 10s siguientes grupos basados en su funcionalidad: Gestidn de conexidn Acceso a bases de datos Tipos de datos Metadatos debase de datos Excepciones y advertencias Examinemos las clases disponibles en cada grupo.
Gestion de conexion Las siguientes clases/interfaces le permiten establecer una conexidn a la base de datos. En la mayoria de casos. conlleva una conexidn a la red: Clase
Descripci6n
java.sql.DriverManager
Esta clase proporciona la funcionalidad necesaria para gestionar uno o mis drivers debase de datos. Cada driver a suvezle permite conectar con una base de datos especifica. ~ s t es a una interfaz que abstrae el protocolo de conexi6n especifico del vendedor. Puede e n c o n t r a r implementaciones de estainterfazenvendedores de bases La tabla continua en la prigina siguiente
197
Programacion de bases de datos con JDBC Clase
Descripcion
java.sql.Array
Esta interfaz proporciona una abstracci6n ARRAY de lenguaje Java, una coleccion de tipos de datos SQL.
j ava. sql. Blob
Esta interfaz proporciona una abstraccion de lenguaje Java de SQL tipo BLOB.
j ava .sql .Clob
Esta interfaz proporciona una abstraccion de lenguaje Java de SQL tipo CLOB.
j ava. sql. Date
Esta clase proporciona una abstraccion de lenguaje Java de S Q L tipo D A T E . Aunque j a v a . u t i l . D a t e proporciona una representation de fecha de pro 6sito general, la clase j ava . s q l .D a t e es preferib& para representar datos en aplicaciones centradas en bases de datos, ya ue este tip0 re resenta directamente en ti o S~LDA?E.~ b s e x - v e ~ u e ~ c ~ava a s .esql j .Dat eam&a laclasej ava. util. Date.
java.sql.Time
Esta clase porpociona una abstraccion de lenguaje Java d e S Q L t i p o ~ ~ ~ ~ y a m p l i a l a cava. l a s e util j .Date.
java.sql.Timestamp
Esta clase porpociona una abstraccion de lenguaje Java de SQLtipo~lME,yamplialaclase j ava .util .Date.
java.sql.Ref
Esta clase proporciona una abstraccion de lenguaje Java de S Q L tip0 REF.
java.sql.Struct
Esta interfaz proporciona una abstraccion de lenguaje Java de tipos estructurados SQL.
j ava. sql .Types
Esta clase alberga un conjunto de numero enteros, cada uno de ellos se corresponde con un tip0 SQL.
Como veremos m6s adelante, a d e m b de las anteriores, el API JDBC tambien especifica representaciones estindar entre tipos primitivos en Java y en SQL. El API JDBC tambien incluye recursos para tratar tipos de bases de datos adaptadas. Estos tipos pueden ser representados como objetos j ava .s q l .SQLData y se puede acceder a 10s datos contenidos en estos tipos utilizando las interfaces j ava .s q l .SQLInput y j ava .s q l .SQLOutput que proporcionan una interfaz tip0 corriente (stream) para acceder a 10s datos.
Metadatos de base de datos El API JDBC tambien incluye recursos para obtener metadatos sobre la base de datos, pardmetros para las instrucciones y resultados: Clase
Descripci6n
java.sq1.DatabaseMetadata
Puede encontrar informaci6n sobre las caracteristicas de bases de datos utilizando estainterfaz. Puede obteneruna instancia de esta interfaz utilizando j a v a . s q l . Connection. La tabla continua en la pigina siguiente
Capitulo 4 Clase
Descripci6n
java.sql.Resu1tSetMetaData
Esta inetrfaz propociona mktodos para acceder a metadatos del Resul tse t,como 10s nombres de las columnas, sus tipos, el nombre de tabla correspondlente y otras propiedades.
java.sql.ParameterMetadata
Esta interfaz le permite acceder a 10s tipos de parimetros de bases de datos en instrucciones preparadas.
Excepciones y advertencias Las siguientes clases encapsulan errores de acceso a bases de datos y advertencias: Clase
Descripci6n Esta excepci6n representa todas las condiciones de excepci6n relacionadas con JDBC. Esta excepci6n tambkn incorpora todas las excepciones relacionadas con el driver/base de datos y c6digos de error. Esta excepci6n representa las advertencies de acceso a base de datos. En lugar de tener que capturar esta excepcibn, puede utilizar 10s mCtodos apropiados en java.sql.Connection, java.sql.Statement,
y java .sql .~ e s u tl ~ e paraaccederalas t advertencias. j ava .sql .BatchUpdateException
~ s t e e s u n a c a s o e s ~ e c i a l dava. e j sql .SQLException destinada a actiallzaciones de lotes. Estudiaremos las actualizaciones de lotes mis adelante en este capitulo.
~ s t es e un caso especial de j ava. sql .SQLWarning destinado a errores de truncamiento de datos. Observe ue 10s ti os de datos no siempre coinciden entre Java y Q Q ~ y, e transferencia de datos puede suponer truncamiento de datos. Ademis de estos rasgos, JDBC tambikn proporciona recursos para registros y permisos de seguridad asociada para registros. En las siguientes secciones, estudiaremos algunas de las clases e interfaces mis utilizadas de este API. En particular, aprenderemos: C6mo cargar un driver de base de datos
O C 6 m o abrir una conexi6n de base de datos O C 6 m o enviar instrucciones SQL a bases de datos para su ejecucidn O C 6 m o extraer resultados devueltos de una consulta a una base de datos O Quk son las instrucciones preparadas O La funcidn de 10s tipos JDBC
o
A manejar excepciones y advertencias
Programacion de bases de datos con JDBC
Cargar un driver de base de datos y abrir conexiones La interfaz j a v a .s q l .C o n n e c t i o n representa una conexi6n con una base de datos. Es una interfaz porque la implementaci6n de una conexi6n depende de la red, del protocolo y del vendedor. El API JDBC ofrece dos vias diferentes para obtener conexiones. La primera utihza j a v a .s q l .D r i v e r M a n a g e r y es adecuada para aplicaciones no gestionadas como clientes de base de datos Java aut6nomos. El segundo enfoque esti basado en el paquete j a v a x .s q l que introduce la noci6n de fuentes de datos y es adecuado para el acceso a bases de datos en aplicaciones J2EE. Comencemos considerando c6rno se obtienen las conexiones utilizando la clase j a v a . s q l . D r i v e r M a n a g e r . En una sola aplicaci6n, podemos obtener una o mis conexiones para una o mis bases de datos utilizando diferentes drivers JDBC. Cada driver implementa la interfaz j a v a . s q l . D r i v e r . U n o de 10s rnetodos que define esta interfaz es el metodo c o n n e c t ( ) que establece una conexi6n con la base de datos y devuelve un objeto c o n n e c t i o n que encapsula la conexi6n de base de datos. En lugar de acceder directamente a clases que implementan la interfaz j a v a .s q l .D r i v e r , el enfoque estindar para obtener conexiones es registrar cada driver con j a v a .s q l .D r i v e r M a n a g e r y utilizar 10s metodos proporcionados en esta clase para obtener conexiones. j a v a .s q l .D r i v e r M a n a g e r puede gestionar rnGltiples drivers. Antes de entrar en 10s detalles de este enfoque, necesitarnos entender c6mo JDBC representa la posici6n de una base de datos.
Los URL de JDBC La noci6n de un URL en JDBC es muy similar al modo en que 10s URL se utilizan en otras situaciones. Para poder entender la base ldgica de 10s URL de JDBC, consideremos una aplicacidn que utiliza diversas bases de datos; a cada base de datos se accede mediante un diferentes driver debase de datos. En tal situaci61-1, ic6rno identificamos de forma exclusiva un driver? Ademis, las bases de datos utilizan diferentes tipos de parimetros para obtener conexiones. i C 6 m o se especifican 10s parimetros al establecer las conexiones? Los URL de JDBC proporcionan un modo de identificar un driver de base de datos. U n URL de JDBC representa un driver y la informaci6n adicional especifica del driver para localizar una base de datos y conectarla a 61. La sintaxis del URL de JDBC es como sigue:
Tiene tres partes separadas por dos puntos: 0
Protocolo: En la sintaxis anterior, jdbc es el protocolo. ~ s t es e el h i c o protocolo permitido en JDBC.
0
Sub-protocolo: El sub-protocolo es utilizado para identificar un driver de base de datos, o el nombre de un mecanismo de conectividad de una base de datos, elegido por 10s proveedores del driver de la base de datos.
O Subnombre: La sintaxis del subnombre es especifica de driver. U n driver puede elegir cualquier sintaxis apropiada para su implementaci6n. Por ejernplo, para una base de datos Cloudscape llamada "Movies", el URL a1 que debe conectar es:
Capitulo 4 Alternativamente, si estuvikramos utilizando Oracle mediante el puente JDBC-ODBC, nuestro U R L seria:
donde Movies es D N S establecido utilizando un administrador de driver ODBC. C o m o puede ver, 10s URL de JDBC son lo suficientemente flexibles como para especificar informaci6n especifica del driver en el subnombre.
DriverManager El prop6sito de la clase j ava .sql .DriverManager (gestor de drivers) en JDBC es proporcionar una capa de acceso comGn.encima de diferentes drivers de base de datos utilizados en una aplicaci6n. En este enfoque, en lugar de utilizar clases de implementaci6n Driver individuales directamente, las aplicaciones utilizan la clase DriverManager para obtener conexiones. Esta clase ofrece tres mktodos estiticos para obtener conexiones. Sin embargo, Drive rManager requiere que cada driver que necesite la aplicaci6n sea registrado antes de sepa r que esti ahi. su uso, de mod0 que el ~ r i v e r ~ a n a g e El enfoque JDBC para el registro de un driver de base de datos puede parecer oscuro al principio. En JDBC, intente cargar el driver de base de datos utilizando el actual j ava. lang.ClassLoader.Fijese en el siguiente fragmento de codigo, que carga el driver de base de datos de Cloudscape: try { Class.forName("COM.cloudscape.core.JDBCDriver"); } catch (ClassNotFoundException e ) { / / Driver no encontrado.
En el tiempo de e j e c u c h , elClassLoader localiza y carga la clase COM.Cloudscape .core. JDBCDriver desde alclasspathutihandoel cargadordeclase de autoarranque (bootstrap). Mientras carga una clase, el cargador de clase ejecuta cualquier c6digo estitico de inicializaci6n para la clase. En JDBC, se requiere que cada proveedor de driver registre una instancia del driver con la clase j ava .s ql .DriverManager durante esta inicializaci6n estitica. Este registro tiene lugar automiticamente cuando el usuario carga la clase del driver (utilizando la llamada Class. forName ( ) como anteriormente). j ava .sql .DriverManager es unaclase estiticay proporciona el siguiente metodo para este prop6sito: public static void
registerDriver(java.sq1.Driver)
Alternativamente, podemos especificar una lista de drivers utilizando el mecanismo de propiedades Java. Por ejemplo, el siguiente fragmento permitiria a la clase j ava .sql .Driv.erManagercargar la h a de drivers cuando se realizara un intento de establecer una conexi6n: System.setProperty ("jdbc.driversSS,"C0M.cloudscape.core. JDBCDriver") ;
Puede especificar multiples drivers en forna de lista separada par dos puntos (:). Una vez que el driver ha sido registrado con el j ava .sql .DriverManager,podemos utilizar sus m6todos estiticos para obtener conexiones. Mis adelante, en este mismo capitulo, examinaremos la interfaz j avax .sql .Datasource que proporciona una mejor alternativa a las aplicaciones j ava .sql .DriverManager de J2EE. Sin embargo, puede que todavia seanecesario queutilice j ava .sql . DriverManager para el acceso direct0 a bases de datos fuera de las aplicaciones J2EE.
Pro~ramacionde bases de datos con JDBC
.
La clase j a v a . s q l D r i v e r M a n a g e r especificalos siguientes tipos de m6todos: 0 Mktodos para gestionar drivers 0 MCtodos para obtener conexiones 0 Mktodos para registros
Examinemos cada una de estas ireas sucesivamente.
Mbtodos para gertionar drivers Los siguientes mktodos gestionan drivers. Observe que estos mCtodos estin dirigidos a la implementacibn de drivers y a las herramientas que manipulan drivers: public
static void registerDriver (Driver driver)
Este mktodo es utilizado para registra un driver con el DriverManager. Una clase de driver recientemente cargada debe llamar este metodo para hacerse conocer por el DriverManager. Las clases que implementan la interfaz Driver llaman este metodo durante la inicializacidn estitica para registrar una clase. Una vez registrada, el gestor de driver alberga una referencia a1 driver hasta que Cste es desregistrado. Por razones de seguridad, el gestor de driver asocia el cargador de clases del llamante con cada driver, de mod0 que las clases cargadas desde un cargador de clase tengan acceso Gnicamente a aquellos drivers que son registrados por clases cargadas por el mismo cargador de clases. public static void deregisterDriver (Driver driver)
Este mitodo desregistra un driver del gestor de drivers. public static Driver getDriver (String url)
Dado un URL de JDBC, este metodo devuelve un driver que puede entender el URL. public static Enumeration getDrivers0
Este mktodo devuelve una enumeraci6n de todos 10s drivers registrados JDBC registrados por clases utilizando el mismo cargador de clase.
Metodos para obtener conexiones El gestor de drivers tiene tres variantes de mktodo estitico g e t c o n n e c t i o n ( ) utilizado para establecer conexiones. El gestor de drivers delega estas llamadas en el mktodo c o n n e c t ( ) de la interfaz java.sql.Driver. Dependiendo del tip0 de driver y del servidor de base de datos, una conexi6n puede conllevar una conexi6n de red fisica a1 servidor de base de datos o un proxy a una conexion. Las bases de datos integradas no requieren conexi6n fisica. Haya o no una conexion fisica, el objeto de conexi6n es el Gnico objeto que utiliza una conexi6n para comunicar con la base de datos. Toda comunicaci6n debe tener lugar dentro del context0 de una o mis conexiones. Consideremos ahora 10s diferentes mktodos para obtener una conexi6n: public static Connection getConnection(String url) throws SQLException
.
j a v a .s q l D r i v e rManage r recupera un driver apropiado del conjunto del drivers JDBC registrados. El URL de la base de datos esth especificado en forma de j d b c : s u b p r o t o c o l : subname. Q u e obtengamos o no una conexi6n con este mitodo depende de que la base de datos acepte o no solicitudes de conexi6n sin autentificaci6n.
public static Connection getconnection (String url, java.util.Properties info) throws SQLException
Este metodo requiere un U R L y un objeto java.util. Properties.El objeto Properties contiene cada parimetro requerido para la base de datos especificada. La lista de propiedades difiere entre bases de datos. Dos propiedades c o m h m e n t e utilizadas para Cloudscape con autocommit=true y create = fa1se.Podemos especificar estas propiedades junto con el URL como jdbc:Cloudscape :Movies; autocommit=true;create=trueopodemosestablecerestas propiedades utilizando el objeto Properties y pasar el objeto Properties en el mktodo anterior getconnection 0. String url = "jdbc:cloudscape:Movies"; Properties p = new Properties( ) ; p.put("autocommit", "true"); p.put ("create","true"); Connection connection = DriverManager.getConnection(ur1,
p);
El driver descuida las propiedades n o existentes; si el valor de la propiedad no es vilido, puede obtener una excepci6n. Observe que estas propiedades son especificas del driver y debe recurrir a su documentaci6n del driver para obtener la lista de propiedades requeridas. Para saber mis sobre las propiedades disponibles para Cloudscape 4.0, dirijase ahttp://www.cloudscape.con\/docs/doc~40/doc/html/coredocs/attrib.htm. public static Connection getConnection(String url, String user, String password) throws SQLException
La tercera variante toma usuario y contrasefia como argumentos ademis del URL. ~ s t es e un ejemplo; el siguiente codigo utiliza un driver ODBC, donde Movies es un DNS fijado en la configuracidn de ODBC. Este D N S corresponde a una base de datos que requiere un nombre de usuario y una contrasefia para obtener una conexion: String url = "jdbc:odbc.Movies "; String user = "catalog admin"; String password = "catalog admin"; Connection conn
=
DriverManager.getConr~ection(url, user, password);
Observe que todos estos mktodos estin sincronizados,lo que supone que mis de un thread de aplicaci6n no puede conseguir el mismo objeto j ava .sql .connection.Estos metodos lanzan una excepci6n SQLExcept ion si el driver no consigue obtener una conexi6n. En ocasiones es necesario especificar el tiempo miximo que debe esperar un driver mientras intenta conectar a una base de datos. Los siguientes dos mktodos pueden ser utilizados para fijarlobtener el tiempo limite de registro: public static void setLoginTimeout(int seconds) public static int getLoginTimeout()
El valor por defect0 para el tiempo limite de registro es especifico del driverlbase de datos.
M e t o d o r de registro Los siguientes mktodos acceden o establecen un objeto printwriter con propdsitos de registro: public static void setLogWriter(PrintWriter
out)
Procramacion de bases de datos con JDBC public static Printwriter getlogwriter
()
Ademis, las aplicaciones cliente tambien puden registra mensajes utilizando el siguiente mitodo: public static void println(String message)
Este metodo es utilizado junto con P r i n t w r i t e r establecido por el metodo s e t L o g W r i t e r ( ) para imprimir mensajes de registro.
En JDBC, cada driver es identificado utilizando un URL de JDBC, y cada driver debe implementar la interfaz j a v a s q l D r i v e r . Por ejemplo, en Cloudscape, la clase COM. C l o u d s c a p e c o r e . J D B C D r i v e r implementalainterfazj a v a s q l .~ r i v e r , q u e e s p e c i f i c a l o s siguientes mktodos:
.
public public public public public public
. .
.
boolean acceptsURL (String url) Connection connect(String url, Properties info) int getMajorVersion0 int getMinorVersion0 DriverPropertyInfo getPropertyInfo(String url, Properties info) boolean jdbcCompliant()
La clase D r i v e r M a n a g e r utiliza estos mitodos. En general, las aplicaciones cliente n o necesitan acceder directamente a las clases de driver.
Establecer una conexion Para comunicar con una base de datos utilizando JDBC, debemos en primer lugar establecer una conexi6n con la base de datos a traves del driver JDBC apropiado. El API de JDBC especifica la conexi6n en la interfaz j a v a s q l . C o n n e c t i o n . Esta interfaz tiene 10s siguientes mitodos pbblicos:
.
Crear instrucciones Obtener informacibn de bases de datos
getMetaData ( )
Apoyo de transacciones
s e t A u t o C o d t () g e t A u t o C o d t () commit ( ) r o l l b a c k ( ) setTransactionIsolation() getTransactionIsolation()
Estado de conexion y cierre Configurar diversas propiedades, limpiar recuperar cualquier advertencia genera a
isclosed () close () setReadOnly ( ) isReadOnly ( ) clearwarnings () getwarnings ( )
Convertir strings SQL en SQL especifico de base de datos y configurar vistas y tipos definidos por el usuario
nativeSQL ( ) setcatalog () getcatalog () setTypeMap ( ) qetTvPeMaP ( )
valOresd
Capitulo 4 Las categorias de la tabla anterior representan un intento de descomponer 10s metodos en grupos lbgicos segun sus funcionalidad. En las siguientes secciones, estudiaremos la mayoria de estos metodos. ~ s t es e un ejemplo de establecimiento de una conexi6n JDBC a la base de datos C l o u d s c a p e ~ o v i e s : Connection connection; String url = "jdbc:cloudscape:Movies;create=true"
connection
=
DriverManager.getConnection(ur1);
/ / Acceso a datos utilizando el objeto de conexi6n
. . )
)
.
catch (SQLException e ) { / / Tratar el error aqui finally { try 1 connection. close ( ) ; 1 catch(SQLException e ) { / /
System error?
]
En este ejemplo, el URL especifica el URL de JDBC; c r e a t e = t r u e indica que Cloudscape deberia crear la base de datos M o v i e s si 6sta no existe. Siempre debe capturar la excepci6n S Q L E x c e p t i o ne intentar cerrar la conexi6n despuCs de utilizar la conexibn para acceso a 10s datos. En el APT de JDBC, hay varios metodos que lanzan una exception S Q L E x c e p t i o n . En este ejemplo, la conexi6n se cierra a1 final del bloque f i n a l l y , de mod0 que 10s recursos del sistema pueden ser liberados independientemente del Cxito o fracas0 de cualquier operaci6n de base de datos. Resumamos ahora lo que hemos analizado hasta el momento utilizando un ejemplo sencillo. Este ejemplo registra el driver Cloudscape y establece una conexi6n: / / Importar paquetes requeridos import j ava. sql. Driver; import j ava. sql. DriverManager; import j ava. sql .Connection; import j ava. sql. DatabaseMetaData; import j ava. sql . SQLException; import j ava .sql.DriverPropertyIr~fo; import j ava. util. Enumeration; import java.util.Properties; public class DriverTest { public static void main(String arg[]) { String protocol = " jdbc:cloudscape: c: /CloudscapeDBU; String driverclass = "C0M.cloudscape.core.JDBCDriver"; / / Registrar el driver Cloudscape try 1 Class.forName(driverC1ass); ) catch (ClassNotFoundException cne) { cne. printStackTrace ( ) ; 1. / / Comprobar 10s drivers registrados Enumeration drivers = DriverManager.getDrivers ( ) ; while (drivers.hasMoreElemer1ts i ) ) 1 Driver driver = (Driver) drivers. nextElement [ ) ; System.out .println ("Registered driver: "
+
driver.getClass0.getNamei));
Programacion de bases de datos con JDBC
/ / Acepta este driver el URL conocido if (driver.acceptsURL(protoco1)) I System.out .println ("Accepts URL: "
+
protocol);
1
I
1 catch
(SQLException sqle) sqle.printStackTrace0;
t \
/ / . O b t e n e r una c o n e x i 6 n d e l DriverManager. try I C o n n e c t i o n c o n n e c t i o n = DriverManager.getConnection(protoco1); / / Obtener 10s rnetadatos DatabaseMetaData metaData System.out.println("Product )
connection.getMetaData(); name: " + metaData.getDatabaseProductName()); S y s t e m . o u t . p r i n t l n ( " D r i v e r n a m e : " t m e t a D a t a .getDriverNarne ( catch (SQLException sqle) [ sq1e.printStackTrace ( ) ; =
) ) ;
1
Este ejemplo ejecuta tres tareas cuyo prop6sito es acercarle 10s fundamentos de la programaci6n JDBC: 0 La primera tarea es registrar un driver. Puesto que 10s drivers realizan este registro via inicializacion estitica, todo lo que tiene que hacer es cargar el nombre de clase para el driver especifico que esti utilizando. En este ejemplo, registramos el driver para Cloudscape. Observe que puede registrar mis de un driver de una aplicaci6n dada. 0 La segunda tarea es encontrar cuiles son 10s drivers registrados. Utilizamos java.sql.DriverManager para encontrar una enumeraci6n de 10s drivers registrados en ese momento. Como solo hemos registrado un driver en el primer paso, el segundo paso encontrari s d o un driver. El segundo paso tambikn determina si el driver encontrado acepta el URL conocido. En este caso, determinamos si el driver acepta el URL " jdbc :Cloudscape : c : / CloudscapeDB", donde " c : / c l o u d s c a p e D ~es " el nombre (y localizaci6n) de la base de datos para esta aplicaci6n. 0 El tercer paso es obtener una conexi6n a la base de datos utilizando el mktodo getconnection ( ) en java. sql .~riverManager.Despuksdeobtenerlaconexion,tambikn encontramos algunos de 10s metadatos de la base de datos utilizando j ava .sql DatabaseMetadata obtenidoinvocandoelm6todoget~eta~ata ( ) en java.sq1.Connection.
.
Para poner a prueba este ejemplo, debe axiadir las librerias Cloudscape a su classpath. La principal que requerimos para este ejemplo es cloudscape .j ar,que encontrari en %J2EE~HOME%\lib\cloudscape(o%J2EE%J2EE_HOMEg\lib\cloudscape(o%J2EE_HOME%\HOME%\1ib\~ystem). Despu6s de configurar este classpath, compile y ejecute esta clase. Para Cloudscape 3.6.4, la salida de esta clase seri como sigue:
Capitulo 4
~ s t incluye e el nombre de clase del driver, el URLaceptado, el nombre del producto y el nombre del driver. Fijese en que el nombre del driver es algo criptico. Esto se debe a que las librerias Cloudscape son confundidas para prevenir la descompilaci6n.
Crear y ejecutar instrucciones SQL Podemos utilizar un objeto Connection para ejecutar instrucciones SQL creando un statement, un Preparedstatement o un Callablestatement.Estos objetos abstraen instrucciones SQL normales, instrucciones preparadas y procedimientos almacenados respectivamente. Una vez hemos obtenido uno de esos objetos de instrucciones, podemos ejecutar la instrucci6n y leer 10s resultados gracias a un objeto ResultSet. Como hemos mostrado en la tabla anterior, 10s siguientes mttodos crean objetos de instrucciones: Statement createstatement0
throws SQLException
Este mttodo crea un objeto statement, que podemos utilizar para enviar instrucciones SQL a la base de datos. Las instrucciones SQL sin pardmetros son ejecutadas normalmente utilizando objetos Statement. Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
Esta variante de createstatement ( ) requiere el Tipo Result Set y argumentos resultSetconcurrency.Estos argumentos se aplican a objetos ResultSet creados ejecutando consultas. De estos dos argumentos, el primero es utilizado para especificar el tipo ResultSet requerido. Como veremos mds adelante, existen tres tipos de resultados dependiendo de su capacidad de desplazamiento: desplazables s61o hacia adelante (ResultSet.TYPE-FORWARD-ONLY), desplazables pero insensibles a 10s cambios realizados por otras transacciones (ResultSet.TYPE-SCROLL-INSENSITIVE) o desplazables y sensibles a 10s cambios realizados por otras transacciones (ResultSet .TYPE-SCROLL-INSENSITIVE). Lainterfazjava. sql. ~ e s u l t ~ e t e s p e c i f i c a t r e s constantes como tipos de resultados. El segundo argumento es utilizado para especificar si el Result set es de s61o lectura (ResultSet. CONCUR-READ-ONLY) o deberiaseractualizable (Result Set. CONCUR-UPDATEABLE). El mttodo de no argumento createstatement hacia adelante y de s d o lectura.
()
devuelve un ~ e s u l set t que s61o es desplazable
Programacion de bases de datos con JDBC El mCtodo createstatement ( ) no toma argumentos (except0 para tip0 y concurrencia donde sean aplicables) y devuelve un objeto statement. El objetivo final de un objeto statement es ejecutar una instrucci6n SQL que puede o no devolver resultados. Veremos un ejemplo pr6ximamente. public Preparedstatement prepareStatement(Strin9
sql) throws SQLException
Podemos obtener un objeto Preparedstatement invocando este metodo en una connection.Mis adelante en este capitulo, haremos un recorrido por el uso de instrucciones preparadas para ejecutar instrucciones SQL. public Callablestatement preparecall
(String sql) throws SQLException
Este metodo es utilizado para invocar un procedimiento almacenado. La interfaz statement tiene 10s siguientes mCtodos:
Ejecutar instrucciones
execute ( ) executeQuery ( ) executeupdate ( )
Actualizaciones lotes
Tamaho de toma de resultset
Obtener resultset actual Resultset concurrency and type Otros
setQueryTimeout ( ) getQueryTimeout ( ) setMaxFieldSize ( ) getMaxFieldSize ( ) cancel ( ) getconnection ( )
Statements tambikn se ajusta a 10s mismos mktodos para transacciones que el objeto connection, junto con el metodo close ( ) .
Hay dos subinterfaces Prepareds tatement y CallableS tatement,que son utilizadas para invocar instrucciones SQL precompiladas y procedimientos almacenados de base de datos. Estas dos interfaces especifican mktodos adicionales para preparar instrucciones e invocar procedimientos almacenados.
Un ejemplo: catiilogo de peliculas Para ilustrar el API JDBC, consideremos un simple catilogo de peliculas. La base de datos para este ejemplo consiste en una tabla llamada CATALOG. Consideremos una clase Java CreateMovieTable que Cree una tabla CATALOG e inserte 10s datos en la tabla. En este ejemplo, recuperamos 10s datos de un archivo de texto, catalog. txt,y 10s insertamos en la CATALOG.
209
Capitulo 4 Crear la tabla Movie
El rnCtodo i n i t i a l i z e ( ) carga el driver y obtiene una conexi6n. c r e a t e t a b l e ( ) crea la tabla. Puede utilizar el siguiente mktodo en el objeto s t a t e m e n t para insertar datos: int executeUpdate(String
sql) throws SQLException
e x e c u t e U p d a t e ( ) es utilizado para ejecutar instrucciones SQL que no devuelven ning6n resultado, por ejernplo instrucciones INSERT, UPDATE o DELETE. Este rnCtodo devuelve un nGrnero entero que denota el n h n e r o de las filas afectadas: public class CreateMovieTables { static String driver = "COM.cloudscape.core.JDBCDriver"; static String url = "jdbc:cloudscape:"; Connection connection = null; Statement statement = null; / / ... public void initialize ( ) throws SQLException, ClassNotFoundException [ Class.forName (driver); + "Movies;create=trueW); connection = DriverManager.getCor~r~ectior~(url
I public void createTable() throws SQLException [ statement = connection.createStatement(); statement.executeUpdate("CREATE TABLE CATALOG" + " (TITLE VARCHAR(256) PRIMARY KEY NOT NULL, "LEAD ACTOR VARCHAR(256) NOT NULL, " + "LEAD ACTRESS VARCHAR(256) NOT NULL, " + "TYPE VARCHAR(20) NOT NULL, " + "RELEASE DATE DATE NOT NULL)");
"
+
I En este c6dig0, las variables c o n n e c t i o n y s t a t e m e n t son variables de instancias de la clase C r e a t e M o v i e T a b l e s . E l r n C t o d o c r e a t e ~ a b l e( ) obtieneunaconexi6nde~~river~anager.Para Cloudscape, especificarnos e~protoco~ocorno" j d b c :c l o u d s c a p e : M o v i e s ; c r e a t e = t r u e n . Cuando crearnos una tabla por prirnera vez utilizando este URL, Cloudscape DMBS crea un subdirectorio bajo el directorio actual llarnado " M o v i e s " para alrnacenar 10s datos. Consulte la docurnentaci6n Cloudscape para especificar un directorio diferente. En caso de que desee lirnpiar su base de datos, puede elirninar este directorio y volver a crear todas las tablas. Puede acceder a la docurnentaci6n de Cloudscape online enhttp://www.cloudscape.comlsupportldocumentation.html. En el c6digo anterior, el e x e c u t e U p d a t e ( ) no actualiza ning6n registro de la base de datos y por ello el rnktodo devuelve cero. En el caso de las instrucciones INSERT, UPDATE o DELETE puede que estC interesado en el nfirnero de filas insertadas, actualizadas o elirninadas, respectivarnente. Observe tarnbikn que el esquema utilizado en este ejernplo es s61o con fines ilustrativos y no refleja de una forma realista 10s datos del catilogo. DespuCs de conseguir una conexion, el siguiente paso es crear una instruccibn. Pasamos una instrucci6n SQL para crear la tabla utilizando el mCtodo e x e c u t e u p d a t e ( ) en la instrucci6n. Como puede ver en la instrucci6n anterior, la tabla CATALOG tiene cinco columnas. lnsertar datos
El mktodo i n s e r t D a t a ( ) de la c l a s e ~ r e a t e ~ o v i e ~ a blee l eregistros s de pelicula de una archivo de texto y 10s inserta en la base de datos:
Programacion de bases de datos con JDBC public void insertData ( ) throws SQLException, IOException { BufferedReader br = new BufferedReader(r1ew FileReader("catalog.txt"));
title = br.readLine( ) ; 1eadActor = br. readline ( ) ; 1eadActress = br. readline ( ) ; type = br. readline ( ) ; dateOfRelease = br.'read~ine ( ) ; String sqlString
}
"INSERT INTO CATALOG " t " (TITLE, LEAD ACTOR, LEAD ACTRESS, "t "TYPE, RELEASE DATE) " t "VALUES(\" t title t "',"' t 1eadActor t "',"' t 1eadActress "\,"' t type t "',"' t dateOfRelease t
t "\)";
staternent.executeUpdate(sq1String); statement. close ( ) ; while(br.readLine ( ) ! = null); / / This reads the termination line
}
]
=
catch (IOException e ) e.printStackTrace() finally { br. close ( ) ;
{
I Elformato delarchivo deentradaes t i t u l o , a c t o r p r i n c i p a l , a c t i z p r i n c i p a l , t i p 0 y f e c h a d e E s t r e n o introducidos en lineas separadas, seguidos de una linea separatoria como se muestra a continuaci6n: Austin Powers Mike Myers Liz Hurley Comed y 1999-04-01
En el c6digo anterior, la unica instrucci6n que es relevante para nuestro anilisis es el mCtodo s t a t ement e x e c u t eUpdat e ( ) invocado para insertar 10s datos en la tabla CATALOG. Observe que n o capturamos aqui S Q L E x c e p t i o n .En su lugar, estamos dejando a1 llamante de este mCtodo capturar la excepci6n SQL.
.
Metodos para el manejo de excepciones C o m o hemos mencionado con anterioridad, la mayoria de 10s mCtodos en las interfaces y clases JDBC lanzan una instancia de SQLExcepti o n para indicar que hay un fallo. Sin embargo, dependiendo de 10s drivers y las bases de datos que est.6 utilizando, podri haber varias capas y fuentes de error. Para acomodar esto, la excepci6n S Q L puede ser anidada, integrando diversas excepciones en una lista vinculada. Podemos utilizar el metodo g e t N e x t E x c e p t i o n ( ) en la clase SQLExceptionpara recuperar todas esas excepciones. El siguiente fragment0 de c6digo recorre recursivamente las excepciones disponibles. Este enfoque puede resultar informativo para el manejo de excepciones en nuestras aplicaciones JDBC:
while (sqlException ! = null) {
Capitulo 4
De un modo similar, puede recuperar advertencias (incluido las especificas del vendedor) recibidas o generadas por el driver utilizando el metodo getwarnings ( ) en la conexi6n: SQLWarrling warnings
=
connection.getWarnings
while(warnings ! = null) { System.err.println ( c o n n e c t i o n . g e t W a r r i i n g s warnings = warnings. getNextWarning ( ) ;
( );
( ) ) ;
I ~ s t es a la fuente completa: import import import import import import import import import import import import
j ava. sql. DriverManager;
j ava. sql. Connection; j a v a .sql .Statement; java.sq1.PreparedStatement; java.sql.SQLException; j ava. sql . Date; java.io.BufferedReader; java. i o . FileReader; j ava. io. IOException; j ava. io. EOFException; java.text.Simp1eDateForrnat; j ava. text. ParseExcept ion;
//
Esta clase requiere un archivo d e texto Llamado catalog.txt contenga / / 10s datos d e entrada. public class CreateMovieTables
que
{
static String driver = "COM.cloudscape.core.JDBCDri~er"; static String url = "jdbc:cloudscape:"; String title, leadActor, Connection connection; Statement statement;
leadActress, type, dateOfRelease;
public void initialize ( ) Class.forName(driver);
throws SQLException, ClassNotFoundException {
.getConr~ection (url + "Movies; create=trueT'); conr~ection = DriverMar~ager )
public void c r e a t e T a b l e 0 throws SQLException [ statement = connection. createstaterner~t( ) ; statement.executeUpdate("CREATE TABLE CATALOG" + "(TITLE VARCHAR(256) PRIMARY KEY NOT NULL, " + "LEAD ACTOR VARCHAR (256) NOT NULL, " + "LEAD ACTRESS VARCHAR(256) NOT NULL, " + "TYPE VARCHAR(20) NOT NULL, " + "RELEASE DATE DATE NOT NULL) " ) ; 1
public void i n s e r t D a t a 0 throws SQLException, IOException { BufferedReader b r = r ~ e w BufferedReader(r1ew FileReader("catalog.txt")i;
Programaci6n de bases de datos con JDBC
title = br. readline ( ) ; leadActor = br. readline ( ) ; 1eadActress = br. readline ( ) ; type = br. readline ( ) ; dateOfRelease = br. readline ( ) String sqlstring
=
;
"INSERT INTO CATALOG " + "(TITLE, LEAD ACTOR, LEAD ACTRESS, " + "TYPE, RELEASE DATE) " + "VALUES( "' + title + 11 \ , + leadActor + "',"' + leadActress + "',"' + type t "',"' + dateOfRelease + " ' ) " ; 1 1 1
}
1
statement.executeUpdate(sq1String); statement.close(); while (br.readLine() ! = null); / / This reads the termination line
catch (IOException e ) { e.printStackTrace ( ) ;
I finally { br.close0;
I I public void close ( ) throws SQLException 1 try I connection. close ( ) ; ) catch (SQLException e ) { throw e;
t
I
public static void main (String arg [ 1 ) { CreateMovieTables movies = new CreateMovieTablesO; try i movies.initialize(); rnovies.createTable() ; movies.close(); ] catch (SQLException sqlException) { while (sqlException ! = null) { sq1Exception.printStackTrace ( ) ; sqlException = sqlException.getNextExceptior~( ) ;
I ]
catch (Exception e) { e.printStackTrace ( ) ;
1
I 1
C o n objetivos de demostraci61-1, esta clase e s t i estructurada en terminos de pequefios metodos, cada uno de 10s cuales desempefia funciones JDBC especificas. En esta clase, el metodo i n i t i a l i z e ( ) carga el driver y crea una conexi6n. El metodo c r e a t e T a b l e ( ) crea una tabla utilizando el metodo e x e c u t e u p d a t e ( ) enlainstrucci6n j a v a . s q l . S t a t e m e n t . El m e t o d o i n s e r t ~ a t a( ) leeunaserie de registros de un archivo de texto y 10s inserta en la tabla. El metodo m a i n ( ) de esta clase es el controlador que invoca 10s otros metodos en secuencia. Observe que el metodo m a i n ( ) invoca el metodo c l o s e ( ) para cerrar la instrucci6n y la conexi6n.
Capitulo 4 Fijese que de 10s campos insertados en el mitodo anterior, aunque el campo RELEASE-DATE es de tip0 DATE, utilizarnos un string a1 crear la instrucci6n. Esto es vilido siempre que el String utilizado pueda ser forzado de forrna segura en un carnpo DATE. En este ejemplo, el string utilizado es de la forrna YYYYMM-DD, que es traspasable a un carnpo DATE. Sin embargo, para que Sean seguros, debe considerar utilizar instrucciones preparadas para ejecutar SQL que conlleve datos introducidos corno fechas, estampillas de tiernpo, nfirneros, etc. Para la mayor parte de 10s ejernplos restantes de este capitulo, seguiremos la clase anterior corno plantilla. Si desea experirnentar con el APIJDBC, debe ariadir nuevos rnitodos a esta clase.
Consultar la base de datos El o b j e t o s t a t e m e n t devuelve un objeto j a v a . s q l . R e s u l t S e t que encapsulalos resultados de ejecuci6n. Esta es una interfaz que es implernentada por vendedores de drivers. Puede desplazar 10s bloques de resultados utilizando un cursor para leer 10s resultados en R e s u l t s e t. El siguiente r n C t o d o , e x e c u t e Q u e r y 0,en lainterfaz j a v a . s q l . S t a t e m e n t le perrnite ejecutarlas instrucciones SQL SELECT: public ResultSet executequery
:
(String sql) throws SQLException
Existe tarnbikn un rnitodo genirico e x e c u t e ( ) que puede devolver multiples resultados: public boolean execute(String sql) throws SQLException
Este metodo execute() puede utilizarse para ejecutar procedimientos almacenados conocidos para ofrecer mdtiples resultados o strings SQL desconocidas (por ejemplo, instrucciones SQL leidas en otras fuente en el tiempo de ejecuci6n). Este rnetodo devuelve un Boolean con valor true cuando la ejecuci6n tiene como resultado uno o rnis bloques de resultados, o un valor false cuando la ejecuci6n tiene como resultado una o mis cuentas de actualizaci6n. Utilizando este valor de retorno, la aplicaci6n puede invocar 10s rnetodos getResult () o getupdate() para acceder al bloque de resultados o actualizar la cuenta, respectivarnente. El API JDBC 2.1 introduce dos tipos rnis de ResultSet que perrniten desplazar 10s resultados hacia adelante y hacia atris per0 no todos 10s vendedores de bases de datos se ajustan en la actualidad a esta caracteristica. Analizaremos el desplazamiento de resultados posteriorrnente en este capitulo.
Metodos para recuperar datos
.
.
La interfaz j a v a s q l ~ e s u lSte t ofrece varios rnitodos para recuperar carnpos de diferentes tipos. Dependiendo de su esquema, deberi utilizar 10s rnetodos apropiados para recuperar 10s datos: getArray ( )
getAsciiStream()
getBigDecimal()
getBinaryStream
getBlob ( )
getBoolean ( )
9etByte ()
getBytes
getcharacter Stream0
getClob
getDate ( )
getDouble ( )
GetFloat
getInt ()
getLon9 ( )
getobje c t ()
getshort ()
getstring ()
getTime ( )
getRef
()
()
getTimestamp ( )
()
getURL ( )
()
Programacion de bases de datos con JDBC Todos estos metodos requieren el nombre de la columna (como un string) o el indice de la columna como argumento. La sintaxis para las dos variantes de 10s mitodos getstring ( ) son las siguientes: public String getString(int columnIndex) throws SQLException public String getString(String columnlame) throws SQLException
En casos en 10s que el indice de la columna estd sujeto a1 cambio debido a cambios en SQL o en el esquema de la base de datos es preferible utilizar nombres de columna en estos metodos. Los tipos devueltos de estos mitodos varian desde simples primitivas Java como int,double,byte, etc., hasta tipos SQL de prop6sito especifico como j ava .sql lob y java .sql lob. Los metodos getAsciiStream(),getBinaryStream(,)ygetCharacterStream() permitenelaccesoadatos ASCII/caracteres arbitrariamente largos devolviendo objetos j ava . io . Inputstream y j ava.io.Reader. Volvamos a nuestro catdogo de peliculas y creemos otra clase, Que ryMovieTable,para implementar diferentes tipos de consultas. El siguiente mitodo, queryAll ( ) , recupera todos 10s datos de la tabla CATALOG: public void queryAll(1 throws SQLException { Systern.out.println("Query All") ; Statement statement = connection. createstatement ( ) ; String sqlstring
ResultSet
rs
=
=
"SELECT CATALOG.TITLE, CATALOG.LEAD ACTOR, "CATALOG. LEAD ACTRESS, CATALOG. TYPE, " + "CATALOG.RELEASE DATE FROM CATALOG";
"+
statement.executeQuery(sqlString);
while (rs.next ( ) ) { System.out .println(rs.getString("TITLEt') t ", " t rs .getString,("LEAD ACTOR") t ", " t rs.getStringiMLEAD ACTRESS") t ", " t rs.qetString("TYPE") t ", " t rs.getDate("RELEASE DATE"));
1
I
Este m i t o d o crea primero un objeto statement,que utiliza entonces para invocar executeQuery ( ) con una instrucci6n SELECT SQL como argumento. El objeto j ava .sql .ResultSet contiene todas las filas de la tabla CATALOG que coinciden con la instrucci6n SELECT. Utilizando el metodo next ( ) del objeto ResultSet,podemos repetir todas las filas contenidas en el bloque de resultados. En cualquier fila, podemos utilizar uno de 10s mitodos getXXX de la tabla anterior para recuperar 10s campos de una fila. i Q u e sucede si la consulta (o cualquier SQL enviado a la base de datos a traves del driver para su ejecuci6n) es muy cara y tarda mucho tiempo en completarse? Esto puede ocurrir, por ejemplo, si la consulta es compleja o si la base de datos esti intentando devolver un gran ndmero de resultados. Para controlar el tiempo que espera el driver para que la base de datos complete su ejecucibn, la interfaz j ava .sql . statement tiene dos mktodos para obtener o fijar un limite mdximo de tiempo. Por ejemplo, podemos modificar el metodo quer y ~ l (l) para establecer un intervalo de tiempo miximo para la consulta (en segundos) utilizando el mitodo setQueryTimeout ( ) . Puede utilizar el metodo getQueryTimeout ( ) para conocer el intervalo de tiempo de la consulta en segundos (o el valor por defecto, si n o se ha fijado explicitamente). Una vez que la base de datos excede el intervalo miximo de tiempo, el driver aborta la ejecuci6n y lanza una excepci6n j ava .sqlSQLException.Por ejemplo, aqui fijamos el valor del plazo limite de tiempo en 1 segundo:
Capitulo 4 4
Statement staten~erlt = connection. createstatement ( ) ; statement.setQueryTimeout(1); / / Establecer SQL para la irjstrucci6n ResultSet rs = statement .executeQuery ( s q l s t r i n g );
lnterfazResultSetMetaData
La interfaz ResultSet tambien nos permite conocer la estructura del bloque de resultados. El metodo getMetaData ( ) nos ayudaa recuperarun objeto java. sql .ResultSetMetaData que tienevarios metodos para describir 10s cursores del bloque de resultados: GetCatalogName ( ) getTableName ( ) Get SchemaName ( ) GetColumnCount ( ) GetColumnName ( ) ) GetColumnLabel ( ) GetColumnType ( )
Tomando un bloque de resultados, podemos utilizar el metodo getcolumncount ( ) para obtener el numero de columnas del bloque de resultados. Utilizando este numero de columnas, podemos obtener la meta-informaci6n de cada columna. Por ejemplo, el siguiente metodo de nuestro ejemplo imprime la estructura del bloque de resultados: public vold g e t M e t a D a t a 0 throws SQLException { System.out .prlntln("MetaData o f ResultSet") ; Statement statement = connection.createStatement(); String sqlString ResultSet
rs
=
=
"SELECT
statement.executeQuery(sq1String);
ResultSetMetaData metaData int nocolumns
=
* FROM CATALOG";
=
rs .getMetaData (
metaData.getColumnCount (
) ;
) ;
/ / Nhmero d e columna empezando desde el 1 for(int i = 1; i < nocolumns t 1; it+) { System.out.println(metaData.getColumnName(i) metaData. getColumnType(i)
+ "
"
+
) ;
I I El metodo anterior obtiene el numero de columnas del bloque de resultados e imprime el nombre y el tip0 de cada columna. En este caso, 10s nombres de columna son TITLE, LEAD-ACTOR, LEAD-ACTRESS, TYPE y RELEASE-DATE. Observe que 10s tipos de columna son devueltos como numeros enteros. Por ejemplo, todas las columnas tipo VARCHAR tendrin el tipo de columna 12, mientras que el tipo DATE es
Programacion de bases de datos con JDBC tipo 91. Estos tipos son constantes definidas en la interfaz j a v a .s q l . T y p e s . Fijese tambikn en que 10s numeros de las columnas empiezan desde 1 y no desde 0. Esta informaci6n puede utilizarse para decidir c6mo tratar este tip0 de datos. Por ejemplo, conociendo que la quinta columna es tipo DATE (fecha), la aplicaci6n puede determinar que un j a v a .s q l .D a t e deberia utilizarse para representar este dato. Aunque esta informaci6n puede derivarse del estudio del esquema de la base de datos y del SQL utilizado para extraer 10s datos, 10s metadatos de la base de datos pueden utilizarse para reducir la codificaci6n de dicha informaci6n.
lnstrucciones preparadas Las instrucciones preparadas JDBC cumplen 10s siguientes requisitos:
o
Crear instrucciones parametrizadas de mod0 que 10s datos para parimetros puedan ser sustituidos dinimicamente
O Crear instrucciones que impliquen valores de datos que no siempre pueden ser representados como strings de caracteres O
Precompilar instrucciones S Q L para evitar la compilaci6n repetida de las mismas instrucciones S Q L
Analicemos brevemente las razones de la importancia de estos requisitos. En la mayoria de 10s casos, puede que n o tenga la informacion completa para construir una cliusula DONDE en SQL. Por ejemplo, para escribir una instrucci6n SQL SELECT para seleccionar 10s datos de un usuario, mientras escribe el c6digo JDBC, necesita conocer el valor clave primario (como el USER-ID) para construir el SQL. En la mayor parte de 10s casos, esta informacion esti disponible s61o en el period0 de ejecuci6n (digamos, desde una interfaz de usuario o desde cualquier otra aplicaci6n). Las instrucciones preparadas se enfrentan este problema proporcionando parimetros (expresados como signos de interrogaci6n) en SQL. En lugar de utilizar valore, puede utilizar calificadores " ? " en SQL. Por ello, en vez de crear una instrucci6n con el string SQL: SELECT
En el caso de las aplicaciones Web, el D T D es parte de la especificaci6n J2EE para aplicaciones Web y es estdndar para todas nuestras aplicaciones Web. La verdadera definici6n de 10s sewlets aparece entre etiquetas . Dentro de la etiqueta , fijese en las tres entradas para el nombre del sewlet, el nombre de presentacih del sewlet, y la clase cualificada Java. La etiqueta permite a1 contenedor Web conocer el nombre utilizado para referirse a un sewlet:
Recuerde que FORM en index.htm1 envia la solicitud a un URL relativo, /greeting/servlet / GreetingServlet. El valor de es un alias para el verdadero nombre de clase. Este rasgo nos permite cambiar 10s archivos de clase sewlet cambiando nuestras piginas HTML u otros sewlets. Tambiin podemos desplegar el mismo sewlet mis de una vez en la misma aplicaci6n Web. Para conseguirlo, s61o necesitamos utilizar nombres diferentes.
Capitulo 5
Este capitulo ofrece un anilisis de 10s contenedores Web, sin entrar en muchos detalles sobre 10s API subyacentes. El prop6sito de este capitulo es introducirle en el desarrollo de aplicaciones Web utilizando servlets Java. Ademis de ilustrar el modelo de programaci6n de servlets Java con la ayuda de una sencilla aplicaci6n, este capitulo cubre 10s siguientes puntos: 0
Los principios bisicos de HTTP: 10s diferentes tipos de solicitudes y detalles del paradigma de solicitudes y respuestas H T T P
0
Los servlets Java, las paginas JSP y 10s descriptores de despliegue
0
Los pasos necesarios para la construcci6n de una sencilla aplicacion Web para recabar datos de 10s usuarios y generar una respuesta utilizando la implementaci6n de referencia J2EE
Aunque estas ireas ilustran el modelo bisico de desarrollo de aplicaciones, hay otras diversas caracteristicas necesarias para construir utiles aplicaciones Web de calidad de producci6n. En 10s siguientes capitulos profundizaremos en las tecnologias de servlets y JSP. Mis concretamente, en 10s siguientes cuatro capitulos trataremos: 0
En el capitulo 6, examinaremos el API Servlet con detalle. Ademis, este capitulo tambitn analizari el ciclo de vida de 10s servlets y el API de solicitud y respuesta.
0
El capitulo 7 le presentari 10s conceptos de sesiones y contexto, y su funci6n esencial para el desarrollo de aplicaciones Web. Este capitulo tambitn estudiari c6mo utilizar dos o mis servlets o piginas JSP en coordinacion.
O
El capitulo 8 le presentari 10s filtros. Los filtros le permiten intenenir en el proceso en el que el contenedor invoca 10s senlets y las piginas JSP, o sirve contenido estatico.
0
El capitulo 9 analizari detenidamente 10s descriptores de despliegue y c6mo utilizarlos para proporcionar seguridad a las aplicaciones.
Estos capitulos le mostrarin el desarrollo de varias aplicaciones Web. Estas muestras se centrarin en diferentes aspectos del API servlet e incorporarin lo que ha aprendido en este capitulo.
Programacion de servlets Los servlets son bloques de construccidn bisicos para construir interfaces de base Web para aplicaciones. La tecnologia de servlets proporciona un modelo de prograrnacidn comGn que es tambiCn la base de las Piginas JavaServer. En capitdo anterior, hemos visto un andisis de las aplicaciones Web y 10s contenedores Web, en el que hemos repasado 10s requisitos de prograrnaci6n y estructura bisica de las aplicaciones Web. DespuCs nos hernos centrado en presentar 10s principios bisicos de 10s contenedores Web y las aplicaciones Web, y en c6rno las aplicaciones Web pueden ser programadas para rnejorar el proceso de solicitud-respuesta HTTP. El objetivo de 10s siguientes capitulos es presentar el API Java Servlet 2.3, que puede ser descargado desde http://java.sun.com/productS/servlet. Este API inchye dos paquetes: j avax .servlet y j avax. servlet .http.
Fijese en que el paquete javaxsmlet tiene dos subpaquetes para JSP (javax.servlet.jsp) y las etiquetas de adaptaci6n JSP (jsp.servlet.jsp.tagext). Estos paquetes s e r h analizados a partir del capitulo 10. Analizaremos el API Java Servlet en cuatro pasos:
O Irnplernentacidn de servlets
o
Solicitudes y respuestas
O Sesibn, context0 y colaboracidn de servlet O Filtrado de solicitudes y respuestas
En este capitulo, nuestra intencidn es analizar 10s pasos primer0 y segundo; el tercer paso sera analizado en el capitulo 7 y el cuarso en el capitulo 8. Adicionalmente, estudtaremos 10s aspectos de despliegue en el capitulo 9. En este capitulo, examinaremos 10s siguientes puntos:
0
Clases e interfaces para la irnplernentacidn de sewlets, incluido las excepciones de sewlet
O Configuracidn de sewlets O
El ciclo de vida de 10s sewlets
0
Solicitudes y respuestas
i-1 El modelo de programacidn del sewlet
Fijese en que este capitulo no pretende ser una referencia exhaustiva para 10s paquetes j a v a x . s e r v l e t y j a v a x . s e r v l e t .h t t p . En carnbio, analizarernos estos paquetes y 10s conceptos que 10s respaldan, concentrindonos en cdrno utilizar el API durante el desarrollo de las aplicaciones. La docurnentacidn del API Sewlet debe tenerlo a cerca mientras lee este capitulo. Puede acceder a esta docurnentacidn online en http://java .sun.com/products/servlet,/2.3/javadoc/index.htrn1.
Analisis del API Java Servlet Corno ya hemos visto, el API Sewlet esti especificado en dos paquetes de extensidn Java: j a v a x . s e r v l e t y j a v a x . s e r v l e t .h t t p . Las clases e interfaces contenidas en el paquete j a v a x .s e r v l e t son independientes del protocolo, rnientras que el segundo paquete, j a v a x . s e r v l e t h t t p , contiene clases e interfaces que son especificas de HTTP. Observe que algunas de las clases/interfaces en j a v a x .s e r v l e t .h t t p arnplian las especificadas en el paquete javax. s e r v l e t .
.
La siguiente figura rnuestra el diagrarna de clase para algunas de las clases centrales del paquete j a v a x . s e r v l e t y algunas de sus asociaciones:
mterfaz ModeloThreadUnico
I I t lnterfaz RqJLIe~taSeNlet -
--
t
'
mterfaz SolicitudSelvi>
I
mterfaz Sewietbntext
I I
t
t StrearnSal~da StreamSalida
StrearnEntrada StreamEntrada
I
+
mterfaz LanzadorSolicitud
1
~
Las flechas continuas representan asociaciones, mientras que las flechas discontinuas indican dependencias. Una asociacidn puede ser herencia, composicidn o incluso navegabilidad. La dependencia indica algun tip0 de combinacidn entre clases. Por ejemplo, la flecha discontinua que va desde la interfaz javax.servlet.Servlet basta javax.servlet.ServletRequest indica que el primero depende del ultimo y cualquier cambio en el primero depende del riltimo, y cualquier cambio en la Lltima definicidn de interfaz provoca cambios en el primero.
Programacion de servlets La siguiente figura muestra algunas de las clases/interfaces del paquete j a v a x . s ervlet .ht tp: -
lnterfaz escuchante de eventos Escuchantede asociacion
intern
de sesion http -
--
I
~nterfaz RespuestaServletHttp
o..*
--
Cookle clonable Cookie
ava lo Ser~al~zable
va lo Ser~al~zable
Sol~c~tudServleHtt
A~nterfaz Sesi6nHttp -
1
1
Observe que el contenedor rnantiene todas estas asociaciones, siernpre y cuando este' utilizando el paquete ja v a x . s e r v l e t . h t t p . Sin embargo, si estd construyendo servlets especializados que arnplien las clases del paquete 1a "a: . s*r 1.1 * t , tendra' que rnantener algunas de las asociaciones. Estos diagramas no representan el API Sewlet completo. Para una mayor sencillez, estas figuras s610 destacan aquellas clases/interfaces que son necesarias para proporcionar un anilisis de este API. Presentaremos la parte restante del API durante 10s siguientes capitulos. iCuil es el prop6sito de todas estas interfaces y clases? Consideremos las siguientes cuestiones: O
iC6mo gestiona el contenedor Web el ciclo de vida de 10s senlets? iC6mo pueden 10s senlets participar en este ciclo de vida?
O
iC6mo implementamos la bgica de aplicaci6n? La 16gica de aplicaci6n en senlets es la &ica de programaci6n para responder a las solicitudes HTTP. Dependiendo de la arquitectura y complejidad de las aplicaciones, h a podria ser acceder a bases de datos, invocar 10s senicios de diversos EJB u otros componentes de capa media, o utilizar JMS para enviar mensajes a otras aplicaciones de empresa, etc.
O
iC6mo leemos solicitudes HTTP y c6mo generamos respuestas HTTP?
O
i C 6 m o tratamos las excepciones en 10s senlets?
0
iC6mo pueden 10s sewlets interactuar con su entorno?
N o intentaremos responder a estas preguntas en este momento pero, despuks de leer este capitulo, podremos responderlas. La siguiente tabla ofrece un anilisis del API Java Senlet, que seri examinado con detalle en breve. En esta tabla, varias intefaces/clases estin agrupadas segGn su prop6sito y uso (que estudiaremos en un momento). Las interfaces aparecen en cursiva, mientras que las clases (ya sean abstractas o no) y excepciones aparecen en fuente normal. Las adiciones a1 API Senlet de la versi6n 2.3 estin marcadas con un asterisco (:'):
Capitulo 6
Implementaci6n de servlet
javax.servlet.Servlet javax.servlet.Sir~gleThreadMode1 j a v a x . s e r v l e t .GenericServlet javax.servlet.http.HttpServ1et
Configuraci6n de servlet
j avax. s e r v l e t . S e r v l e t C o r ~ f i g
Excepciones servlet
javax.servlet.ServletExceptior~
Solicitudes y respuestas
javax.servlet.http.HttpServ1etRequest
j avax. s e r v l e t . U n a v a i l a b l e E x c e p t i o r ~
javax.servlet.http.HttpServletRequestWrapper(*) javax.serv1et.http.HttpServletResporjse javax.servlet.http.HttpServletRespor~s~eWrapper
j avax. servlet. ServletIr~putStrearn i t ) javax.servlet.Servlet0utputStrearn
javax.servlet.Serv1etRequest javax.servlet.ServletRequestWrapper
j+)
javax.servlet.ServletRespor~se javax.servlet.Serv1etResponseWrapper
( * )
javax.servlet.http.HttpSessior~ javax.servlet.http.HttpSessior~Activatior~Listerer( + ) javax.servlet.http.HttpSessior~AttributeListener i t !
j avax. servlet. http. H t t p S e s s i o r ~ B i r ~ d i r ~ g L i s t e r ~ e r j a v a x . servlet. http. H t t p S e s s i o n B i r ~ d i r ~ g E v e r ~ t j avax. servlet. http. HttpSessionEvent
it)
javax. servlet . h t t p . H t t p S e s s i o r ~ L i s t e r e r
Contexto de servlet
( * )
javax.servlet.Serv1etContext
javax. servlet. S e r v l e t C o r ~ t e x t A t t r i b u t e E v e r t i t ) javax.servlet.ServletContextAttributeLister~er javax. servlet. ServletCor~textEver~t(
* )
j avax. servlet. ServletCor~textListerer i t
Colaboraci6n de servlet
javax.serv1et.RequestDispatcher
Filtrado
javax. servlet. Filter
( * )
javax. servlet. Filterchain javax. servlet. FilterCorifig
Varios
( + )
it)
j a v a x . s e r v l e t .h t t p . C o o k i e javax.servlet.http.HttpUti1s
)
(*)
Programacion de servlets Los servidores Web con las implementaciones de Java Servlet, como Tomcat, WebLogic, Orion, iPlanet, JRun, etc., utilizan la mayoria de las interfaces y clases que aparecen en la tabla anterior. De hecho, aparte de las diversas interfaces escuchadoras de la tabla, s61o queda una clase abstracta ( j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ) yunainterfaz(javax. s e r v l e t . F i 1 t e r ) p a r a implementar cuando construya aplicaciones Web. El contenedor crea el resto de 10s objetos de periodo de ejecuci6n que son parte de su aplicaci6n. iPor q u i ocurre asi? U n contenedor Web es un marco de aplicacion con un entorno de periodo de aplicaci6n. En el marco, 10s objetos de aplicaciones son creados e invocados por el periodo de ejecuci6n. Mientras invoca 10s mitodos sobre 10s objetos de aplicaci6n, el contenedor tiene que construir 10s objetos para 10s argumentos. Por ejemplo, consideremos el G r e e t i n g s e r v l e t del capitulo anterior. En este servlet, el contenedor crea y pasa 10s o b j e t o s ~ t t p s e r v l e t ~ e q u eys H t t t p S e r v l e t R e s p o n s e como argumentos a1 r n i t o d o d o ~ o s (t ) : protectd v c i d doPost(HttpServ1etRequest request, HttpServletResponse responce) t h r ~ w s ServletExceotion, IOException {
Del mismo modo, el contenedor crea todos 10s demis objetos (corno s e r v l e t c o n f i g , S e r v l e t c o n t e x t , H t t p S e s s i o n , etc.) a 10s que un servlet puede acceder, directao indirectamente. La tabla anterior clasifica las clases/interfaces de 10s paquetes j a v a x . s e r v l e t y j a v a x .s e r v l e t .h t t p , basindose en su funcion en el desarrollo de aplicaciones Web. Por lo tanto, examinemos ahora esta clasificacidn rnis detenidamente: Implementaci6n de servlet Las clases/interfaces de esta categoria estin destinadas a implementar servlets. Por ejemplo, la clase G r e e t i n g s e r v l e t del capitulo anterior amplia la c l a s e ~ t t p s re v l e t. Para desarrollar nuestra propios servlets, implementariamos uno o rnis mitodos de estas clases/interfaces. Cuando desplegamos semlets, el contenedor Web invoca estos mttodos para controlar su ciclo de vida y para ejecutar la 16gica de aplicaci6n. 0
Configuraci6n de servlet La interfaz s e r v l e t c o n f i g pertenece a esta categoria. El API Servlet ofrece varios medios de acceder a1 objeto s e r v l e t c o n f i g asociado a un servlet. Este objeto proporciona acceso a ciertos parametros de inicializacion que pueden ser configurados al desplegar un servlet. Demostraremos c6mo se puede realizar esto mas adelante, en este mismo capitulo.
0 Excepciones servlet El API JavaServlet especifica dos excepciones: S e r v l e t E x c e p t i o n y U n a v a i l a b l e E x c e p c t i o n . Habitualmente, 10s servlets lanzan estas excepciones, que el contenedor captura luego para ejecutar un apropiado manejo de errores.
o Solicitudes y respuestas Hay cuatro interfaces y dos clases abstractas en esta categoria. Estos objetos proporcionan mttodos para acceder a la conexion cliente y las corrientes subyacentes de entrada y salida asociadas a ista. Utilizando estos objetos, podemos leer datos de la entrada y escribir datos de vuelta a1 cliente. Ademis de las anteriores, la especificacih Servlet 2.3 introduce clases envoltorio para las clases ServletRequest,ServletResponse,http.HttpServletRequesty
h t t p .H t t p S e r v l e t R e s p o n s e (corno hemos visto en la tabla en las nombres de clases terminados en "Wrapper"). Aunque todas estas clases son abstractas, no contienen en realidad ninguna funcionalidad. Examinaremos la funcidn de estas clases envoltorio rnis adelante en este capitulo. 0 Localizaci6n de sesi6n La localizaci6n de sesi6n es una de las partes esenciales del desarrollo de aplicaciones Web. Como veremos en el capitulo 7, que es el protocolo fundamental para las aplicaciones Web, no tiene
estado. Como resultado, las aplicaciones Web no pueden reconocer multiples solicitudes del rnismo cliente HTTP originandose del mismo lugar. La noci6n de sesi6n proporciona esta abstracci6n. En tirminos sencillos, una sesi6n le perrnite agrupar solicitudes en un grupo reunido. Ademis, la gesti6n de sesiones tambikn irnplica la asociaci6n de datos con cada sesi6n. Al API Servlet especifica la interfaz j avax . servlet .Httpsession para proporcionar esta abstraction. Aprenderernos mas sobre sesiones en el proximo capitulo. 0
Contexto de servlet La nocion de contexto de servlet esti intimamente asociada a la noci6n de aplicaci6n Web. La interfaz j avax . servlet . servletcontext permite a 10s servlets de una aplicaci6n cornpartir datos. Tambiin ofrece mitodos con 10s que 10s servlets pueden acceder al contenedor Web host. Utilizando el objeto servletcontext,un servlet puede registrar eventos, obtener referencias URL a 10s recursos y fijar y almacenar atributos a 10s que puedan acceder otros servlets del contexto. Trataremos el contexto de servlet en el siguiente capitulo. Colaboraci6n de servlet El API Servlet tambiin proporciona una interfaz (~equest Dispat cher) con la que un servlet puede invocar otro servlet, una JSP o incluso un recurso estitico como una pigina HTML. Este rnecanisrno le ayuda a controlar el flujo de 16gica de mdtiples servlets y piginas JSP programiticarnente; lo estudiaremos con detalle en el capitulo 7.
0
Filtrado El API Servlet tiene un mecanismo con el que podemos introducir c6digo (Ilamado filtro) para participar en el proceso solicitud/respuesta del contenedor. Los filtros son una nueva caracteristica del API Java Servlet versi6n 2.3. Generalmente, no crean solicitudes/respuestas; en su lugar, rnodifican o adaptan solicitudes y respuestas desde y hacia un recurso Web, que puede tener contenido estitico o dinimico. Estudiaremos 10s filtros mis detenidamente en el capitulo 8.
0
Otros API varios En esta categoria, encontrara dos clases: http .Cookie,que puede utilizar para crear cookies y http .HttpUtils,que proporciona mitodos ayudantes varios. Encontrari algunos ejemplos de estas clases en el siguiente capitulo.
En las siguientes secciones, analizarernos detenidamente las cuatro primeras categorias.
Implementation de servlet Comencemos examinando de cerca las clases e interfaces utilizadas para irnplementar servlets. /'
La interfaz servlet public interface Servlet
Esta interfaz especifica el contrato entre el contenedor Web y un servlet. En el paradigma orientado a1 objeto, un objeto puede cornunicar con otro siempre que el primer objeto pueda referenciar a1 segundo objeto con una interfaz conocida (no es necesario que conozca el nombre de la verdadera clase de implernentacion). En el caso del API Servlet, j avax . servlet . servlet es la interfaz que 10s contenedores utilizan para referenciar a servlets.
Programacion de servlets Cuando escriba un servlet, debe implementar esta interfaz directa o indirectamente. Probablemente siempre implemente la interfaz indirectamente ampliando la clase j a v a x s e r v l e t .G e n e r i c s e r v l e t o laclasejavax. s e r v l e t . h t t p . ~ t t p ~ e r v l e t .
.
A1 implementar la interfaz j a v a x . s e r v l e t . s e r v l e t , 10s siguientes cinco metodos deben set implementados: public public public public public
void init(Serv1etConfig config) void service(Serv1etRequest request, ServletResponse response) void destroy 0 ServletConfig getServletConfig() String getServletInfo0
El metodo init() public void init(Serv1etConfig
config) throws ServletException
Una vez sue el servlet ha sido instanciado, el contenedor Web invoca el metodo i n i t ( ) . El obietivo de este metodo es permitir a un servlet realizar cualquier inicializacion requerida antes de ser invocado en solicitudes HTTP. El contenedor pasa un objeto de tip0 s e r v l e t c o n f i g a1 metodo i n i t ( ) y, como veremos mis tarde, un servlet puede acceder a sus datos de configuracion utilizando el objeto ne~ de queno se s e r v l e t c o n f i g . El m e t o d o i n i t ( ) lanzauna e x c e p c i 6 n ~ e ~ v l e t ~ x c e p t i o n ecaso complete de forma normal. La especificacion Servlet garantiza que el metodo i n i t ( ) seri invocado exactamente una vez en una instancia dada del servlet y el metodo i n i t ( ) podri completar (siempre que no lance una S e r v l e t E x c e p t i o n ) antes de que ninguna solicitud sea pasada a1 servlet. Algunas de las tareas tipicas que pueden ser implementadas en el metodo i n i t 0
()
son:
Leer 10s datos de configuracion de recursos persistentes como archivos de configuraci6n
O Leer parimetros de inicializaci6n utilizando el objeto s e r v l e t c o n f i g LI
Inicializar actividades antiguas como registrar un driver de base de datos, una reserva de conexion o un servicio de registro
El metodo service() public void service(Serv1etRequest request, ServletResponse response) throws ServletException , IOException
~ s t es e el punto de entrada para ejecutar la 16gica de aplicacion en un servlet. El contenedor invoca este metodo en respuesta a solicitudes entrantes. S d o despuis de que el servlet haya sido inicializado con kxito, sera invocado el metodo s e r v i c e ( ) . El metodo s e r v i c e ( ) acepta dos argumentos, implementado las interfaces ja v a x . s e r v l e t .S e r v l e t y ja v a x . s e r v l e t .S e r v l e t ~ e s p o n s e r e s p e c t i v a m e n t e . E l objeto solicitud proporciona metodos para acceder a 10s datos originales de solicitud y el objeto respuesta proporciona mktodos con 10s que el servlet puede construir una respuesta.
El metodo destroy() public void destroy
()
Este contenedor invoca este metodo antes de eliminar una instancia de servlet fuera de servicio. Esto puede suceder si necesita liberar memoria o si el servidor Web esti siendo cerrado. Antes de que el
Capitulo 6 contenedor invoque este metodo, dara tiempo a 10s restantes hilos s e r v i c e ( ) para que terminen de ejecutar (sujetos a un period0 de tiempo limite), de mod0 que el metodo d e s t r o y ( ) no sea invocado mientras se produce una llamada s e r v i c e ( ) . Despues de invocar el metodo d e s t r o y ( ) , el contenedor no encamina dirige el servlet. Las actividades que pueden ser implementadas en el metodo d e s t r o y ( ) incluyen: D Realizar tareas de limpieza, como cerrar cualquier recurso abierto, cerrar una reserva de
conexiones, o incluso informar a otra aplicaci6n/sistema que el servlet ya no esta de servicio
O Mantener cualquier estado asociado a un servlet
El metodo getsewletconfig() public ServletConfig getServletConfig()
Este mktodo debe ser implementado para devolver el s e r v l e t c o n f i g que fue pasado a1 servlet durante el metodo i n i t ( ) .
public S t r i n g g e t S e r v l e t I n i o 0
Este metodo debe devolver un objeto s t r i ? g que contenga informaci6n sobre el senlet (por ejemplo, autor, fecha de creacibn, descripci6n, etc.). Esta esta disponible para el contenedor Web, en caso de deseara mostrar, por ejemplo, una lista de servlets instalados junto con sus descripciones.
La clase GenericServlet public abstract class GenericServlet implements Servlet, Servletconfig, Serializable
La clase G e n e r i c S e r v l e t proporciona una implementaci6n bisica de la interfaz s e r v l e t . ~ s t es a una clase abstracta y todas las subclases deben implementar el metodo s e r v i c e ( ) . Esta clase abstracta tiene 10s siguientes metodos ademis delos declarados en j a v a x . s e r v l e t .s e r v l e t y javax.serv1et.ServletConfig: public init ( ) public void log(String message) public void log (String message, Throwable t)
El metodo init ( s e r v l e t c o n f i g c o n f i g ) almacenael o b j e t o s e r v l e t C o n f i g e n u n a v a r i a b l e de instancia privada transitoria (llamada c o n f i g ) . Puede utilizar el metodo g e t s e r v l e t c o n f i g ( ) para acceder a este objeto. Sin embargo, si elige ignorar este metodo, debe incluir una llamada a s u p e r . i n i t ( c o n f i g ) .Alternativamente, puede ignorar el metodo sin argument0 i n i t ( ) de laclase GenericServlet. La c l a s e ~ e n e r i c ~ e r v ltambikn et implementala interfaz S e r v l e t c o n f i g . Esto permite a1 desarrollador de servlet invocar 10s mktodos s e r v l e t c o n f i g directamente sin tener que obtener primer0 un objeto s e r v l e t c o n f i g . Estos metodos son g e t I n i t p a r a m e t e r ( ) , g e t I n i t P a r a m e t e r N a m e s 0 , g e t s e r v l e t c o n t e x t ( ) y g e t S e r v l e t N a m e ( ) .Cadaunodeestos metodos delega las llamadas en 10s mitodos respectivos del objeto s e r v l e r c o n f i g almacenado.
Programacion de servlets La clase G e n e r i c C o n f i g tambiin incluye dos metodos para escribir a un registro de servlet, que invoca 10s mitodos correspondientes en s e r v l e t c o n t e x t . El primer metodo, l o g ( S t r i n g m s g ) , escribe el nombre del servlet y el argument0 msg en el registro del contenedor Web. El otro mitodo, l o g ( S t r i n g m s g , T h r o w a b l e c a u s e ) , incluye una traza de pila para la excepci6n dada T h r o w a b l e ademis del nombre del servlet y el mensaje. La verdadera implementaci6n del mecanismo de registro es especifica del contenedor, aunque la mayoria de 10s contendores utilizan archivos de textos para 10s registros.
La interfaz SingleThreadModel public interface SingleThreadModel
El API Servlet especifica una interfaz de registro especjal llamada javax.servlet.SingleThreadMode1. Durante la vida de un servlet que no implementa esta interfaz, el contenedor puede enviar multiples solicitudes de servicio en diferentes hilos a una unica instancia. Esto significa que la implementacidn del metodo s e r v i c e ( ) debe estar a salvo de hilos. Sin embargo, icual es la alternativa si el mitodo s e r v i c e ( ) no esti a salvo de hilos? El API Java Servlet especifica la interfaz S i n g l e T h r e a d M o d e l con este prop6sito. Los servlets pueden implementar la interfaz S i n g l e T h r e a d M o d e 1 (ademis de implementar la interfaz j a v a x s e r v l e t S e r v l e t o ampliar una de sus clases de implementaci6n) con el objetivo de informar a1 contenedor de que debe asegurarse de que s610 un hilo esti ejecutando el metodo s e r v i c e ( ) del servlet en un momento dado.
.
.
Para servlets S i n g l e T h r e a d M o d e l , 10s contenedores deben seguir uno de 10s siguientes enfoques para asegurar que cada instancia de servlet es invocada en un hilo independiente: 0 Reserva de instancias En este enfoque, el contenedor mantiene una reserva de instancias de servlet. Para cada solicitud entrante, el contenedor destina una instancia de servlet de la reserva y sobre la conclusi6n del servicio, el contenedor devuelve la instancia a la reserva. 0
Serializaci6n de solicitudes En este enfoque, el contenedor mantiene una unica instancia del servlet. Sin embargo, como el contenedor no puede enviar multiples solicitudes a la instancia a la vez, el contenedor serializa las solicitudes. Esto significa que las nuevas solicitudes se mantendrin a la espera mientras que la solicitud actual es servida.
En realidad, una combinacicin de estos dos enfoques es m6s pragmitica, de modo que el contendor podria mantener un numero razonable de instancias en la reserva, mientras que todavia serializaria las solicitudes si el nlimero de solicitudes excediera el numero de instancias en la reserva. Fijese en que el modelo de hilo unico ( S i n g l e T h r e a d M o d e l ) es intensivo en recursos, especialmente si se espera un gran numero de solicitudes concurrentes para el servlet. El efecto del S i n g l e T h r e a d M o d e l es que el contenedor invoca el metodo s e r v i c e ( ) en un bloque sincronizado. Esto es equivalente a utilizar la palabra clave s y n c h r o n i z e d para el mitodo s e r v i c e ( ) del servlet. Consecuentemente, cuando hay cientos o incluso miles de solicitudes concurrentes en el contenedor Web, el contenedor puede serializar las solicitudes a la misma instancia del servlet o crear tantas instancias como solicitudes. En el primer caso, la capacidad del contendor para procesar las solicitudes concurrentes se veri severamente perturbada debido a la serializaci6n. En el ultimo caso, el contenedor se encuentra con mis asignaci6n de objeto (que incluye m6s sobregasto de creaci6n de objetos y gasto de memoria).
Capitulo 6 Sin embargo, en casos en 10s que s61o algunas instrucciones del metodo s e r v i c e ( ) no estin a salvo de hilos, debe considerar reducir el alcance de la sincronizaci6n y sincronizar explicitamente esos bloques utilizando la palabra clave s y n c h r o n i z e d . Cuanto mis cortos sean 10s bloques, mejor puede ser el rendimiento de este enfoque.
Siempre debemos considerar la posibilidad de volver a disehar nuestras aplicaciones para evitar el modelo de hilo h i c o , SingleThreadModel, o la sincronizaci6n de hilos. Si no podemos evitarlas, es importante ser consciente de las implicaciones de rendimiento. Con cualquier c6digo de sincronizaci6n de hilos est6 bloqueando potencialmente un hilo de contenedor Web.
La clase HttpServlet public abstract class HttpServlet extends GenericServlet implements Serializable
La c l a s e H t t p S e r v l e t a m p l j a G e n e r i c S e r v l e t y proporcionauna implementaci6n especifica de H T T P de la interfaz Senlet. Esta seri probablemente la clase que todos 10s senlets ampliarin. Esta clase especifica 10s siguientes metodos: public void service(Serv1etRequest request, ServletResponse response) protected void service(HttpServ1etRequest request, HttpServletResponse response) protected void doGet (HttpServletRequest request, HttpServletResponse response) protected void doPost(HttpServ1etRequest request, HttpServletResponse response) protected void doHead(HttpServ1etRequest request, HttpServletResponse response) protected void doDelete (HttpServletRequest request, HttpServletResponse response) protected void dooptions (HttpServletRequest request, HttpServletResponse response) protected void doput (HttpServletRequest request, HttpServletResponse response) protected void doTrace(HttpServ1etRequest request, HttpServletResponse response) protected long getLastModified(HttpServ1etRequest request)
Los metodos service() El H t t p S e r v l e t tiene dos variantes de este metodo: public void service(Serv1etRequest request, ServletResponse response) throws ServletException, IOException
~ s t es a unaimplementaci6n del metodo s e r v i c e ( ) en G e n e r i c S e r v l e t . Este metodo emite 10s objetos de solicitud y respuesta a H t t p S e r v l e t R e q u e s t y H t t p S e r v l e t R e s p o n s e , e invocael siguiente metodo sobrecargado s e r v i c e ( ) . Por lo tanto, no debe ignorar el mitodo anterior. protected void service(HttpServ1etRequest request, HttpServletResponse response) throws ServletException, IOException
Este metodo sobrecargado toma objetos solicitud y respuesta especificos de HTTP, y es invocado por el primer m i t o d o anterior. H t t p S e r v l e t irnplementa este mitodo para ser un lanzador de solicitudes HTTP. C o m o veri mis adelante en este mismo capitulo, la interfaz j a v a x . s e r v l e t .S e r v l e t R e q u e s t p r o p o r c i o n a u n m ~ t o d o g e t ~ e t h o( d ) quedevuelveel tipode metodo H T T P asociado a la solicitud. Por ejemplo, para solicitudes GET, este metodo devuelve "GET" como una cadena. El metodo s e r v i c e ( ) utiliza esta cadena para delegar la solicitud en uno de 10s m e t o d o s d o x x x ( ) . J a v a x . s e r v l e t h t t p . H t t p S e r v l e t pr~~orcionairnp~ementaciones pordefecto a todos estos metodos.
.
Programacion de servlets En general, debe evitar ignorar este mitodo ya que afecta a1 comportamiento por defecto del metodo s e r v i c e ( ) . La Gnica situacion que requiere ignorar este metodo se produce cuando se quiere cambiar el comportamiento por defecto o cuando se quiere incluir procesamiento adicional comGn a todos 10s metodos ~ O X X X( ) . Incluso en esos casos, debe considerar incluir una llamada a s u p e r . s e r v i c e ( ) en sus servlets. La secuencia de llamadas de metodo cuando el contenedor recibe una solicitud para un servlet es la siguiente:
u El contenedor invoca el metodo s e r v i c e
(
0
El metodo pGblico s e r v i c e ( ) invoca el metodo protegido s e r v i c e ( ) despues de emitir 10s argumentosa H t t p S e r v l e t R e q u e s t y H t t p S e r v l e t R e s p o n s e r e s p e c t i v a m e n t e
0
El metodo protegido s e r v i c e ( ) invoca uno de 10s mktodos ~ O X X X( ) , dependiendo del tip0 del metodo de solicitud H T T P
Los metodos doXXX() La clase ~ t t e rpv l~e t implementa 10s siguientes metodos protegidos, uno para cada metodo de solicitud HTTP: protected void doGet (HttpSe~letRequestrequest, HttpServletResponse response) throws ServletException, IOException protected void doPost(HttpServ1etRequest request, HttpServletResponse response) throws ServletException, IOException protected void doHead(HttpServ1etRequest request, HttpServletResponse response) throws ServletException, IOException protected void doDelete(HttpServ1etRequest request, HttpServletResponse response) throws ServletException, IOException protected void doOptions(HttpServ1etRequest request, HttpServletResponse response) throws ServletException, IOException protected void doput (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException protected void doTrace(HttpServ1etRequest request, HttpServletResponse response) throws ServletException, IOException
La firma de cada uno de 10s mktodos ~ O X X X( ) es la misma que la del metodo protegido s e r v i c e ( ) anterior; cada uno toma argumentos H t t p S e r v l e t R e q u e s t y H t t p S e r v l e t R e s p o n s e , lanza ServletExceptionyIOException. La clase H t t p e~r v l e t proporciona implementaciones adecuadas para 10s mktodos TRACE y OPTIONS, y n o es necesario que sus servlets ignoren d o T r a c e ( ) y d o o p t i o n s ( ) . Para 10s otros cinco mktodos, la clase H t t p s e r v l e t proporciona implementaciones que devuelven errores H H T P . Para el caso de contenedores sometidos a HTTP 1.0, estos mktodos devuelven un error HTTP con c6digo de estado 400, indicando que la solicitud enviada por el cliente es sintacticamente incorrecta. Para 10s contenedores que se ajustan a HTTP 1.1, estos metodos devuelven un error H T T P con codigo de estado 405, indicando que el metodo H T T P solicitado no esta permitido para este servlet. Esta clase utiliza el m ~ t o d o g e t ~ r o t o (c) ode~ la interfaz j a v a x . s e r v l e t S e r v l e t R e q u e s t para determinar el protocolo.
.
Dependiendo de su aplicaci6n, debe determinar 10s mktodos HTI'P que deben ser apoyados por su servlet e ignorar consecuentemente 10s metodos ~ O X X X( ) correspondientes (except0 10s de 10s metodos TRACE y OPTIONS).
El metodo getlastModified() protected long getLastModified(HttpServ1etRequest
req)
Capitulo 6 Este mCtodo implementa una operaci6n condicional get. Por ejemplo, debe devolver el momento en el que el servlet fue modificado por Gltima vez en milisegundos desde el 1 de Enero, 1970 00:00:00 GMT. La implementacih por defect0 devuelve un numero negativo (-1) indicando que el momento de modificaci6n es desconocido. H T T P 1.1 alberga la nocion de solicitudes condicionales GET. La cabecera 1f-Modi f i e d - s i n c e es una de las cabeceras que convierte a una solicitud en condicional. Los clientes que se ajustan a HTTP 1.1 pueden enviar esta cabecera con un campo de fecha (por ejemplo: I f -Modif i e d - s i n c e : S a t , 01 J a n 2 000 00 : 00 : 00 GMT).Esta cabecera indica a1 servidor que si el recurso solicitado no ha sido modificado desde la fecha indicada en la cabecera, el contenedor Web no necesita invocar el mCtodo d o G e t ( ) , puesto que todas las versiones actuales de navegadores de uso comun como Internet Explorer 5.5, Netscape 6.0, y Opera 5.1 se ajustan a H T T P 1.1 y se aprovechan de esta cabecera. Sus servlets pueden ignorar este metodo para controlar la memorizaci6n en cache de piginas generadas por el mCtodo doGet ( ) .
Configuracion de servlets .
En el API Java Servlet, 10s objetos j a v a x . s e r v l e t S e r v l e t c o n f i g representan la configuracidn de un servlet. La informaci6n de configuracibn contiene parimetros de inicializacion (un conjunto de pares nombre/valor), el nombre del servlet y un objeto j a v a x . s e r v l e t .s e r v l e t c o n t e x t , que ofrece la informaci6n del servlet sobre el contenedor. Los parimetros de inicializacidn y el nombre de un servlet pueden ser especificados en el descriptor de despliegue (el archivo Web. xml), por ejemplo:
Este ejemplo registra un servlet de nombre a d m i n y especifica dos parametros de inicializaci6n, e m a i l y helpURL. El contenedor Web lee esta informaci6n, y la pone a disposicion de com.wrox. a d m i n . ~ d m i n ~ e r v l medianteelobjetojavax. et s e r v l e t . servletConfig.Si queremos cambiar estos parimetros, podemos hacerlo sin tener que volver a compilar el servlet. Aprenderemos mis sobre este enfoque en el capitulo 9.
El mecanismo del descriptor de despliegue fue introducido en la especificacio'n Servlet 2.2. Los contenedores W e b (llamados entonces motores de servlet) que se ajustan a versiones antiguas de la especificacion, proporcionan medios especificos del proveedor (como archivos apropiados) para espec;ficar 10s pardmetros de inicializacidn.
La interfaz ServletConfig public
interface ServletConfig
Programacion de servlets Corno hernos ya visto cuando hemos analizado la clase G e n e r i c S e r v l e t , esta interfaz especifica 10s siguientes rnetodos: public public public public
String getInitParameter(String name) Enumeration getInitParameterNames() ServletContext getServletContext() String getServletName ( )
El metodo gethitparameter() public String getInitParameter(String
name)
Este mCtodo devuelve el valor de un parirnetro llarnado inicializacidn o n u 1 1si el pardmetro especificado n o existe. En el ejernplo anterior, a1 invocar el rnCtodo g e t ~ n i t ~ a r a m e t con e r " e m a i l " como argumento, se obtiene el valor " a d m i n . @ a d m i n w r o x com".
.
.
El metodo getlnitParameterNames() public Enumeration getInitParameterNames()
Este mktodo devuelve una enurneraci6n de todos 10s parimetros de inicializaci6n de un sewlet. U t i k a n d o esta enurneraci6n, puede obtener 10s nornbres de todos 10s parimetros de enurneraci6n sucesivarnente. Si n o hay parirnetros de inicializaci6n e ~ ~ e c i f i c a d oeste s , metodo devuelve una enurneraci6n vacia. En el ejernplo anterior, invocar el rnktodo g e t I n i t P a r a m e t e r N a m e s ( ) devuelve una enurneraci6n que contiene dos objetos S t r i n g : " e m a i l " y " h e l p U R L U .
El metodo getsewletcontext() public ServletContext getServletContext0
Este rnktodo devuelve una referencia a1 objeto s e r v l e t c o n t e x t asociado con la aplicaci6n Web. j a v a x . s e r v l e t .S e r v l e t c o n t e x t es analizadoconrnis detalles enel siguientecapitulo.
El metodo getSewletName() public String getServletName()
Este metodo devuelve el nornbre asignado a un sewlet en su descriptor de despliegue. Si n o hay ningdn nombre especificado, kste devuelve en su lugar el nombre de clase de sewlet.
Obtener una referencia a ServletConfig En el API Java Sewlet, un sewlet puede obtener una referencia al objeto j a v a x . s e r v l e t .~ervlet~onfigdelossiguientesrnodos:
Durante la inicializacion del sewlet Corno hemos analizado anteriorrnente, 10s rnktodos i n i t ( ) de la interfaz s e r v l e t y la interfaz G e n e r i c S e r v l e t tienenunargurnentodetipos j a v a x . s e r v l e t . s e r v l e t c o n f i g . D u r a n t e l a inicializaci6n de un sewlet, el contenedor Web crea este argurnento y lo pasa el metodo i n i t ( ) . Cuando sustituye el m e t o d o i n i t ( ) ,puedeaccederalobjeto j a v a x . s e r v l e t .s e r v l e t c o n f i g .
Capitulo 6 Sin embargo, cuando ignora el mCtodo anterior i n i t ( ) en la clase G e n e r i c s e r v l e t , debe invocar e x p l i c i t a m e n t e ~ u ~.eirn i t ( ) como sigue: public
i n i t ( ServletConfig
config)
{
super. i n i t ( c o n f i q ) ; //
Inicializaci6n
ayui
\
La llamada a s u p e r . i n i t ( c o n f i g ) asegura que la c l a s e ~ e n e r i c ~ e r v lrecibe et una referencia a1 o b j e t o s e r v l e t c o n f i g . La irnplementacidn de la c l a s e ~ e n e r i c ~ e r v lmantiene et en realidaduna referencia a1 objeto s e r v l e t c o n f i g (como una variable de instancia transitoria) y requiere que s u p e r . i n i t ( c o n f i g ) sea invocado en subclases.
Utilizar el metodo getsewletconfig() Los servlets tambikn pueden acceder a1 objeto s e r v l e t c o n f i g invocando el mktodo g e t s e r v l e t c o n f i g ( ) . Estemktodoestiespecificadoenlainterfaz j a v a x . s e r v l e t .S e r v l e t . Alternativamente, 10s servlets que arnplian e l ~ e n e r i ecr~v l e t o su s u b c l a s e ~ t t pes r v l e t tambikn pueden invocar 10s mCtodos de la interfaz s e r v l e t c o n f i g directamente. Esto se debe a que G e n e r i c S e r v l e t tambiknirnplementalainterfaz s e r v l e t c o n f i g .
Excepciones servlet El paquete j a v a x .s e r v l e t especifica dos clases de excepciones: javax.servlet.ServletExceptionyjavax.servlet.UnavailableException.
La clase ServletException public
class ServletException
extends
java. lang. Exception
~ s t es a una excepci6n generica que puede ser lanzada por 10s rnktodos i n i t ( ) , s e r v i c e ( ) , ~ O X X X( ) y d e s t r o y ( ) . La clase proporciona 10s siguientes constructores: public public
ServletException ( ) ServletException (String message)
A1 crear objetos de tip0 s e r v l e t E x c e p t i o n , puede integrar cualquier excepci6n de aplicaci6n (Ilamada causa-raiz). Los contenedores utilizan la excepcidn causa-raiz con propdsitos de registro. Por ejemplo, puede integrar una excepci6n j a v a x . s q l .S Q L E x c e p ti o n en una excepcidn j a v a x .s e r v l e t .S e r v l e t E x c e p t i o n . Existen dos constructores adicionales para apoyar estas excepciones causa-raiz: public public
ServletException(Throwab1e cause) ServletException(String message, Throwable cause)
El m k t o d o g e t ~ o o t ~ a u (s )e devuelve la excepci6n causa-raiz: public
Throwable getRootCause()
Programacion de servlets
La clase UnavailableException public
class UnavailableException extends ServletException
javax . servlet .UnavailableExceptiones un tiPo especial deexcepci6nservlet. Puesto queeste servlet amplia j avax.servlet . ServletException,todos 10s metodos de servlet quepueden lanzar una exception j avax .servlet .Exception tambiin puedenlanzarunaexcepci6n javax.servlet.UnavailableException. El objetivo es indicar a1 contenedor Web que el servlet no esti disponible bien de forma temporal o permanentemente. Esta clase especifica 10s siguientes constructores: public UnavailableException(String
message)
~ s t construye e una nueva excepci6n permanentemente indisponible con el mensaje dado: public UnavailableException (String message, int seconds)
Esto construye una nueva excepci6n n o disponible con el mensaje dado. El argument0 seconds indica la duraci6n en segundos durante la cual el servlet no esti disponible. Analizaremos mis tarde el cornportamiento exacto del contenedor en fallos temporales y permanentes.
C o m o hernos visto anteriormente, el contenedor es un period0 de ejecuci6n que gestiona 10s servlets. De entre las diversas responsabilidades de un contenedor, la gestion del ciclo de vida es la mbs .-es caso de 10s servlets, 10s eventos de ciclo de vida estin especificados en la interfaz j avax . servlet .servlet del API Servlet. Aunque la gesti6n del ciclo de vida es una responsabilidad del contenedor, como desarrolladores de servlets, debemos asegurarnos de que nuestros servlets siguen el modelo de ciclo de vida y de que no son implementados en un modo que contradiga esta condici6n. Los metodos de la interfaz Servlet relevantes para el ciclo de vida del servlet son init ( ) , service ( ) y destroy ( ) . El ciclo de vida empieza cuando el contenedor invoca el metodo init() y termina cuando el contenedor invoca el mitodo destroy ( ) . El ciclo de vida de un servlet consiste en las siguientes etapas fundamentales:
Instanciacibn El contenedor Web crea una instancia del servlet
Inicializacibn El contenedor invoca el metodo init ( ) de la instancia
Revisibn Si el contenedor tiene una solicitud para el servlet, invoca el metodo service ( ) de la instancia del servlet
Destruccibn Antes de destruir la instancia, el contendor invoca el metodo destroy() de la instancia del servlet
N o disponible La instancia es destruida y marcada para la recolecci6n de residuos
Capitulo 6 El diagrama de estado UML muestra las posibles transiciones en el ciclo de vida del servlet:
No exlste
-1
1
Instanclac16nbasada en una sollcltud o en el
7 -
+
lnstanc~ado
arranque del contenedor
-
-
--
-
Fallo en ln~c~ac~on
L~berar
referenc~a
De vuelta a revlslon en caso d
I
indisponibilidad temporal
1 Sol~citud(es)HlTP de
1
I
Hilo de final
Fallo temporal o permanente
1
Fin de plazo limite o cierre del contenedor
El contenedor crea una instancia de servlet en respuesta a una solicitud HTTP entrante o en el arranque del contenedor. DespuPs de la instanciaci6n, el contenedor inicializa la instancia invocando su metodo i n i t ( ) . DespuCs de la inicializaci6n, la instancia de servlet esti preparada para servir solicitudes entrantes. El proposito de este proceso de inicializacion es cargar cualquier parimetro de inicializaci6n requerido para el servidor. Veremos c6mo se puede conseguir esto en la siguiente secci6n. Durante el proceso de inicializaci6n, una instancia de servlet puede lanzar una exception Servlet~xceptiono~navailable~xce~tion.~navailable~xceptionesunasubc~asede S e r v l e t E x c e p t i o n . Mientras q u e s e r v l e t E x c e p t i o n p u e d e ser utilizadaparaindicar fallos generales de inicializaci6n (como fallos a1 encontrar 10s parimetros de inicializacibn), U n a v a i l a b l e E x c e p t i o n se utiliza para informar sobre la no-disponibilidad de la instancia para servir solicitudes. Por ejemplo, si su servlet depende de un servidor RMI y esti verificando si el servidor es alcanzable para r e v i d n , su instancia de servlet puede lanzar una U n a v a i l a b l e E x c e p t i o n para indicar que esti temporal o permanentemente indisponible. Si su instancia de servlet determina que la nodisponibilidad debe ser temporal, puede que asi lo indique mientras construye la excepci6n U n a v a i l a b l e E x c e p t i o n , especificando el numero de segundos de indisponibilidad a1 constructor de la excepci6n. Cuando tiene lugar este fallo, el contenedor suspende todas las solicitudes a su servlet durante el periodo especificado y lo devuelve a su estado de disponibilidad a1 final del periodo. Si no especifica internamente una configuracidn de indisponibilidad, el servlet estari indisponible cuando se reinicie el contenedor. Una de las aplicaciones de esta excepci6n tiene lugar cuando uno de sus componentes o sistemas de segundo plano no esti accesible temporalmente. En general, si su 16gica de aplicaci6n es tal que ciertos fallos pueden ser resueltos reintentindolo despu6s de un rato, puede utilizar esta excepci6n. El contenedor garantiza que, antes de que se invoque el metodo s e r v i c e ( ) , el metodo i n i t ( ) podri ser completado y que, antes de que el servlet sea destruido, su metodo d e s t r o y ( ) seri invocado. El servlet puede l a n z a r s e r v l e t ~ x c e ~ t i ~o U n n a v a i l a b l e E x c e p t i o durante n su metodo s e r v i c e ( ) , en cuyo caso el contenedor suspenderi las solicitudes para esa instancia temporal o permanentemente. Es importante que disefie sus servlets considerando fallos temporales y permanentes.
Programacion de servlets En teoria, no hay nada que impida que un contenedor Web ejecute el ciclo de vida complete del servlet cada vez que un servlet es solicitado. En la prictica, 10s contenedores Web cargan e inicializan 10s servlets durante el arranque del contenedor o cuando el servlet es invocado por primera vez y mantienen esa instancia de servlet en la memoria para revisar todas las solicitudes que recibe. El contenedor puede decidir en cualquier momento liberar la referencia de servlet, finalizando asi el ciclo de vida del servlet. Esto podria ocurrir, por ejemplo, si el servlet no ha sido invocado durante un tiempo o si el contenedor se estd cerrando. Cuando esto sucede, el contenedor invoca el metodo destroy ( ) . En el modelo habitual de ciclo de vida de servlet, el contenedor Web crea una unica instancia de cada servlet. Pero, ique ocurre si el metodo service ( ) del servlet esta todavia ejecutandose cuando el contenedor Web recibe otra solicitud? Para 10s servlets que no implementan la interfaz j avax. servlet .SingleThreadModel,el contenedorinvoca lamismainstancia de servlet en cada hilo de solicitud. Por lo tanto, siempre es posible que el metodo service ( ) sea ejecutado en mas de un hilo, siendo necesario que el metodo service ( ) estk a salvo de hilos. Aparte de no acceder a recursos a salvo de hilos (como escribir a archivos), debemos tambien considerar mantener nuestros servlets sin estado (es decir, no definir ningun atributo en sus clases de servlet). A1 definir variables de instancias en nuestros servlets, debemos asegurarnos de que tales variables son manipuladas de modo seguro. Hemos analizado previamente el rendimiento de 10s servlets que implementan la interfaz j avax . s ervlet . SingleThreadModel.Recuerde que, paraestos servlets, el contenedorpuede serializar solicitudes o mantener una reserva de instancias de servlet y destinar cada solicitud a una instancia diferente de la reserva, o utilizar una combinaci6n de estas dos. El siguiente diagrama muestra la secuencia de eventos que representan un servlet durante su carga, revisando dos solicitudes en ripida sucesi6n y siendo despues descargado cuando el servidor se cierra: Contenedor
'
Crear reserva de
lnstanclar servlet
Sollc~tud
HTrP 1
---4 ---
4 Sewlet
lnvocar m e t o d o l n l-t ( ) -. - -
*Destmar sollcltud a hllo
4
Ejecutar
lnvocar metodoservlce
I Sol~c~tud HTrP 2
1
-----,
Destlnar sollcltud a hllo & --
C~erre
'Ejecutar rews~on
Ejecutar revlslon 10s h~losactlvos
/t-
HTrP 1
--
--
-
-
F~nal~zar reselva de h~los -
Y
*.
/
ocar metododestro
b
Respuesta
HTrP 2
*i Servlet destruido y la YI
-
C~erredel contenedor
basura recog~da
Capitulo 6 Existe todavia otra situaci6n en la que un contenedor podria crear mbs de una instancia de un servlet: seria el caso en el que una clase servlet fuera afiadida en el descriptor de despliegue mbs de una vez, posiblemente con diferentes parbmetros de inicializacion. Puede que encuentre 10s anteriores enfoques de instanciaci6n bastante complejos. Para evitar problemas, sus servlets no deben asumir la instanciaci6n. Por ejemplo, no debemos asumir que la misma instancia de servlet se utilice para todas las solicitudes/clientes o que s61o un hilo ejecute un mitodo service ( ) a la vez.
Consideremos ahora un ejemplo, para comprender mejor el ciclo de vida del servlet. El ejemplo consiste , demuestra 10s diversos estados de un tipico servlet, en un h i c o servlet llamado Frea. k ~ e r v l e tque incluido la indisponibilidad. Introduzcalasiguientefuenteen%BOOK-HOME~\ChO6\freakservlet\src\FreakServlet donde BOOK-HOME es el directorio raiz para su c6digo fuente:
.java,
, ' / Importar paquetes d e servlet i m ~ , o r tjavax.servlet.http.HttpServ1et; import javax.servlet.http.HttpServ1etRequest; import javax.servlet.http.HttpServ1etRespor~se; import javax.servlet.ServletExceptior~; i m p o r t javas.servlet.Unavai1ab1eExcepti0r~; /,' Importar otros paquetes Java import j a v a . io. IOException; i m p ~ r t j a v a . io. PrintWri ter; public class FreakServlet extends HttpServlet { java.util.Vector states; j ava. util. Random random; int waitInterva1; public static final int DEFAULT WAIT INTERVAL
=
10;
public F r e a k S e r v l e t o ( states = new java.uti1 .Vector ( ) ; random = new j ava. util. Random( ) ; waitInterva1 = DEFAULT WAIT INTERVAL; states. add (createstate ("Ir1star1tiatior1")) ; I
public void init ( ) throws ServletException ( states.add (createstate(states.addicreateStateo'Ir~itializatior~") ) ; String wait1ntervalString = getServletConfig( ) .getIr,itParameter("waitIr~terva1") ; if (waitIntervalString ! = null) ( waitIrlterva1 = new Integer (waitIntervalStrir~g) . ir~tvalue( ) ;
I protected void doGet(HttpServ1etRequest request, HttpServletResponse throws ServletException, IOException { if
response)
(random.r!extBoolean ( ) ) { / / No disportible durante waitIr~terva1 segundos states.add(createState("Urlavailab1e from d o G e t V )) ; throw new UnavailableExceptior~("Ur~available from doGetM, wait.Irlterva1);
Programacion de servlets
states .add(createState ("Service"))
;
response. setConterjtType ( "text/htmll'); Printwriter out = response.getWriter(); / / enviar acuse a1 r~avegador out.println("" )
;
out .println I" FreakServlet: State History" ) ; o u t .printlr~( " g i n a m
") ; out .println (" | ") ; out.println("WROX Book Store |
You've " + itemCount + " items in your cart.
" ) out .print ("") ; o u t .println ("Add t o Cart | ");") ; out .println (" | "); out.println("Itern 1: " t " Begining Java2 - JDK 1.4 Version |
") ; out.println(" | ") ; out .println ("Itern 2: " t " Professional Java XML | |
") ; out .println (" | " ) out .println ("Item 3: Professional Java " t "Server P r o q r a r n m i n g < / t d > < / t r > " i ; out. println ( " |
" + iterator.next ( )
t
"
Back to the shop
");This is static output.
< % if
(readerName ! = null) [
%>
Si tenernos un valor con el que podernos trabajar: Thank you. You told me your name
/>
Si no tenernos un valor con el que trabajar, anirnarnos a1 usuario a facilitar su nornbre: You're too shy to tell me your name. Try again, using the reader parameter:
remember I trusted you with my fully-qualified class name!!
This is static output again.
HTML
Bijn j o u r < % = n a m e % > . Je rn'appelle < % = c l a s s N a m s % > .i b r / ; , C'est
> +>Plus d e HTML.
H e l l o < % = n a m e % > .You' r e e n t r y < % = i n d e x % >i n my l i s t .
< b > N a t i o n a l i t y : < / b > < % = n a t i o n a l i t y % >< b > C i t y : < / b > < % = c i t y % : < / e x a m p l e s :n a m e I n f o >
Para implementarlo, primero necesitaremos ahadir un metodo aVarHe 1101t e r a t i o n que exponga el contexto necesario, S t r i n g getName 0 . Mientras tanto, crearemos una interfaz N a m e c o n t e x t que contengi este nuevo metodo. De este modo, podemos hacer queVarHelloIterationTag, que ya define un m e t o d o g e t ~ a m e( ) ,implemente la interfaz y proporcione el contexto necesario para nuestras nuevas sub-subetiquetas. La interfaz NameCont e x t es trivial: package public
tagext; irlterf ace
Namecontext
I
Devuelva el nombre expuesto actualmente por este objeto (probablemente una etiqueta adjunta, per0 convirtikndolo en interfaz aseguramos que es una sohci6n general): S t r i n g qetName ( ) ;
I La modificaci6n aplicada a V a r H e l l o 1 t e r a t i o n T a g (mis a h de hacerle imp1ementar~ameconte x t ) es tambien trivial ya que simplemente implementamos un nuevo mktodo: public
I
S t r i n g getName() { r e t u r n names. g e t ( i n d e x ) t o s t r i n g i ) ;
.
Exarninernos ahora el nuevo rnanejador de etiqueta NameInf oTag. Sus principales tareas son obtener el contexto a partir de una etiqueta adjunto y recuperar la inforrnacion adicional. Observe corno aplica el anidarniento correcto. Hay un rnktodo g e t p a r e n t ( ) en la interfaz Tag, pero norrnalrnente es preferible utilizar f i n d A n c e s t o r W i t h C l a s s ( ) . Nosotros n o querernos lirnitar el contexto en el que podernos utilizar nuestra etiqueta, ya que no podernos garantizar que otra etiqueta no se sitfie en la jerarquia entre 10s dos etiquetas cooperantes. Si una o rnis etiquetas estin presentes y tenernos confianza de refundido en una deterrninada clase progenitora o interfaz, la etiqueta anidada n o encontrara el ancestro que requiere para proporcionar su contexto. Para una mayor sirnplicidad hernos refundido 10s datos adicionales de la clase, en una tabla hash. Para nuestro ejernplo, irnaginarernos que estos datos son realmente caros de recuperar. La inforrnacion extra sobre las personas de la lista seri la nacionalidad y la ciudad en la que viven en la actualidad: package tagext;, impcrt import import import
j ava. io. IOException; java .util. * ; javax. servlet. j sp. * ; javax.servlet.jsp.tagext.*;
public class NameInfoTag extends TagSupport
{
Cree el alrnackn de datos: 6rivate HashMap
infoHash
=
new HashMapi
) ;
Pueble el alrnacin de datos. En una aplicacion real, estos datos proc ederian de una verdadera h e n datos, corno una base de datos: public NameIr~foTag( ) { infoHash.put ("Rod", new PersonalInfo ("Australian", "London") ) ; infoHash.put("Isabelle", new PersijnalInfo("French", "Gabon")); infoHash.put ("Bob", new PersonalInfo ("Australian", "Sydney") ) ; 1
public ir4t doStartTag ( ) throws JspTagException { Strlng nationality = "Unknown"; String city = "Unknown";
Cornpruebe si esta etiqueta tiene un ancestro del tip0 requerido, que podarnos utilizar para obtener un nornbre que buscar. Fijese en que utilizar el rnktodo estitico f i n d A n c e s t o r W i t h C l a s s ( ) es rnis flexible que utilizar g e t p a r e n t ( ) . g e t p a r e n t ( ) fallari si uno o rnis etiquetas separan esta etiqueta de la etiqueta deseada en la jerarquia de period0 de ejecucidn de rnanejadores de etiqueta: NameContext nameContextAncestor = (NameContext) TagSupport. findAncestorWithClass ( this, NameContext.class);
La excepcidn lanzada aqui sera rnanejada por la miquina JSP corno cualquier excepcion lanzada en un scriptletlexpresi6n o corno una excepcion lanzada por un bean. (El resultado probable sera una redireccidn a una pigina de error): if
(nameContextAr~cestor == null) { throw new JspTagException("NameTag must only be used within "a NameContext tag");
I
"
t
Extensiones de etiaueta JSP Si llegamos hasta este punto, tenemos u n ancestro vilido del que podemos obtener u n contexto: S t r i n g name = r i a r n e C o r l t e x t A r ~ c e s t o r . g e t N a m e( ) ; P e r s o n a l I n f o p1 = ( P e r s o n a l I n f o ) i n f o H a s h . g e t ( n a m e ); i f ( p i != n u l l ) { n a t i o n a l i t y = p i . g e t N a t i o n a l i t y () ; city = pi.getCity();
I pagecontext . s e t A t t r i b u t e ("r~atior~ality''n , ationality); pagecontext. s e t A t t r i b u t e ("city", c i t y ) ; r e t u r n EVAL BODY INCLUDE; \
Esta clase interna que contiene datos adicionales recuperados para cada nombre es utilizada internamente para posibilitar que dos campos requeridos para cada persona Sean almacenados c o m o un dnico objeto e n una tabla hash: private private private
c l a s s PersonalInfo { S t r i r ~ gr ~ a t i o n a l i t y ; String city;
public Persc?nalInfo(String nationality, this. nationality = nationality; this.city = city;
String
city)
1
I public String getNaticnality return nationality;
( )
{
1 public String getcity() { return city;
I TambiCn necesitaremos una nueva entrada en nuestro archivo TLD, recordando utilizar sub-etiquetas de variable para declarar las variables de directiva que crea la nueva etiqueta:
nameInfo
tagext.NameIr~foTag n a t i o n ailt y < / n a m e - g i v e n >
the
N a m e C ~ r ~ t e x it r l t e r f a c e
java.lar~g.Strir~g
I
HTML.
More HTML
Be s u r e t o c h e c k o u t y o u r u s e r p r o f i l e b y < b r > c l i c h i r ~ g < a href="displayDetails">here. < p i I n t h e m e a r i t i m e , h a v e f u r l w o r k i n g w i t h JSP t a g l i b r a r y
Many t h a n k s , < b r >
E v e r y o n e a t Wrox P r e s s L t d . < b r > < a href="h~tp://www.wro~.c~m">ww~.wrox.com
.:hr> < % Sh:>w t h e d i s c l a i m e r n o t i c e f r o m < i l E n : s t r i n q name="appDisclaimer". © W r ~ xP r e s s L t d , 2001
the
applications.
bur,dle % >
A primera vista, la pigina parece l o suficientemente inofensiva. Pero el Area decisiva ha sido internacionalizada. La plgina importa una biblioteca bisica de etiquetas para la internacionalizaci6n, escrita para demostrar el concepto de este capitulo. Incidentalmente, mientras tratamos el tema de internacionalizaci6n, la abreviatura utilizada comfinmente en el mundo de la tecnologia de la informaci6n es i18 (internacionalizacion: i seguido de 18 caracteres, m i s una n). DespuCs de haber registrado a una personalidad aleatoria, la pigina t h a n k y o u . j s p ha sido mostrada, como aparece en la siguiente pantalla:
Escribir aplicaciones JSP con bibliotecas de etiquetas
2
Dear Bu@, you have been assigned a usemarne of BuffyTheVampire Thanks for registering!
Be sure to check out your user proble b y cliclung here.
In the meantime, have h workug with JSP tag library applications. Many thanks. Everyone at W r o x Press Ltd.
v m w . w r ~ xcorn .
We try our best to ensure your ~rformationis kept secret. Ultimately though, w e can't b e held responsible.
La internacionalizacidn ha sido conseguida en esta JSP utilizando lotes de recursos Java. Como quizis rnuchos lectores de este libro no sepan mucho sobre lotes de recursos, a continuacidn repasaremos 10s conceptos bisicos. DespuCs, perfeccionarernos este ejemplo viendo cdmo funcionan las etiquetas en esta pggina.
Internacionalizaci6n de nuestro codigo JSP La internacionalizaci6n de nuestras aplicaciones se ha convertido en algo rnucho 1116s evidente debido a Internet. Con cualquier persona capaz de acceder a nuestras aplicaciones, desde cualquier lugar del rnundo, la necesidad de ofrecer informacidn al usuario en su propio lenguaje, o adaptado de alguna forrna a sus gustos o preferencias culturales, se convierte en algo muy importante. Sin embargo, una vez mjls Java sale al encuentro de este reto. De repente, con el uso de 10s lotes de recursos, ( java .util .ResourceBundle) en nuestra aplicacidn, el tema de la internacionalizaci6n no parece tan delicado. Con la atenci6n de Java prestada a 10s detalles sensibles a localismos y su aplicacidn en 10s lotes de recursos, la capacidad para adaptar aplicaciones a clientes especificos se consigue sin esfuerzo y casi de forrna gratuita. Repasemos ripidarnente c6mo funcionan 10s lotes de recursos y veamos despuks c6mo pueden ser utilizados de forrna efectiva dentro de una aplicacidn JSP. GQue es un lote de recursor?
Un lote de recursos es simplernente un repositorio para una serie de recursos. De hecho, un lote de recursos puede considerarse un conjunto de pares de valor nombre.
Capitulo 12 A un lote de recursos se le otorga un nornbre denorninado nombre base. Por ejernplo, si todos 10s recursos para una aplicacion estuvieran contenidos solo en un lote (probablernente no en una gran aplicacion), podria l l a r n a r s e ~ y ~ p p ~ e s o u r cSin e s embargo, . nornbres especificos de lugar pueden ser adjuntados a1 nornbre base del lote para crear rnis lotes, especificos de cada lugar. Por ejernplo, podriarnos crear: 0 MyAppResources
Por lo general, 10s nornbres de lugar tienen la forrna, < l a n g u a g e > - < c o u n t r y > , con un lenguaje y region opcional de alli donde se utiliza el lenguaje. Por ello, por e j e r n p 1 0 , ~ y ~ p pources-fr-CH ~es especifica recursos en franc& contenidos enMyAppResources, hablados en Suiza yMyAppResources-fr solo especifica generalmente recursos en franc&, sin tener en cuenta donde se utiliza. Los lotes de recursos son irnplernentados corno clases Java o corno archivos . p r o p e r t i e s , con nornbres corno 10s ejernplos rnostrados arriba. Rernitase a la referencia API Java 2, Standard Edition para encontrar detalles especificos referentes a la clase R e s o u r c e B u n d l e . Como se localizan lor lot-
de recursos
En esta section, estudiarernos c6rno son localizados 10s lotes de recursos y corno son utilizados con una aplicaci6n. Las busquedas de lotes de recursos son realizadas partiendo de:
o El localisrno deseado del cliente O El localisrno actual por defecto tal y corno es devuelto por L o c a l e . g e t D e f a u l t de una aplicaci6n Web, este seria el lugar del servidor.
()
. En el caso
0 El lote raiz de recursos, cuyo nornbre es el nornbre base elegido.
Vearnos un ejernplo. Considerando nuestros recursos, identificados por el nornbre base MyAppResources, si el localisrno deseado por el usuario es deterrninado corno -fr-CH (French Switzerland) y el lugar por defecto en el servidor en -en-GB (English - United Kingdom), entonces el orden de busqueda para recursos dentro de 10s lotes seria el que rnuestra el siguiente diagrarna:
Escribir aplicaciones JSP con bibliotecas de etiquetas
sens~blea1 lugar
MyAppResources
lote de recursos Baselraiz
lote de local~smo porDefecto
lotes de local~srno Deseado
El mas sens~bleal lugar
En otras palabras, el localismo deseado por el usuario es Suiza franc6fona por lo que la bGsqueda es de recursos franceses, preferiblemente tal y como se expresan y utilizan en Suiza. Pero, si 10s recursos especificados en 10s lotes franceses deseados no existen, pruebe entonces 10s lotes del lugar por defecto. D e nuevo, si 10s recursos de 10s lotes de lugar por defecto no se hallaran, retroceda entonces hasta el lote raiz de recursos, cuyo nombre es el nombre base elegido. La busqueda se realiza jerirquicamente.
Aplicar lotes de recursos a aplicaciones JSP Ahora exarninaremos c6mo el concept0 de lotes de recursos puede ser aplicado de forma efectiva en aplicaciones JSP. Inicialmente, veremos algunos etiquetas para abstraer lotes de recursos y despuks volveremos a la pagina "gracias" de la aplicaci6n de registro y veremos c6mo han sido empleados. Hemos creado una biblitoteca de etiquetas de internacionalizaci6n para demostrar lo ficil que pueden llegar a ser las aplicaciones de internacionalizaci6n. Como hemos mencionado anteriormente, en Java es bastante sencillo. Sin embargo, hasta ahora, poco ha emergido en la definicidn de JSPTL en cuanto a la biblitoteca de etiquetas de internacionalizacion. Cuando sea incluida, se basari en principios muy similares a 10s descritos aqui. Las etiquetas de la biblioteca de internacionalizaci6n son 10s que aparecen en la siguiente tabla:
(
Etiqueta
Atributo
Descripci6n Carga unRes o u r c e B u n d l e y loponeadisposici6n dentro del alcance del cuerpo de su etiqueta.
name
El nombre base cualificado completo del lote de recursos a emplear. Por ejemplo, com.wrox.writingjsps.il8n. .MyAppResources. La tabla continka en la prigina siguiente
Capitulo 12
Etiqueta
Atributo
Descripci6n
locale
El localismo a emplear para bhsquedas de recursos en el lote de recursos. Si no es especificado, dependiendo del valor del atributo u s e C l i e n t L o c a l e , se utilizarienlocalismodel cliente solicitante o el localismo por defecto.
useClientLocale
Determinasi emplear o noel localismo delcliente, si es detectado con Cxito, para bhsquedas dentro del lote de recursos cargado. El valor por defecto es t r u e . Devuelve elvalor de unapropiedad especificada en el lote de recursos en contexto.
string name
El nombre de la ropiedad en el lote de recursos cuyo valor debe ser Bevuelto.
alt
Unvalor alternativo para ser utilizado si la pro iedad especificada no pudiera ser encontrada en el Pore de recursos. Espec~ficarun valor para este atributo implementari retroceso, evitando el lanzamiento de excepciones en el caso de que no pudieran hallarse recursos. Proporcionar un cuerpo la etiqueta comovaloralternativo tambienpuedeutilizar elmismo mecanismo de retroceso. Devuelve elvalor de unapropiedad especificada en el lote de recursos en contexto como un mensaje, formateado por la clase j a v a . t e x t . M e s s a g e F o r m a t .Losargumentos arael formato demensajesonespecificadosutilizando fos atributos a r g s o a r g < n > o mediante etiquetas descendientes inrnediatosmessage~rg .
message
name
El nombre de la propiedad del lote de recursos, cuyo valor debe ser devuelto.
alt
U n valor alternativo a ser utilizado si la ropiedad especificada nopudiera hallarse en el lote e recursos. Especificar unvalor araesteatributo implementari un retroceso, evitanlo el lanzamiento de excepciones en el caso en que no se encontraran 10s recursos. Proporcionar un cuerpo a la etiqueta como valor alternativo tambikn puede utilizar el mismo mecanismo de retroceso.
args
U n array que contiene 10s argumentos.
B
Una etiqueta de argument0 de mensaje. Debe ser utilizado como un descendiente inmediato del etiqueta de mensaje. Los argumentos serin sustituidos en el mensaje en el orden de aparicion de las etiquetes bajo la etiqueta progenitor de mensaje. Por lo que el siguiente mensaje
Escribir aplicaciones JSP con bibliotecas de etiquetas Atributo Podria escribirse utilizando la etiqueta :
El valor del argumento.
value
Veamos ahora cdmo ha sido introducida la internacionalizaci6n en el ejemplo de registro y en la pigina thankyou. j sp.Puesto que una aplicacion de registro se asienta abiertamente en cualquier sitio Web, es realmente bastante conveniente que una aplicacion de este tip0 sea internacionalizada, con el objetivo de Hegar a la mayor proporcion de pbblico. Despues del registro de 10s usuarios, estos son reenviados a la pigina de agradecimiento, como hemos visto anteriormente. La pdgina simplemente toma parte de la informacion del usuario de un bean User,la utiliza para dar las gracias al usuario por registrarse y le proporciona una par de vinculos para reenviarle a otras ireas de interis. El codigo para la pigina JSP ya ha sido mostrado. La pigina utiliza la etiqueta ResourceBundle para cargar el lote de recursos nominado, writingjsp. registration. ~egistration~esources,ene~a~cance.Lo~ueestosignificaesque cualquiera de las etiquetas de internacionalizaci6n puede ser entonces utilizado dentro del alcance de Esta etiqueta y de su(s) lote(s) cargado(s). Podemos ver que hay una etiqueta de mensaje que carga un recurso, greetingMessage y proporciona el nombre del usuario y el nombre de usuario elegido como parimetros para el mensaje. Mis abajo, podemos ver cdmo la etiqueta string ha sido utilizado para cargar y mostrar una nota de salvedad que podria, perfectamente, ser especifica de la region en la que se ubica el usuario. Esta en manos del diseiiador de la aplicacion especificar el numero de regiones internacionales que serdn cubiertas y proporcionar lotes para aquellos localismos bajo el nombre base especificado. Para nuestros propositos, crearemos 10s siguientes lotes de recursos: 1. writing. jsps. registration.RegistrationResources . p r o p e r t i e s , q u e c o n t i e n e l a siguiente informacion: g r e e t i r , g M e s s a g e = H i { 0 } , y o u 1 ( r e userrlame i s { 1 ) ! a p p D i s c l a i m e r = N c > s e s f o r z a m o s a 1 mdximo p a r a q u e su i r l f o r r n a c i b r ~ < b r > s e m a t e n g a e n s e c r e t o . P e r o , e n l i l t i m a i n s t a n c i a , r ~ in ~o s hacerrios responsables.
2.writingj sps . registration.RegistrationResources~en.properties;estearchivo no tiene nada que ariadir a1 lote base. 3.writingjsps.registration.RegistrationResources~en~GB.properties,que
contiene la siguiente informacion:
4.
greetingMessage=Dear
101,
you h a v e
beer,
assigned
a
usernarrie
of
{l)
writingjsps.registration.RegistrationResources~en~US.properties,que
contiene la siguiente informacion:
Capitulo 12
5.writingjsps.registration.RegistrationResources~fr~properties,quecontiene~a
siguiente informacibn: Cotnenzando desde la parte superior, el listado rnuestra el lore (base) por defecto ( I ) , seguido por 10s lotes de recursos en inglis (2), inglislReino Unido (3), inglCslEstados Unidos (4) y francCs (5). El contenido de cada tote esri especificado despuCs de cada uno de ellos. Sblo queda demostrar el efecto.de diferentes localismos en el cliente solicitante y servidor. El localismo del Sistema Operative y, por lo tanto, del servidor, puede ser canibiado en Windows 98/NT/2000 a travis del icono Panel de Control I Configuraclon Regional. Si estl utilizando Microsoft Internet Explorer (IE) 5.x, puede alterar 10s idiomas aceptados por el cliente via Herramientas I Opcionesde Internet 1 Idiomas...Para u s u ~ r i o sde Netscape, vaya a Preferencias, seleccione la seccibn Navegador, haga clic en la opcion ldiomas y seleccione el idioma que desee. La siguiente captura de pnntalla rnuestra 10s resultados derivados de ejecutar nuestro servidor Tomcat en el localismo English/GB y configurar despuCs I E con Francks como idiorna preferido:
Edicmn
Ver
Favorites
Henarnier
2
Bonjour Robert! Thanks for registem! Be sure to check out your user profile by clickng &.
In the meantime, have hn wor!ung wth JSP tag library applications Many thanks, Everyone at Wrox Press Ltd.
We try our best to ensure your dormation is kept secret. IJItimately though, we can't be held responsible
El lote de recursos en francis ha sido elegido y cargado automiticamente porque el navegador ha reflejado 10s deseos del usuario (en realidad, a travis la cabecera HTTP accept-languages) para el contenido en francCs. Puesto que el lote franc& habia ignorado la propiedad greetingMessage, Cste ha sido elegido y utilizado desde ese lote. Sin embargo, el tote francis no ha proporcionado una propiedad de salvedad especifica ni tampoco 10s lotes por defecto de ingles local o inglks/Gran Bretafia del servidor. Esto significa que esta propiedad debe residir en el lote base; de no ser asi, puede suceder un error. La propiedad estaba presente en ese lote y ha sido cargada desde ahi.
Escribir aplicaciones JSP con bibliotecas de etiquetas Como eiemplo a inglCslEstados . - final, si cambiamos ahora nuestro localismo preferido del navegador Unidos, la siguiente captura de pantalla ilustra el resultado:
II
II
IIII
-
Hey Herschel, you're now known as KmstyTheClown! Thanks for regstenng! Be sure to check out your user profile by clickmg b. In the meantme, have hn w o r h with JSP tag hbrary applications.
Everyone at Wrox Press Ltd ~ ~ : a corn r ~ x
Subject to US export and Data Protection policies.
Estos resultados reflejan claramente el hecho de que el lote de localismo ingl6slEstados Unidos invalida 10s mensajes greet ingMes s age y appDis claimer, especificamente para clientes regionales de Estados Unidos.
La pagina de error de registro Si, durante el proceso de registro, se elige un nombre de usuario que coincide con el nombre de usuario de un usuario existente, el servlet controlador de registro reenvia al usuario a la pigina de error de registro. El c6digo para la plgina tryAnotherUsername .j sp es realmente muy sencillo y es el queaparece a continuaci6n:
Registration Errors
Sorry, t h a t u s e r n a m e w a s a l r e a d y and c h o o s e
another
username.
c/html>
Los resultados de intentar registrarse como miembro ya existente son 10s que mostramos en la siguiente captura de pantalla:
I
Arch~vo Edicih
Ver
-
Herramientas
Favorltor
Ayuda
-
. ,m
I& http //localhost 8110WlapTag4pps/reg1stratm~/regForrnSubrn~t L]
~ireccitm
-
-
-
-
-
--
&r
I
Sorry. tkat username was already taken Please go back in your browser and c110osp :mther U C ~ ~ X L I ~
En este punto, podria elegirse o t r o nombre de usuario volviendo al formulario d e registro. ~ s t ha a sido la secci6n dedicada a las plginas de registro. Volvamos ahora al registro en el sitio.
La pagina de formulario de entrada Cuando 10s usuarios se registran en un sitio Web, se espera de ellos norrnalmente que elijan un nombre de usuario y una contraseria. Esta inforniaci6n es utilizada siempre que vuelven al sitio Web.
Ya hemos visto el formulario que recoge esta y otra informaci6n en nuestra aplicaci6n de registro. Los usuarios registrados entran en el sistema utilizando la opci6n dos de la plgina d e bienvenida, o directamente via http://localhost:8000/jspTagApps/registration/login. El servlet controlador asocia la solicitud d e entrada a la JSP formulario d e entrada, 1 o g i n F o r m . j s p , que aparece a continuaci6n:
Igual que el formulario de registro, esta JSP formulario de entrada importa y utiliza la biblitoteca d e etiquetas ayudantes HTML para crear el formulario d e entrada y 10s campos d e entrada. En este ejemplo, el n6mero d e caracteres visibles para cada campo ha sido establecido en 20, la siguiente captura d e pantalla muestra el formulario d e entrada servido:
Escribir aplicaciones JSP con bibliotecas de etiquetas
Arch~vo Ed1c16n Ver I
[hmchIfl
FavwRos
Herramlentas
Ayuda
hltp l/localho:t 20001r~pTag4pp.;lr~ilrIrahonllogn
"m 81r
El formulario de e n t r a d a , l o g i n ~ o r m j. s p , utiliza las etiquetasf o r b t e x t I n p u t , p a s s w o r d I n p u t de la biblitoteca de etiquetas H T M L . Hernos analizado estas etiquetaes en la liltima secci6n. C u a n d o se presenta el formulario, el servlet controlador de registro procesa 10s elementos del formulario y s e asegura de que Ins credenciales del usuario son vilidas y de que existe un usuario con el nombre d e usuario y la contraseiia especificada en la basc de datos de registro. Si las credenciales del usuario son verificadas, el servlet controlador sirve un cookie d e usuario. El cookie persiste entre solicitudes a la aplicaci6n de registro y autentifica al usuario de la aplicaci6n en cada solicitud posterior. Despues de que el cookie sea servido, el controlador envia al usuario a la pigina que rnuestra el perfil d e usuario. Si 10s detalles introducidos n o corresponden a 10s d e un usuario registrado, el servlet controlador reenvia al usuario una pigina d e error d e entrada. Las piginas de perfil de usuario y dc error d e entrada son analizadas en las siguientes secciones.
Ver su perfil de usuario Las aplicaciones de registro de sitios Web perrniten a 10s usuarios registrados v e r y potencialmente, editar sus detalles dc registro. Aunque dentro el alcance d e este libro, la aplicaci6n de registro d e este capitulo n o perrnite carnbios e n la i n f o r r n a c i h de registro, si ofrece la posibilidad de ver 10s detalles d e registro existentes. Los usuarios que s e han registrado, corno hernos visto e n la Gltima seccibn, pueden ver su perfil de usuario a traves d e la opci6n tres de la pigina inicial o directarnente via http://localhost:800O/jspTagAppsl registration/displayDetails. El servlet controlador asocia la solicitud para el perfil de usuario a d i s p 1 a y D e t a i l . s . j s p . Esta JSP rnuestra la informacibn de usuario autentificada. El c6digo para la JSP es el siguiente:
Capitulo 12
User Profile
Age This Year: | |||
Actual Age: | < / t r> | Pensioner This Year: | Region of Origin: |
Company Name: | Your Role: | < / td> | |
Main Hobby: | Favourite Web Site: | 'bdy> ct>lor="#996600"?User P r o f i l e < / f o r ~ t > < t a b l e border="On> ctr> 'td>User Narne: | ctd>|
ia h r e f = " o r d e r c h r ~ s e n ? s a l e s d i v i s i o n = c%=view.qetSalesDivi~ion[)~>&orderr~umbec="> | < % = v i e w g . e t p r ~ d u c t( 1 % > < / t d > | i4=vie~.getGateDue [ ) % > < / t d > Capitulo 18 La prinlera vez que el usuario intenta elegir un pedido para su fabricncion, se le pedirii que introduzca un nilmero de ID de cClula para identificar el Area e n la que el producto estii siendo fabricado (es decir, que s e registre): Enter your current manufachirug cell identlGcation shmg: ICELLZ .... .... . ..... .... ..,., I rr/@~ocal intranst ist to A LJ siguiente pigina JSI'es utilizada para identificar al usuario. Los tipos de usuario e n el nombre de su cClula y la Eecha d e prebentacibn de formulario son llevados a 105 principales servlets: ,-i~trnl> .:head:, < t i t l e > P I r n x S a m p l e Code E r l t ~ r Ycur C e l l I D < / t i t l e ' . - e , q u i v = " C o n t . e r ~ t - T y p e "c o n t e n t . = " t e x t / h t m l ; charr.et-iso-RH.50-1": - c t ~ o d y h g c ~ ~ l o r i= l FFFFFF1'> " < p > L c ~ q i r < f e r n 1 m e t t , o d = " p u c t 1 ' a c t i ~ r ~ = " c e cl hl , 3 s e n u > W r o x S a m p l e C o d e - Routing Step < p > H e r e is t h e n e x t s t e p i n t h e manufacture o f this product: < p > < a href="manufactureroute">C1ick h e r e w h e n completed. < / p >
Finalrnente, despuis de que se hayan rnostrado todos 10s pasos de redireccionarniento, se introduce la inforrnaci6n de envio: Capitulo 18 1 Archlvo ] C AtrBs li- II EdkltKl Ver Favoritos - +-@a , ( HerrMnientas @Bisque& Ayuda - Favoritos C@~ultimedia - aI 1 @1 r S h p the manufactured product: La vista es proporcionada por s h i p . j s p : Wrox Sample Code - Ship the Product Ship the manufactured product:
Proporcionamos un archivo HTML que puede ser utilizado como archivo de bienvenida para esta ap~icaci6r1,~larnadoindex. html: Wrox Sample Code - Manufacturing Application Roles de desarrollo y de implementaci6n ,'./hea.j? F a c t o r y Demo f o r J S F s a n d E J B s < / h l > < p - . T h i s PJeb s i t e p r o v i d e s a s i m p l e i r ~ t e r f a c e to t h e m a n l d f a c t u r i n g e x a m p l e t h a t w e d e v e l c p e d f o r t.hc c h a p t e r s on E n t e r p r i s e J a v a B e a n s i n t h e It:r,:,x S e r v e r S i d e J a v a book.-:/p> h r r f - " c o r ~ t . r o l / c h o i c e s " > S e e t h e d e n i n . . . La estructura de directorio del archivo Web ( j s p s .war) es la siguiente: cellid.jsp choices.j sp createproduct. jsp createrouting. jsp index. html main. j s p manageorders. jsp manufacturechoose. jsp manufactureroute. jsp message. j s p Roles de desarrollo y de implernentacion placeorder. j sp ship.jsp WEB-INF/ Web. xml w e b l o g i c . xrr~l classes/ fact;,^ y/ Mixi?ltlar~agerc . lass O r d e r V i e.d. c l a s s Request P r o c e s s o r . c l a s s ScreenNarnes.class Este archivo Web es ariadido a un EAR en el mismo nivel que el archivo EJB. Debemos ariadir referencias a ambos en el archivo estindar J2EE a p p l i c a t i o n . xml. Suponiendo que el JAR de EJB (o directorio, si su servidor de aplicaci6n es compatible con este formato) es denominado e j b s . j a r y el archivo Web (0 directorio) es denominado j s p s . w a r (observe que estos nombres son arbitrarios), el archivo a p p l i c a t i o n . xmlseriasi: < ! DOCTYPE a p p l i c a t i o n PUBLIC ' - / / S u r ~ micro system.^, I n c . //DTD J2EE A p p l i c a t i o n 1.2//EN1 ' h t t p : / / j a v a . s u n . com/j 2 e e / d t d s / a p p l i s a t i m 1 2 . d t d 1 > < W e b - u r i \ j s p s :xar Entoncea, ejecute ~ r o x ~ u e u e ~ e c e ~incluyendo ver, el mlsnlo archivo de propiedades anterior: Aunque hemos detenido el servidor JZEE, el mensaje todavia estaba disponible (incluso hubiera estado ahi si se hubiera arrancado su ordenador de nuevo). Esto demuestra que la cola de destino JZEE es persistente. Esto no es siempre asi; el productor de nuestro ejemplo ha utilizado 10s parinietros por defect0 al enviar el mensaje. Para ser portitil, estos padmetros en realidad necesitan ser definidos esplicitamente en la versi6n mis eshaustiva del metodo s e n d ( ) . Si sustituimos: E n w r o x Q u e u e S e n d e r por: q u e u e S e n d e r . s e n d (messaqe, DeliveryMode.PERSISTENT, Message. D E F A U L T P R I O R I T Y , 6 0 L 1 0 0 0 L ); .. Se enviara el mismo nlensaje pero s d o durari un minuto. Consumir un mensaje asincronicamente Hasta ahora hemos enviado (o producido) un mensaje y despuks lo hemos recibido (o consumido). Hemos tratado 10s rnodos en 10s que podemos utilizar el metodo r e c e i v e ( ) per0 necesitariamos sondear (en bucle) continuamente, para consumir mensajes a medida que vayan Ilegando. En un entorno como JFC, 10s eventos asincronos como movimientos de r a t h o clic de teclado son manejados por oyentes. Lo mismo sucede si queremos recibir mensajes asincr6nicamente; es necesario que utilicemos un M e s s a g e L i s t e n e r . Utilizar u n M e s s a g e L i s t e n e r significa que laaplicaci6n puedecontinuar con otras tareas mientras dejamos al oyente que procese 10s mensajes entrantes. Creemos una nueva clase W r o x Q u e u e R e c e i v e r A que pueda consumir mensajes asincronicamente. Gran parte del c6digo seri igual paraWroxQueueReceiver: impcrt import j ava.util.Date; j a v a x . j m s . '; Capitulo 19 import j avax. naming.-; p u b l i c c l a s s WroxQueueRecei~/erA { public s t a t i c void main(Strir~g[largs) { Queue qlleue = n u l l ; Q u e u e C o r ~ r i e c t i o n F a c t o r y q u e u t C o n r ~ e c t i o n F a c t o r ~=. n u l l ; QueueConnection queueConnection = n u l l ; try i C o n t e x t j n d i C o n t e z t = n e w I n i t i a l C , > r ~ t e x( t) ; q u ? ~ ~ e C o r ~ r ~ e c t i o r ~ F a c=t ,(QueueConnectionFactory) ?ry j n d i C o r ~ t e x .t l o o k u p ( " Q u e u e C o n n e c t i a r ~ F a c t o r y " ); q u e u e = ( Q u e u e ) j n d i C a r i t e x t . l o o k u p ( " W r o x O r d e r s W) ; } c a t c h (NamingException nEx) { S y s t e m . o u t . p r i n t l n ( r ~ E xt .t j S t r i r ~ g (t )l ' \ r ~ D o e s t h e q u e u e e x i s t ? " ) ; S y s t e m . e x i t (1); I I try q u e u e C o r , r , e c t i o r , = q u e u e C o n n e c t i a r ~ F a c t o r yc. r e a t e Q u e u e C o r i r ~ e c t ri ~ ( ) ; Q u e u e S e s s i o n q u e u e S e s s i , - n = q u e u e C o n r ~ e c t i c ? r c~r. e a t e Q u e u e S e s s i o n i false, QueueReceiver q11eueReceiver = Session.AUT0-ACKNOWLEDGE); queueSession.createReceiver(que); Hasta el rnornento todo es igual, per0 ahora necesitarnos configurar e l M e s s a g e L i s t e n e r antes de iniciar la Q u e u e c o n n e c t i o n . El rnotivo es que tan pronto corno se inicie la Q u e u e c o n n e c t i o n , se invocari e l ~ essa g e L i s t e n e r en cualquier rnornento: WroxListener wroxListener new W r o x L i s t e n e r = ( ) ; queueReceiver.setMessageLister~e~-(wroxListener); q u e u e C < : > n n e c t i o n .s t a r t ( ) ; Ahora podernos continuar y hacer lo que tengarnos que hacer en la aplicaci6n sin preocuparnos por 10s rnensajes. Por ejernplo, podriarnos cornenzar rnostrando algunas estadisticas de rnensaje, procesando 10s rnensajes per0 asurniendo q u e M e s s a g e L i s t e n e r 10s esti escribiendo en una base de datos o clasificando 10s rnensajes y volviendo a enviarlos a otras colas o apartados. E l ~ e s s a ~ e ~ i s t epodria n e r ser cierta forrna de "alrnackn seguro", un tkrrnino utilizado a rnenudo en sisternas M O M que requieren que 10s rnensajes sean alrnacenados en disco. Los alrnacenes seguros se utilizan con mayor frecuencia en aplicaciones financieras puesto que, una vez en el disco, 10s rnensajes estin a salvo de fallos MOM. O t r o uso frecuente consiste en insertar en rnensaje en una base de datos para una posterior recuperaci6n. N o varnos a realizar ninguna operaci6n tan cornplicada corno Csta, sino que sirnplernente varnos a esperar alrededor de un rninuto para ver si hay algun rnensaje rnis: System.out . p r i n t l n ("Waiting 1 minute f o r messages.. .") ; f o r i i n t 1 = 6 0 ; i > 0 ; i-) [ S y s t e m . ~ u .t p r i n t ( " C o u n t d o w n . . . " t l t " \ r " ) ; Thread.sleep(1000L); 1 I catch (JMSException jmsEx) { System.out.println("JMSException: " + j m s E x . t o S t r i n g catch(1nterruptedException i n t E x ) { ] System.out . p r i n t l n ( " I n t e r r u p t i o n : finally { i f (queueConnection != n u l l ) { try { ,queueConnection.c l o s e ( ) ; ] catch (Exception any) [ ] 1 I " t ..- ( ) ); intEx. tostring ( ) ) ; JMS y beans controlados por mensaje Es necesario que capturemos cualquier instancia de excepci6n I n t e r r u p t e d E x c e p t i o n que podria generarse debido a1 uso d e ~ h r e a d s. l e e p ( ) . Analicemos ahora n u e s t r a c l a s e ~ e s s a g e ~ i s t e n e~r .s t a es la principal parte de control de mensajes de la aplicaci6n. En este ejemplo, n u e s t r a M e s s a g e L i s t e n e r se Ilamawr o x ~ itse n e r . Implements la i n t e r f a z ~ e s a g e L i s t e n e r , que requiere que proporcionemos una implementaci6n para el metodo o w e s s a g e ( ) : import j ava . u t i l .Date; import j avax. j ms. * ; public class WroxListener implements MessageListener { public void onMessage(Message message) { try I if (message instanceof TextMessage ) { TextMessage textMessage = (TextMessage) message; Date timestamp = new Date(textMessage.getJMSTimestamp()) ; String client = textMessage.getStrir~gProperty("Clier~t"); Systern.out .prir~tln("\r1New 3rder from "tclientt" at "+timestamp); System. out .println "+textMessage.getText ( ) ) ; ('I-> Podemos t a m b i h procesar otros tipos de mensaje si 10s tenemos: ] else if (message instanceof ObjectMessage) { Obj ectMessage obj ectMessage = ( O b jectMessage) message; I J } catch (JMSException j m s E x ) { System.out .println ("JMSExceptior1 in onMessage ( ) : " t jmsEx.toString()) ; catch(Excepticn e ) { System.out .println ("Exception: " + e. tostring ( ) ) ; 1 I Es asi de sencillo. Este metodo es invocado ahora cada vez que llega un mensaje a1 destino Q u e u e . Ejecute el siguiente comando para c o r n p i ~ a r ~ r o x Q u e u e ~ e c rA e i vy eW r o x L i s t e n e r : j a v a c -classpath . ; % J 2 E E p H 0 M E % \ l i b \ j 2 e e . j a r WroxQueueRe WroxListerler. j ava Recuerde iniciar el senidor J2EE y ejecute entonces el siguiente comando para ejecutar el ejemplo (recordando pasar el archivo de propiedades en la linea de comando Java): j ava -Djrns .properties=% J2EE HOME%\config\ jrns client .properties - c p . ;% J2EE HOME%\lib\j 2eeTj ar; W r o x Q u e u e ~ e c e i v e r A - Mientras se ejecuta, debe ejecutar varias veces W r o x Q u e u e S e n d e r para enviar algunos mensajes nuevos. Debe ver algo asi: Capitulo 19 Puede ver en esta captura d e pantalla q u e W r o x Q u e u e R e c e i v e r A ha recibido tres mensajes. Es conveniente destacar la interfaz E x p c e t i o n L i s t e n e r . Puede utilizarse para construir controladores de escepciones. Puesto que, esencialmente, hemos desacoplxlo el receptor en el ejemplo anterior, n o tenemos forma alguna de procesar exccpciones; podemos conseguirlo implementando E x c e p t i o n L i s t e n e r y proporcionando una iniplementacion para el m6todo o n E x c e p t i o n ( J M S E x c e p t i o n ) . U n sencillo ejemplo seria i n v o c a r p r i n t s t a c k ~ r a c (e) en el parimetro de excepci61-1. Ejemplo de apartado publicar/suscribir Un prograrna que utilizn apartados y publicar/suscribir es tan sencillo d e implementar c o m o un programa que utiliza colas y punto-a-punto. Sin embargo, hay m i s funciones disponibles en este dominio. Para crenr un programa que utiliza apartados y publicar/suscribir, podemos tomar literalmente el c6digo a n t e r i o r ~ r o x ~ u e u e ~ e nydseurs t i t u i r " q u e u e n p o r " t o p i c " , " s e n d e r " por " p u b l i s h e r " y " s e n d " por " p u b l i s h " , renombrar el archivo y compilarlo. Sin embargo, para hacerlo un poco mas interesante, afiadiremos tres mensajes en lugar de afiadir solo uno. Nuestra aplicaci6n anunciard sus nuevos libros a 10s suscriptores; por ejernplo, a compradores al p o r mayor o individuales que hayan manifestado interis por determinados tipos de libros. Supondremos que 10s siguientes libros acaban de publicarse: 2 Programaci6n Profesional J2EE Java Server 7 Referencia para Programadores Java XML ASr'.NET I'rofesional Cadn libro tendri propiedades como alcmce del terna, lenguajes, autores, nlimero ISBN y precio pero solo algunas de estas propiedades han sido implementadas en nuestro c6digo de ejemplo. El codigo para esta c ~ a s e , ~ r o x ~ o p ~ c ~ u b les i smuy h e rsimilaral , de~rox~ueue~ender: JMS v beans controlados por mensaie Topic topic = null; TopicConnectionFactory topicConnectlonFactory TopicConnection topicCor~nection = null; = null; try 1 Corltext jr~dicorltext = new InitialContext ( ) ; topicCor~nectionFactory = ( T o p i c C o n n e c t i o n F a c t o r y ) j ridicontext.lookup ( " T o p i c C o r ~ n e c t i o n F a c t o r y ") ; topic = (Topic) j ndicontext. lookup ("WroxPub1icatior~s") ; ) catch (NamingException nEx) { System.out .println (riEx.tostring ( ) +''\riDoes the topic exist?") ; System.exit(1); I try 1 topicConnection = topicConnectior~Factory.createTopicCor~nection(); TopicSession topicSession = topicConnectiori.createTopicSession( false, Session .AUTO ACKNOWLEDGE) ; Topicpublisher topicPublisher = topicSession.createPublisher(topic); TextMessage messagel TextMessage message2 TextMessage message3 = = = topicSession.createTextMessage~); topicSession.createTextMessage(); topicSession.createTextMessage~); rrlessagel.setText ("The new Pro JZEE book 1 s now our") : messagel. setstringproperty ("MetaData","Java,J2EE,EJB, JMS") ; messagel. setstringproperty ("Languages","Eriglish") ; message2.setText ("The new Java XML book is now out"); message2 .setstringproperty ("MetaData","Java,XML"); message2. setstringproperty ("Languages","English") ; message3.setText ("The new Pro ASP.NET book is out"); message3. setstringproperty ( " M e t a D a t a " , " M i c r o s o t ,. N E T , A S P W ); message3.setStringProperty ("Languages","English, Deutsche,Alsacien") ; Los cuatro parirnetros del siguiente metodo p u b l i s h ( ) son el rnensaje, el mod0 de entrega (PERSISTENT o NON-PERS ISTENT), la prioridad y, finalrnente, la duraci6n de la vida del rnensaje (en milisegundos): topicPublisher.publish(messagel, DeliveryMode.PERSISTENT, Message.DEFAULT PRIORITY, 7*24*3600*1000L); topicPublisher.publish(message2, DeliveryMode.PERSISTENT, Message. DEFAULT PRIORITY, 7*24*3600t1000L); topicPublisher.publish(message3, DeliveryMode.PERSISTENT, Message.DEFAULT PRIORITY, 365*24*3600*1000L); System.out.println("3 books have been published today."); catch (JMSException jmsEx) { System.out.println("Sorry, something went wrong with publishing..."); System.out .println ("Exceptiori: " + jmsEx. tostring ( ) ) ; ] finally I if (topicConnection ! = null) { try i topicCor~nectlon.close ( ) ; ) catch (JMSException any) { ) 1 } I I Capitulo 19 Necesitanios crear el apartado en J2EE, utilizando el siguiente comando: j: ? ; a J m i n - a 8 : i . i i r ~ i , = n e e t i n a t i o nL . l r c : i E ' ~ ~ hI lc a t i i.ri.= r;:,(.,ii Compile a h o r a ~ r o x ~ o ~ i c ~ u b l iejecutando sher el siguiente comando: iava,: -c'ld."5p3t.tl .; V . J ? E E - H O M E % \ L i h \ i i i i . j d r P ! ~ r ~ ~ T ~ ? ~ i c P u h l i sa vt V ~ 3e ~ - . Finalmente, inicie el servidor J2EE y ejecute el siguiente comando para e j e c u t a r ~ r o x ~ o ~ i c ~ u b 1 i s h e r : j3 - - E ~ j r n , ? . p r , ~ p e r t i e s = ~ ? ; E E , - H O l . ~ 1 E ' \ : : r t f i 3 \ j r n s - = l i e n t . p r c , p i i - f ii.? -ct . ; P J T E E IIOMEP\lib\j?;~?.i.ir; I ~ ! ~ , . ~ : , T ~ ? ~ ~ i r E ~ ~ i : ~ l i : ~ h e r Debe poder ver algo ask Una vez mas, 10s tres mensajes que hemos creado y enviado al apartado W r o x P u b l i c a t i o n s han desparecido porque n o hay nada que 10s suscriba al apartado (hasta, por supuesto, que creemos y e~ecuten~os~rox~opic~ubscriber). Aunque hemos e s p e c i f i c a d o ~ e l i v e r y ~ o d. PERSISTENT: e el mecanismo publicar/suscribir s610 mantendri o retendri mensajes que tengan suscriptores, por lo que incluso 10s mensajes que no expiren desaparecerin si son enviados a un apartado sin suscriptores. El c6digo para implementar nuestro suscriptor de apartado es similar a1 de ~ r o x ~ u e u e ~ e c e i Una v e r ~ vez mas, anadiremos algunas funciones mis, esta vez con el objetivo de mostrar selectores d e mensaje y suscripciones duraderas: public c l a s s W r o x T o p l c S u h s c r i b e r I p8.1blic s t a t i c void r n a i n l s r - f i n s [ ] a r g s ) I Topic topic = null; T n p i c C o n n e c t i o n f a c t o r y t o p i c C n n n e c t i o n F a c t o r y = null; T o p i c C o n n e c t i o n topicCannection = n u l l ; JMS y beans controlados por mensaje Context jndicontext = n e w InitialContext ( 1 ; topicConnectionFactory = ( T o p i c C o r ~ n e c t i o n F a c t o r y ) j r~3iCor~text. lookup ( " T o p i c C o r ~ n e c t i o n F ' a c t o r y ";) topic = ( T o p i c ) j ndiContext. l o o k u p ( " W r o x P ~ ~ t i l i c a t i o n s;" ) 1 catch (NamingEzception nEx) [ System. out. println (r1Ex.tostring ( ) tf'\r~Doesthe topic e x i s t ? " ) ; System.exiti1); try i topicConnection = topi cConnectionFactory. c r e a t e T o p i c C c c r ~ r ~ e c t i o( r) ~; TopicSession topicSession = t o p i c C o r ~ n e c t i o n . c r e a t e T o p i c S e s s i o r(false, ~ Session.AUTOACKNOWLEDGE); Todo hasta el momento ha sido igual, excepto, por supuesto, las sustituciones de apartado/cola. A continuacion, creamos cuatro T o p i c S u b s c r i b e r s ; el primer0 es un suscriptor duradero (del que hablaremos mis adelante) que escuchari mensajes alli donde la p r o p i e d a d ~ e t a ~ acontiene ta la palabra J Z E E . El segundo T o p i c s u s b c r i b e r esti configurado para escuchar libros publicados en "Alsaciano" (un dialect0 alemin hablado en Francia oriental). El tercero escucha cualquier libro que contenga la palabra "Java" y el ultimo simplemente escucha todo (por defecto): TopicSubscriber topicSubscriberDurableJ2EE = topicSession.createDurableSubscriber(topic, "Wrox", "MetaData LIKE false); TopicSubscriber topicSubscriberAlsacien = topicSessior~.createSubscriber(topic, "Languages LIKE false); TopicSubscriber topicSubscriberJava = topicSessiar~.createSubscri~er(topic, "MetaData LIKE false); '%JZEE%"', '%Alsacien%"', '%Java%"', Si se esti preguntando cuil es el liltimo parimetro, el parimetro " n o ~ o c a "l permite que 10s mensajes procedentes de la conexion local (la suya propia) Sean aceptados o bloqueados; en este caso, f a l s e significa que 10s mensajes locales estin permitidos. Ahora necesiramos configurar cuatro oyentes distintos. El constructor de la clase oyente toma un parimetro name para capacitar la identificacibn de una determinada instancia: topicSubscriberDurableJ2EEEsetMessageLister~er( new WroxTopicI~istener("Durable, J2EE" ) ) ; topicSubscriberAlsacien.settopicSubscriberAlsacien.setMessagelistenMes~aqeLi~tener( new WroxTopicListener("a1sacien")); topicSubscriberJava.setMessageLister(new WroxTopicListener("Java"j); topicSubscriberAll.setMessageListener(rew WroxTopicListener("A11")); System.out.println("Waitir~g I minute for messages.. for (int i = 60; i > 0; i-) { System.out.print("Count down . . . "ti+" \rt'); ." 1 ; Capitulo 19 I catch (JMSException j m s E x ) I System.out .println("Exception: " 1 catchiException lazy) I S y s t e m . o u t .printlr~("Exception: " ] finally I if (topicConnection ! = null) I try I topicConnection.close(); ) catch (JMSException e ) ( I ] t jmsEx. tostring ( t lazy. tostring ( ) ) ; ) ) ; I I Es necesario que creemos nuestro nuevo oyente, W r o x T o p i c L i s t e n e r : import j ava. util. D a t e ; import j avax. j ms. * ; public c l a s s WroxTopicListener implements MessageListener { private String name; public WroxTopicListener[String name) { this.name = name; System.out.println[namet" MessageListener created"); public void onMessage(Message message) { try { TextMessage textMessage = (TextMessage) message; System.out.println(name + " -> " t textMessage.getText()); I catch (JMSException jmsEx) { System.out .println ("JMSException in onMessage ( ) : " + jmsEx.toString() ) ; 1 catch(Exception e ) { System.out.println ("Exception: " + e. tostrirlg ( ) ) ; 1 Hay algo mis que tenemos que hacer antes de poder ejecutar este ejernplo. Los suscriptores duraderos deben tener un ID de cliente para identificarlos. El ID de cliente es el context0 del suscriptor para diferentes sesiones; recuerde que podriamos regresar a una suscripci6n que hayamos configurado hace a@n tiernpo en una sesi6n o aplicaci6n totalrnente distinta. Analizarernos con detalle las suscripciones duraderas rnuy pronto pero, por el mornento, podernos configurar prograrniticarnente el c l i e n t ID utilizando: j avax. jms. C o n n e c t i o r ~ . setC1ientID("WroxX') Sin embargo, hay una serie de condiciones que hacen que este enfoque prograrnitico sea proclive a generar excepciones. Por lo general, el rnodo rnis fiable de realizarlo es utilizando la herrarnienta j 2 e e a d m i n : j2eeadmin -addjmsFactory TopicConnectionFactory topic -props clientId=Wrox Ejecute este cornando para configurar una propiedad c l i e n t I D parawrox. Se configura corno una propiedad de c o n n e c t i o n F a c t o r y . Ya estarnos preparados para cornpilar y ejecutar el consurnidor JMS y beans controlados por mensaje No se recibe ninglin mensaje porque el apartado ~ r o x ~ u b l i c a t i o nn so tiene n i n g l h suscriptor por el momento. Pero si volvemos a ejecutar ~ r o x ~ o p i c ~ u b l i s h e r : j ava - P j m s . p r o ~ r r t i e s = ' 3 J 2 E , EHOE.IEY.\i'r.rtf i 7 \ j m z -c l i e n t . Fr - i f p e r t i e s i suhbel r ;I J 2 E F- M O i 4 E ? \ l i b \ T 2 e e ,+ r ; ~ : J ~ i ~ ~ T o p i c P -cp . .> y despu& ejecute d e n u e v o ~ r o x T o p i c S u s b c r i b e r : j aT?a -Cjm? . p r . ~ p ~ r t i ~ . = = ? ~ 7 2 E E - H O I ? E P \ 1i zq r\ ~jnmf--~c l i e r l t . ~ r i l p r r it e s -.zrr Debe ver algo asi: .;4J:EF: - HOP:F*?lik,\jLre.jRT; !'!r~?:.:T~~pi~S'~hss:rit.er Capitulo 19 La primera vez que s e ha e j e c u t a d o ~ r o x ~ o p i c ~ u s b c r i bsee ha r , suscrito indefinidamente al apartado W r o x P u b l i c a t i o n s . Lo que hace el suscriptor duradero es configurar una conexidn que permanece efectiva hasta que invocamos explicitamente el m t t o d o u n s u b s c r i b e ( ) . Esto significa que el proveedor JMS es responsable de almacenar y posteriormente reenviar 10s mensajes perdidos o n o expirados cuando el suscriptor, identificado por el mismo c l i e n t ID,renueve su conexion. Corno sugiere su funcionalidad, esto se conoce c o m o mensajeria de almacenamiento y reenvio y, en lo que se refiere a funcionalidad, es similar al m o d 0 que funcionan las colas. La mensajeria d e almacenamiento y reenvio es una parte fundamental de las soluciones d e mensajeria d e hoy en dia, puesto que el hecho d e que 10s rnensajes lleguen independientemente d e la durabilidad d e la conexidn proporciona una base perfecta para la conectividad B2B fiable. Para retirar la suscripci6n a una conexidn duradera, tendriamos primer0 que cerrar el suscriptor, asi: sher, 10s siguientes Si e ~ e c u t a m o s ~ r o x T o p i c ~ u b s c r iybde er s p u ~ s ~ r o x ~ o p i c ~ u b l i obtenemos resultados: I I El orden d e 10s mensajes serP aleatorio porque 10s mensajes se reciben asincr6nicamente. P o d e n ~ o sver que, salvo " A 1 1 " W r o x T o p i c L i s t e n e r , cada oyente ha recibido 10s mensajes a 10s que selectivamcnte se ha n erecibido r 10s mensajes. suscrito. E s t i claro que m i s de un s u s c r i p t o r ~ r o x ~ o p i c ~ i s t e ha Para alcanzar la selectividad, utilizamos un selector d e mensajes. Puede configurarse durante el m t t o d o c r e a t e s u b s c r i b e r ( ) . Los selectores d e mensaje son extremadamente capaces y proporcionan posibilidades ilimitadas d e seleccionar mensajes. La sintaxis estP basada e n un subgrupo d e SQL-92. Esencialmente, utjliza t o d o lo que encontrariamos normalmente despues d e la i n s t r u c c i d n " ~ ~en~ ~ ~ " SQL-92 normal. Estos s o n algunos ejemplos: Price . I 50 P r i c e BETWEEN 1 5 A N D 5 0 F r i c ? < 50 OR ( P r i c e < S O C u r r e n c y IN I ' C A D ' , 'GBP' JMSFriori ty=q Title NOT NULL , AND M e t a O a t a L I K E '%Java%') 'AYD' , 'NZD' , 'INRI ) Las propiedades de usuario, n o s61o puede utilizarse para seleccidn, sino que algunas de las propiedades fijas del mensaje, c o m o P r i o r i t y , tambitn pueden utilizarse. Otras que pueden ser incluidas: JMS y beans controlados por mensaje JMSDeliveryMode,JMSPriority,JMSMessage,JSCorrelationIDy JMSType.Algunas de estas propiedades pueden devolver el valor n u 1 1,asi que, si queremos tener criterios fiables de selection debemos utilizar 10s operadores I S NULL o NOT NULL. Puede encontrar 10s detalles completes en el Javadoc de la interfaz Message y en la secci6n 3.8.1.1 de la especificacidn J M S (viase http:lljava.sun.comlproductsljmsldocs.html). Las interfaces JMS forman parte del paquete j avax . jms.Aqui presentamos algunos de 10s mktodos mis complejos, inusuales o exhaustivos de la interfaz. La,mayoria de las interfaces que faltan y algunos de 10s mktodos que faltan, son 10s XA (transaccionales). Estos son por lo general versiones XA de las interfaces o mitodos estindar (distintos de XA) y son utilizados al incluir transacciones JMS en una transacci6n Java Transaction Service (JTS). El proveedor JMS expone su compatibilidad JTS utilizando XAConnectionFactory JMS, que es utilizada por un senidor de apkaci6n para crear una XASess ion. Interfaz Descripci6n BytesMessage Utilizadapara enviarun mensajequecontengaun streamde bytes sin interpretar. Connection Una conexi6n activa del cliente a su proveedor JMS; incluye 10s siguientes mktodos: void setClientID (String clientID) ,configuraelIDdelclientepara la conexi6n. El modopreferido de configurar el IDE cliente consiste en configurar Connect i onFact or y utilizando las herramientas de administraci6n JMS provistas. Si el I D del cliente ha sido configurado por la herramienta de configuracibn, al invocar este metodo se genera una excepci6n IllegalStateException. void start ( ) ,inicia o reinicia la entrega de mensajes de la conexihn. void stop ( ) ,interrumpe temporalmente laentregade rnensajes delaconexibn; sin embar o, se bloquea hasta que recibe un mensaje y l o hasta que se hayan completa o todos 10s oyentes de mensaje en funcionamiento. Interrumpir una sesi6n no tiene ningun efecto sobre su capacidad de enviar mensajes e invocar st art ( ) marcari el reinicio. f Connection Factory Encapsula un conjunto de parimetros de configuracidn que han sido definidos por un administrador. Connection MetaData Proporciona informaci6n que describe la connect ion. DeliveryMode Modos de entrega apoyados por JMS, sencillamente PERSISTENT y N O N PERSISTENT. El mod0 de entrega s610 cubre el transporte del mensaje a su destino. Destination Encapsula direcciones especificas del proveedor puesto que JMS no define una sintaxis estindar de direcci6n. Aunque consider6 una sintaxis estindar de direcci6n, decidi6 quelas diferencias en la semanticade direcciones entre productos M O M existentes eran demasiado dificiles de eliminar con una unica sintaxis. Except ion Listener Si un proveedor JMS detecta un roblema grave con unaconnect ion,informari a1 ExcevtionListener de a conexi6n. si se ha registrado una. P tabla continua - siguiente Capitulo 19 Interfaz Descripcih MapMessage Utilizada para enviar un conjunto de pares valor-nombre donde 10s nombres son cadenasy 10s valores son tipos de primitiva Java. Se puede acceder a las entradas de valor nombre secuencialmente por enumerador o por nombre. Message La interfaz raiz de todos 10s mensajes JMS. void correlation^^) configuraelID ue setJM~~orrelation (string 1~ podia haber sido configurado por el proveedor JMS (si se ajusta a lor I D ge mensaje o por el cliente JMS utilizando el metodo de confi uraci6n. Se utiliza a menu o para correlacionar de aplicacih a aplicacibn. poiria utilizarla para identificar un mensaje de respuesta auna solicitudprevia; el I D de la solicitud se utilizaria en la respuesta. La respuestapodria llegar despues de la solicitud y el I D de correlacion es un buen modo de llgar ambos elementos. Los valores especificados en la aplicacion no deben comenzar con el prefijo "ID : ";queda reservado para valores de I D de mensajes generados por el proveedor. d Un cliente utiliza un consumidor de mensajes para recibir mensajes desde un Destino; un consumidor de mensajes es asincrono y proporciona metodos comoreceive ( ) yreceiveNoWait ( ) . Message Listener Utilizada para recibir mensajes recibidos asincr6nicamente; so10 hay un mensaje definido por esta interfaz, o m e s s a g e ( ) . U n cliente utilizaunproductor de mensajeparaenviarmensajes aunDestino. void setDeliveryMode (int deliveryMode) configurael modo de entrega. Opciones vilidas son Del ive ryMode .NON-PERSISTENT y De1iveryMode.PERSISTENT. void setDisableMessageID (boolean value) esparaactivar/desactivar 10s I D del mensaje. Puede utilizarse para reducir el tamafio del mensaje y, en ocasiones, para aumentar el rendimiento. void setDisableMessageTimestamp(boolean value),esparaactivar/ desactivar las estampillas de tiempo del mensaje. Puede utilizarse para reducir el tamafio del mensaje y, en ocasiones, para aumentar el rendimiento. void setpriority (int defaultpriority) ~ o n f i ~ u r a e l m e n s a j e d e prioridad pordefecto.0 es elvalor mis bajo,O-4 son grados de prioridad "normal", 5-9 son considerados prioridad " r i ida" Para prioridad normal utilizar Message. DEFAULT-PRIORI&. . void setTimeToLive (long timeToLive) confi u r a e l t i e r n p ~ d e v i d a ~ o r defecto en milisegundos. Configurar el tiempo de vifa en cero (el valor por defecto) significa efectivamente "ilimitado". Utilizada para enviar un mensaje que contiene un objeto Java serializable. Si se necesita una coleccion de objetos Java, podemos utilizar una clase de coleccih Java. Queue Encapsula un nombre de cola especifico del proveedor. QueueBrowser U n cliente utiliza un QueueBrowser paraexaminar mensajes en una cola sin eliminarlos. Queueconnection Una conexi6n activa a un proveedor JMS punto-a-punto. JMS y beans controlados por mensaje Interfaz Descripcibn QueueConnection Factory U n cliente utiliza unaQueueCo n n e c t i o n F a c t o r y ara crear Q u e u e c o n n e c ti o n s c o n u n P r o v e e d o r P ~JMS P con E s sipientes mktodos: QueueConnection c r e a t e Q u e u e C o n n e c t i o n ( ) QueueConnectioncreateQueueConnection(StringuserName, Stringpassword) QueueReceiver U n cliente utiliza un Q u e u e R e c e i v e r para recibir mensajes que han sido entregados a una cola. Queuesender U n cliente utiliza un Q u e u e s e n d e r para enviar mensajes a una cola. v o i d s e n d ( Q u e u e queue, Messagemessage, i n t d e l i v e r y M o d e , i n t p r i o r i t y , l o n g t i m e T o L i v e ) enviaun mensajeaunacolaparaun productor de mensaje no identificado, especificando mod0 de entrega, pr~oridad y tiempo de vida. Proporciona mktodos para crear Q u e u e R e c e i v e r s , Q u e u e s e n d e r s , QueueBrowsersyTemporaryQueues. QueueBrowser c r e a t e B r o w s e r ( Q u e u e queue, S t r i n g m e s s a g e S e l e c t o r ) crea unQueueBrowser paranave ar,peronoconsumir, mensajes en una cola con un selector de mensaje especi KO. ? Q u e u e c r e a t e Q u e u e ( S t r i n g queueName) ; p ~ o ~ i s t o p a r a c a s ~ s r a r o s e n 10s que clientes necesitan manipular dinimicamente a ~ d e n t ~ d de a dla cola. Suuso no es portitil. TemporaryQueue c r e a t e T e m p o r a r y Q u e u e ( ) creaunaco~atempora~cuya duracidn de vida no es superior que la de Q u e u e c o n n e c t i o n . Session U n context0 de hilo Gnico para producir y consumir mensajes. v o i d r e c o v e r ( ) ,interrumpela entregade mensajes enestasesi6nylareinicia enviando mensajes con el mensaje adm~tidomas antiguo. v o i d s e t M e s s a g e L i s t e n e r ( M e s s a g e L i s t e n e r l i s t e n e r ) ;utilizado con poca frecuencia, mis a menudo utilizado por sewidores de aplicacidn. StreanMessage Utilizado para enviar un flujo de primitivas Java. TemporaryQueue U n objeto exclusivo~ueue creado para la duracidn de u n a ~ u e u e c o n n e cito n . TemporaryTopic U n objeto e x c ~ u s i v o ~ ocreadopara ~ic l a d u r a c i d n d e u n a ~ o p i c ~ o n n eicotn . TextMessage Utilizada para enviar un mensaje que contengan un s t r i n g . Topic Encapsula un nombre de apartado especifico del proveedor. TopicConnection Una conexi6n activa a un ~ r o v e e d oJMS r pub/sub. TopicConnection Factory; U n cliente u t i ~ i z a u n a ~ o ~ i c ~ o n n e c t i o n ~ paracrear actory T o p i c c o n n e c t i o n s con un proveedor JMS pub/sub. TopicPublisher U n cliente utiliza u n T o p i c Pub1 i s h e r parapublicar mensajes en un apartado. v o i d s e n d ( T o p i c t o p i c , Message message, i n t deliveryMode, i n t p r i o r i t y , l o n g t i m e T o L i v e ) enviaunmensajeaunapartadopara un productor de mensaje no identificado, especificando mod0 de entrega, prioridad y tiempo de vida. La tabla continua en la pdgina siguiente 1027 Capitulo 19 I Interfaz Descripci6n TopicSession ProporcionamCtodos p a r a c r e a r T o p i c P u b l i s h e r s , T o p i c S u b s c r i b e r s y TemporaryTopics. TopicSubscriber createsubscriber (Topic t o p i c , S t r i n g messageSelector, boolean n o l o c a l ) creaunTopicSubscriber para el apartado especificado utilizando selectores de mensaje. El parimetro n o l o c a l permite ue 10s mensajes procedentes de la conexion local (la suya propia) Sean acepta%os o bloqueados. TopicSubscribercreateDurableSubscriber ( T o p i c t o p i c , S t r i n g n a m e , S t r i n g m e s s a g e s e l e c t o r , b o o l e a n n o l o c a l ) creaun T o p i c S u b s c r i b e r duraderoparaelapartadoespecificado.Elnombreprovisto debe corresponder con el ID cllente de laconexi6n (vtase ejemplo anterior). El parLmetronoLoca1 permite que 10s mensajes procedentes de laconexi611local (la suya propia) Sean aceptados o bloqueados. TopicSubscriber U n cliente utiliza u n T o p i c S u b s c r i b e r para recibir mensajes que han sido publicados para un apartado. Utilizar transacciones con JMS El mod0 m6s sencillo de utilizar JMS con transacciones consiste en utilizar una sesi6n JMS transaccionada. Sin embargo, esto nos lirnita a JMS. Es decir, podernos agrupar mensajes y realizarlos o deshacerlos. Esto es bastante restrictivo. Por ejernplo, podriamos n o consurnir un mensaje y entonces grabarlo en la base de datos en una h i c a transacci6n; esto requiere el uso del Semicio de Transacciones Java (JTS). Crear una sesi6n JMS transaccionada es bastante sencillo; el primer parirnetro del rnttodo c r e a t e X X X S e s s i o n ( ) puede utilizarse para configurar una sesi6n transaccionada: Queuesession queuesession = TopicSession topicsession = connection.createQueueSession( true Session.AUT0 ACKNOWLEDGE conr~ection.create'~opicSession( true, Session.AUT0ACKNOWLEDGE Los rnensajes enviados o recibidos utilizando esta sesi6n son agrupados autorniticarnente en una transacci6n. Es irnportante sehalar que no hay ninghn rnttodo b e g i n ( ) : TextMessage textMessage1 TextMessage textMessage2 TextMessage textMessage3 = = = queueSession.createTextMessage(); queueSession.createTextMessage(); queueSession.createTextMessage(); textMessagel.setText("Send J2EE book to client 45827"); textMessage2.setText("Reduce J2EE book stock by 1 " ) ; textMessage3.setText("Add $49.95 client 45827's bill"); queuesender. send (textMessage1); queueSender.send(textMessage2); queueSender.send(textMessage3); Estos tres mensajes anteriores pueden realizarse utilizando c o m m i t ( ) ); ); JMS y beans controlados por mensaie q u e u e s e n d e r . commit ( ) ; o anularse con r o l l b a c k 0: queueSender. r o l l b a c k ( ) ; TextMessagel, TextMessage2 y TextMessage3 sonahoraenviados (orecibidos) comounsologrupo. N o estamos limitados simplemente a enviar o recibir. Podemos combinar ambas acciones y vincular recibir y enviar en una sola transaccidn. Esto resulta Gtil cuando estamos reenviando mensajes en una pasarela. O t r o uso es el de vincular colas a apartados. Por ejernplo, llegan noticias a la cola y despuks son "transmitidas" a 10s suscriptores de un apartado determinado en una Gnica transaccidn. Si algo falla en la publicacidn, el mensaje n o seria leido desde la cola (suponiendo que tuviera lugar la llamada a rollback 0). Tres implementaciones JMS de peso industrial Existen mis de una docena de buenas implementaciones JMS entre las que poder elegir. Nuestra eleccibn de proveedor dependeri ampliamente del uso: algunas son gratuitas, otras de c6digo abierto, otras disefiadas para mayor rendimiento y/o fiabilidad, y otras son vendidas como parte de mayores aplicaciones o servidores de aplicaci6n. Las tres siguientes son ficiles de descargar e iniciar (aunque SonicMQ y SpiritWAVE requieren claves de licencia para su uso, claves que son ripidamente proporcionadas y sin ningGn tip0 de problema). Todas ellas son implementaciones profesionales y todas de base Java. Para cualquier situacidn concreta, probablemente haya un JMS que sea ligeramente m i s ripido, m6s fiable o que se reajusta mejor que el resto. Estas son algunas de las cuestiones que nos plateamos a1 elegir un JMS: O iPuede clasterizarse el servidor de destino? 0 i C o m o se reajusta la clusterizacibn? CI iQuk sistema operativo recomienda en proveedor? 0 iRealmente necesita todas las funciones bonitas per0 n o estindar? O Si estamos buscando velocidad, inecesitamos mensajeria punto-a-punto o pub/sub? EI iQuk sucede con el rendimiento cuando empieza a afiadir selectores de mensaje? iQuk ocurre cuando afiade un suscriptor duradero? o Si la pkrdida de un mensaje o la entrega de un duplicado puede costarle dinero, ise centra en proveedor en la fiabilidad en lugar de la velocidad? Es importante probar cualquier implementaci6n JMS en un entorno real con condicionas tan cercanas como sea posible a la soluci6n deseada. Examinemos ahora m5s de cerca tres de estas implementaciones JMS. SwiftMQ (http://www.swiftmq.com), en contraste con sus competidores, es totalmente gratuito. N o s610 su desarrollo es gratuito, sino tambikn su implementacidn. La licencia establece lo siguiente: Capitulo 19 "SwiftMQ Binary Code License Agreement. SwifiMQ es completamente (lit.) GRATISpara uso privado y comercial asi como para implementacidn y asociacio'n con su producto comercial o servidor de aplicacidn de cddigo abierto." La ultirna versi6n,2.01, implementa a1 cornpleto la rnensajeria punto-a-punto y publsub para la version de la especificacion 1.0.2 e integra un rico conjunto de utilidades, todas ellas ficilmente configurables a travks de archivos de propiedad, una interfaz de linea de comando (CLI) y el GUI que utiliza SwiftMQ Explorer. La docurnentacion, en forrnato Javadoc, es ficil de seguir y rnuy completa. TarnbiCn se puede descargar. del misrno sitio SMTP Mailer Extension, que proporciona un puente SMTP que perrnite el envio de e-mail desde clientes JMS. Por ejernplo: Q u e u e s e n d e r s e n d e r = session.createSender(rnai1Queue); T e x t M e s s a q e msq = s e s s i o n . c r e a t e T e x t M e s s a q e ( ) ; m s g . s e t S t r i n g P r o p e r t y ( " f r o m " , " r e a d e r @ w o r k . c o r n " ); m s g . s e t S t r i n g P r o p e r t y ( " t o " , " J o h n @ C 2 4 S o l u t i o r ~. cso r n t ' ) ; r n s g . s e t S t r i n g P r o p e r t y ( " r e p l y t o " , " r e a d e r @ h o r n e . c o r n " ); r n s g . s e t S t r i n g P r o p e r t y ( " c c " , "Wayne . M e i k l e @ C 2 4 S o l u t i o n s .corn") ; r n s g . s e t S t r i n g P r o p e r t y ( " s u b j e c t " , "JMS"); rnsq. s e t T e x t ( " T h i s JMS API i s q r e a t s t u f f ! " ) ; s e n d e r . s e n d (rnsg); Existe tambikn una extension puente JMS que proporciona funcionalidad de puenteado entre SwiftMQ y cualquier sistema externo que se adapte a JMS 1.0.2. SwiftMQ esti preconfigurado con dos colas, un apartado y una cornpleta serie de ejernplos para iniciarse. A partir de su descarga, en tan s610 unos minutos despues de su instalaci611, puede ejecutarse. Modificar 10s ejemplos y las colas provistas es el rnodo mis ficil de ernpezar a partir de ahi. Y lo fundamental sigue siendo que es completamente gratuito. SpiritWave SpiritWave de Spiritsoft ( h t t p : / / ~ ~ ~ . ~ p i r i t - S Oes~una . C Olas ~ )irnplementaciones rnis cornpletas en tkrrninos de irnplementacion central y funciones extendidas. SpiritWAVE, completamente adaptado a JMS 1.0.2, arnplia el apoyo a XA, a tunelizacion HTTPI Cortafuegos y SSL, relevo dinamico, tolerancia a fallos y clustering o operation de agrupamiento. Otra caracteristica es su compatibilidad con controladores conectar-y-usar y transforrnaciones para rnensajeria de legado con, por ejemplo, Tibco Rendezvous 5.x, 6.x y ETX, IBM M Q Series, MSMQ, Talarian SrnartSockets, y WebMethods Activeworks. Tarnbien se integra en varios semidores de aplicacion y, algo muy interesante, tiene adaptadores SpiritWave JMS para aplicaciones Microsoft C O M . Hay varias extensiones para las capacidades del selector del JMS. Por ejernplo, puede realizar selecciones avanzadas basindose en el contenido XML del cuerpo del rnensaje. Estas irnportantes caracteristicas permiten, por ejemplo, el direccionamiento de mensaje basado en contenido XML, per0 esto conlleva el coste de la portabilidad en irnplernentaciones JMS. SpiritWave integra un arnplio conjunto de ejemplo y la docurnentaci6n se encuentra en formato PDF. SonicMQ de Sonic Software (http://www.sonicsoftware.com) es probablemente la implernentaci6n JMS rnis conocida. SonicMQ es tarnbikn una implementacibn cornpleta de la especificaci6n JMS 1.0.2 con apoyo XA. Cuenta con excelente documentacion (en forrnato PDF) y tarnbikn inchye codigo de muestra instructivo. JMS y beans controlados por mensaje SonicMQ hace alarde de mensajeria XML integrada, arquitectura dinimica de direccionamiento (DRA), clusterizacidn y apoyo completo a PKI y SSL. SonicMQ tambikn puede integrarse con puentes, como IBM M Q Series y servicios de correo FTP y SMTP. Beans controlados por mensaje DespuCs de examinar algunos de 10s API controlados por mensaje (MDB), examinaremos el ciclo de vida de un MDB y veremos un sencillo ejemplo que demuestra su uso con transacciones EJB. Los beans controlados por mensaje fueron introducidos en la especificacidn EJB en la versidn 2.0; el objetivo era proporcionar un mecanismo para el manejo asincrono de mensajes en EJB. Esto complementa 10s beans existentes de Sesidn y de Entidad disponibles en EJB 1.0, 1.1 y 2.0. El bean controlado por mensaje es, esencialmente, un oyente de mensajes que puede consumir mensajes de una cola o de una suscripci6n duradera a travis del contenedor J2EE; el contenedor invoca a1 bean como resultado de la llegada de una mensaje JMS. El cliente percibe el bean controlado por mensajes como un consumidor JMS que implementa 16gica de empresa per0 que s61o puede comunicar con el bean enviindole un mensaje a travCs de JMS. Los beans controlados por mensaje pueden comunicar con beans de sesidn y con beans de entidad para ampliar la 16gica de empresa o para proporcionar cierta forma de persistencia de aplicaci6n. Los beans controlados por mensaje son anbnimos, no tienen estado conversacional con el cliente y puede ser reservados como beans de sesi6n sin estado. A diferencia de otros tipos de EJB, 10s beans controlados por mensaje no tienen interfaces iniciales ni remotas. Debido a la carencia de estas interfaces de lado cliente, 10s clientes no pueden interactuar con ellos; el bean es invocado con la llegada de un mensaje. El contenedor EJB realiza las funciones de reserva de recursos, seguridad y gesti6n de transacciones, y mantiene el ciclo de vida de 10s beans controlados por mensaje. Los beans controlados por mensaje no son ideales para situaciones que requieren que multiples colas o apartados sean atendidos por un h i c o consumidor JMS. En este caso, una mejor opcidn seria utilizar varios beans controlados por mensaje para cada cola o, simplemente, utilizar consumidores JMS "estindar". Los MDB esti tambikn bastante limitados por el hecho de que la cola o el apartado son definidos en el descriptor de implementaci6n en el periodo de implementaci6n en lugar de en el periodo de ejecuci6n. Y, lo que es peor a h , 10s selectores de mensaje tambiCn son definidos en el descriptor. Esta es una las caracteristicas mis importantes de JMS y e s una pena que sea fijado en el descriptor de implementacidn. Existen formas de evitar esto en la mayoria de servidores de aplicacidn pero, si utilizamos estas opciones, estamos desviindonos de la especificaci6n J2EEIEJB y corremos el riesgo de atar nuestra aplicacidn a una implementaci6n especifica. Los beans controlados por mensaje deben implementar j avax .jms .MessageListener y javax. e j b .MessageLjstener.Elcuerpo delreceptores i m p l e m e n t a d o e n e l m C t o d o o ~ e s s a g e( ) de Mes s ageLi s tene r. Este no debe generar excepciones JMS o de aplicaci6n; en su lugar, las excepciones deben ser capturadas y, preferiblemente, procesadas. Como minimo, deben volver a generase como EJBExcept ion. U n MDB "bien educado" (corno otros EJB) no debe generar una excepcidn RuntimeException. Capitulo 19 M e s s a g e D r i ~ e n B e a n e s ~ e c i f i cs61o a dos mitodos: 0 void e j bRemove ( ) es invocado por el contenedor justo antes de que el bean sea eliminado 0 void setMessageDrivenContext (MessageDrivenContext ctx) configuraelcontexto para el bean Finalmente, es necesario definir 10s mitodos de creaci6n y elimination. Las firmas relevantes son: 0 public void ejbcreate ( ) Donde debe crear las conexiones JMS si pretende enviar mensajes desde este bean 0 public void e jbRemove ( ) Donde debe cerrar cualquier conexi6n realizada en el metodo e jbCreate ( ) N o hay ning6n otro mttodo de empresa en el MDB. Pueden definirse otros mCtodos para proporcionar funcionalidad de empresa pero, normalmente, s610 serian invocados desde onMessage ( ) ya que este mensaje es el unico modo de comunicar con el bean. Ciclo de vida del bean controlado por mensaje El EJB controlado por mensaje se inicia con la invocaci6n de 10s siguientes mitodos: En este punto, hay una instancia MDB en la reserva preparada para mCtodos del contenedor, preparada para procesar mensajes desde su destino. El contenedor invoca e j b R e m o v e ( ) cuando ha terminado con el EJB: f! Reserva preparada r para rnetodos onMessaqe ( ) ', I Transacciones en beans controlados por mensaje Hay dos tipos de gesti6n de transacciones para beans controlados por mensaje: 0 Gestionadas por bean JMS y beans controlados por mensaje a Gestionadas p o r contenedor st as afectan a 10s atributos transaccionales del metodo onMessage ( ) y a1 manejo de la entrega de mensajes garantizada. Transacciones gestionadas por bean Los limites transaccionales deben ser definidos en el metodo omessage ( ) y realizados o anulados antes d e que devuelva u n valor. La entrega del mensaje n o e s t i garantizada porque el proceso de desacolaci6n e s t i fuera de 10s limites transaccionales, a menos que se utilice j avax. transaction. user~ransaction. Siseutilizaj avax.transaction .user~ransaction, una aplicaci6n cliente puede demarcar explicitamente 10s limites de la transacci6n. Transacciones gestionadas por contenedor Este tip0 garantiza la entrega del mensaje. So10 estin permitidos aqui dos atributos transaccionales: NotSupported y Required. Los beans controlados por mensaje no propagan transacciones distribuidas. E n el caso de NotSupported,el bean es ejecutado sin una transacci6n. Si se configura Required,el bean es ejecutado en una nueva transacci6n. Un ejemplo de bean controlado par mensaje Lo finico que vamos a hacer en este ejemplo tan sencillo es imprimir el tip0 de mensaje y, en la mayoria de 10s casos, el contenido de mensaje para system.out.Si se e s t i preguntando ddnde estin todas las factorias de conexion y las conexiones, la respuesta es que son configuradas en la fase de irnplernentaci6n del bean. EI siguiente c6digo corresponde a nuestro e j e r n p l o ~ e s s a g e ~ r i v e n ~ r o x ~ e a n : import j a v a x . e j b . + ; import j avax. jrns. + ; import j avax.narning. '; public class Mess3qeDrivenWroxBear~ implements MessageDrivenBean, privat.e MessageDrivenContext ctx; MessageListener { publiz void setMessageDrivenContext (MessageDrivenContext c t x ) { this.ctx = ctx; 1 public vbld ejbCreate ( ) throws CreateException { Systern.out .println ("Message-Priven bean created") ; 1 public void onMessage (Message rnsg) { System.out.printlr~("Message received: " ) ; try i if (msg irjstanzeof TextMessage! { Systern.out.printlr~("TextMessa~~e: " + ( (TextMessage)msg).getText() ); 1 else if (msg instanceof ObjectMessage) { System.out .println ("ObjectMessaqe: " + ([ObjectMessaqe)rnsg).getObject(!); 1 else if (rnsg instanceof StrearnMessage) { System.out .println ("StrearnMessage: " + ((StreamMessage)rnsy).readStringi)); Capitulo 19 I } else if (msg instanceof BytesMessage) [ System.out.println("BytesMessage: "t( (BytesMessage)msg).readUT€()) ; else if (msg instanceof MapMessage) ( System.out .println ("MapMessage: " t ( (MapMessageimsq) .getstring ( "msg4')) ; 1 } catch(Exception any) [ System.out.println ["Exception: " 1 I public void e j b R e m o v e 0 { } Implement,aciondel bean controlado por mensaje Igual que ocurre con cualquier tip0 de EJB, escribirlo es s61o la mitad del trabajo; el resto esti en la implementaci6n. Compile su bean con el siguiente comando: j avac -classpath . ;% J2EE_HOME%\lib\j 2ee. j ar MessageDrivenWroxBean. j ava Inicie entonces la herramienta de implementaci6n del servidor de la aplicaci6n; esto se realiza en la implementaci6n de referencia JZEE con el comando deploytool desde el directorio % J2EE-HOME% \. Asegfirese, llegado a este punto, de que esti trabajando con un servidor de aplicaci6n que se ajusta a EJB 2.0; de lo contrario, no veri las opciones de "bean controlado por mensaje". Algunos proveedores JMS de terceros ofrecen funciones MDB que complementan 10s servicios de aplicaci6n; no obstante, a medida que va pasando el tiempo, hay servidores de apkaci6n que se ajustan a MDB cada vez mis "reales". Las siguientes instrucciones se relacionan especificamente con la Implementaci6n de Referencia JZEE; otros servidores de aplicaci6n diferirdn en sus tkcnicas de implementaci6n y la documentaci6n relevante debe ser referida. Una vez se ha cargado la herramienta de despliegue, seleccione File (Archivo) I New (Nuevo) ( Application (Aplicaci6n) e introduzca ~ r o x ~ pseleccione p, despues File (Archivo) ( New (Nuevo) 1 Enterprise Bean. Esto le Ilevari a traves de una serie de cuadros de diilogo: JMS y beans controlados por mensaje A J A R file is requ~redto contain this enterprise bean. You can create a new JAR Rle withln an existing application or use an existing JAR file. Afler you have selected a JAR file, add Ihe EJB classes and any other desired Rles lo ~t's contents. Optionally, you can also provide a description, edit the manifest classpath, and choose icons lor the JAR file. --- .- - - - Create new EJB File in Application iJR OIsf~IayName: WrnxMDPean 9Add to Existing EJB File 1 0 Description... 1I . Manifest Classpat Icons., 1 Seleccione su nueva aplicaci6n e introduzca ~ r o x ~ ~ corno ~ e nornbre a n del bean. Pulse Edit (Modificar) y afiada su c l a s e ~ e s s a g e ~ r i v e n ~ r o x (el ~ earchivo an de clase, no la fuente Java), entonces pulse Next (Siguiente). Capitulo 19 Please chnose the type olenterpr~sebean that you are creating ar~dselect the class files from the JAR file that are tu be used for the bean. You can choose to provlde Only local interfaces, only remote interfaces, or both. Op11onally.you can provide a description and icons for the bean. I ' r n i o i ~lnrwf wrc Y"hrFlC1@~;11? 0Description... 1 -- mi, ... 1 1.- Selcccione el tipo de bean Message-Driven, In clase de bean e introduzca el n o ~ n b r cde nuevo. Una vez m i s , hngn clic en Next p a continuar: JMS y beans controlados por mensaje Para 10s prop6sitos de nuestro sencillo ejeniplo, seleccione Bean-Managed y haga clic en Next: Capitulo 19 Corw~ecl~on Factory. QueueConnedionFactoly Acknowl~tfg~rnertt: - I I I JMS hlessaqe Selwlor: I Seleccione ahora la cola o el apartado desde el que desea consumir el mensaje. Tambien sera necesario que seleccione C o n n e c t i o n F a c t o r y y el metodo de acuse de recibo (para este ejemplo, seleccione AutoAcknowledge). Ya casi hemos Ilegado; en este punto, puede hacer clic en Finish (Finalizar). Ahora tiene un bean controlado por mensaje que esti creado per0 no implementado. Recuerde iniciar y conectarse, al servidor JZEE y, en la herramienta de implementaci6n, seleccionar el nuevo MDB. Seleccione entonces Tools (Herramientas) I Deploy (Implementar): JMS v beans controlados por mensaie Please select the object to be deployed and the s e m r to which it should be deployed: Obiect to Denfov! 0 (0WrOXApP v Tarpet SBI%VT: localhod t The server can send back a client J A R Ne. It contains the extra RMIlIIOP stub classes that client applications written In access this applicationwill need at runtime. Esto nos permitirl implementar el bean en el contenedor JZEE; tomar la aplicacih que deseamos implementar y el servidor en el que varnos a hacerlo (probablemente localhost). C o m o siempre, haga clic e n Next, confirme que el nombre JNDI es correct0 y despubs haga clic en Finish para irnplementar su bean controlado por mensaje: Capitulo 19 Contacted Server... Application WroxApp transferred WroxApp has 1 ejbs, 0 web companents to deploy Deploying Ejbs ... Processing beans ... Making client JARS ... Making senrer3ARs ... Deployment ofWroxApp is complete. I ' m conlprobar que nuestro bean controlado por mensaje esti funcionando, debemos ver un mensaje con10 el siguiente en la ventana de comando desde la que hemos iniciado el servidor J2EE: Si ejecuramos e l ~ r o x ~ u e u e ~ e nque d e hemos r utilizado anteriormente en este capitulo con el siguiente comando: Debcmos ver que el Servidor J2EE imprime lo siguiente: Si lo deja implementado en el servidor JZEE, cada vez que ejecute el servidor, tambitn se ejecutara este MDB. Si vuefve a ejemplos anteriores, n o veri sus mensajes porque este MDB 10s consumiri en su nombre. JMS y beans controlados por mensaje Veamos ripidamente el descriptor de implementaci6n. ~ s t es e un archivo XML que contiene la informaci6n de configuraci6n para el bean y ha sido creado por la herramienta de implementaci6n: WroxMDBear~ This is the Wrox descriptior~ WroxMDBear~ < e j b - n a m e > W r o x M D B e a r ~ < / eb-name> j < e j b - c l a s s > M e s s a g e D r i v e r ~ W r o x B e a r ~ < / ebj- c l a s s > Bear~ Client NOT N U L L < / m e s s a g e - s e l e c t o r > Auto-ackr1o~1edge < d e s t i n a t i o n - t y p e > j a v a x . j ms. Q u e u e < / d e s t i n a t i o r ~ - t y p e > Podemos ver que todos 10s parimetros que hemos configurado durante la implementaci6n del MDB han sido escritos en el descriptor de implementaci6n. En este capitulo, hemos echado un vistazo a 10s primeros tiempos de la mensajeria, antes de ver c6mo JMS se ha convertido en el primer (y h i c o ) estindar M O M que cubre 10s dominios punto-a-punto y publicar/suscribir. Utilizando ejemplos sencillos, hemos experimentado de primera mano lo sencillo que es crear una sesi6n JMS, y producir y consumir mensajes. Tambikn hemos analizado la flexibilidad de 10s mktodos de consumici6n, sincronos y asincronos, y 10s importantes selectores de mensajes. En concreto, hemos analizado: o Las diferencias entre dominios punto-a-punto y publicar/suscribir 0 Los bloques de construcci6n de la arquitectura JMS: objetos administrados, conexiones, sesiones, productores de mensajes, consumidores de mensajes y mensajes 0 C 6 m o manejar mensajes asincr6nicamente (utilizando un oyente de mensajes) y c6mo utilizar 10s selectores de mensajes C 6 m o utilizar transacciones con JMS Finalmente, hemos cubierto la 6ltima incorporaci6n a la familia EJB, 10s beans controlados por mensaje: 0 Hemos examinado el ciclo de vida de MDB 0 Hemos visto como crear e implements un sencillo MDB utilizando la Implementaci6n de Referencia J2EE JMS se esti convirtiendo en una de las caracteristicas mls potentes e importantes de J2EE y, ciertamente, seri una importante tecnologia durante mucho tiempo. En el siguiente capitulo, analizaremos otra nueva caracteristica de J2EE 1.3, la Arquitectura de Conectores, que proporciona otro medio de integraci6n de las aplicaciones J2EE con sistemas de legado. La arquitectura Este capitulo presenta una introduccion a la Arquitectura de Conectores JZEE (JCA), una adici6n nueva y significativa a la plataforma J2EE en la versidn 1.3. JCA es una iniciativa de integration de aplicacion de empresa que proporciona una arquitectura estandarizada para capacitar a 10s componentes J2EE a tener acceso "conectar-y-usar" a Sistemas de Informacion de Empresa (EIS), que incluyen ERP, procesamiento de transacciones y sistemas de base de datos de legado. A lo largo de este capitulo, estudiaremos la Arquitectura de Conectores J2EE y desarrollaremos componentes de Conector J2EE para permitir que las aplicaciones J2EE integren e interactuen con recursos EIS. En concreto, nos centraremos en 10s siguientes puntos: a Temas de integracion EIS y el rol de JCA 0 Arquitectura, servicios y API JCA 0 Como funciona JCA en un sistema J2EE 0 Programaci6n con la Interfaz Comfin de Cliente (CCI) 0 Construccion de un componente JCA 0 Reglas que debe seguir un desarrollador JCA 0 Corn0 desplegar y probar componentes JCA 0 Ventajas potenciales del uso de JCA Limitaciones actuales de JCA 1.1 La especificacion actual de la Arquitectura de Conectores esti disponible en el sitio Java de Sun en http:// java .sun.com/j2ee/connector/. Adicionalmente, existe una lista de vendedores J2EE que apoyan la especificacion Capitulo 20 disponible en http://java.sun.com/j2ee/connector/products.htrnl, pero, en este momento, solo la Implementaci6n de Referencia J2EE 1.3 y un par de vendedores J2EE han puesto a disposici6n del pfiblico sus implementaciones beta. Tambikn esti disponible una lista devendedores de EIS que se adaptan a esta arquitectura para proporcionar sus adaptadores de recursos especificos de EIS. Sin embargo, en el momento de publicacion de este libro, ningiin vendedor de EIS ha puesto a disposicih publics sus adaptadores de recursos EIS beta. Integration de EIS y el roI de JCA En la era del comercio electronico, las aplicaciones de empresa habilitadas para Internet y la integration de empresas en Internet se han convertido en un hecho fundamental para sus ventajas competitivas. Sin embargo, antes de la aparicidn de la economia de Internet, muchas compafiias y empresas ya habian invertido fuertemente en sistemas de aplicacibn de informaci6n de empresas y gestion, corno: 0 Aplicaciones de Planificaci6n de Recursos de Empresa (ERP), como SAP R/3 y BAAN. 0 Aplicaciones de Gestion de Relaciones de Cliente (CRM), como Siebel y Clarify. O Aplicaciones de bases de datos, como DB2 y Sybase. 0 Aplicaciones de procesamiento de transacciones principales, como CICS. 0 Sistemas de Base de Datos de Legado, como IMS de IBM. Estos sistemas son denominados generalmente Sistemas de Informaci6n de Empresa, Enterprise Information System (EIS). U n Sistema de Informaci6n de Empresa (EIS) proporciona 10s sewicios e infraestmctura de informaci6n para una empresa. Esta informaci6n puede estar en forma de u n conjunto de registros e n una base de datos, objetos de empresa e n u n ERP, u n objeto de flujo de trabajo en u n sistema de gesti6n de relaciones de cliente (CRM) o u n programa de transacci6n en una aplicaci6n de procesamiento d e transacciones. Incorporar estas complejas aplicaciones de empresa en un sistema de aplicaciones multi-capa supone un reto bastante importante e implementarlas para una aplicaci6n Web de alta disponibilidad es un proyecto colosal. Antes de la Arquitectura de Conectores, algunos vendedores de servidores de aplicacidn proporcionaban o se adaptaban a una variedad de adaptadores personalizados para sistemas EIS integradores. Estos adaptadores proporcionaban bisicamente interfaces nativas personalizadas, que eran complejas de entender y eran restrictivas a1 intentar adaptarse a una arquitectura estindar. Mis concretamente, algunas de estas limitaciones eran las siguientes: 0 La programaci6n de aplicaciones para EIS es de propiedad por naturaleza y la completa variedad de sistemas de aplicaci6n significaba que no existia ningtin mecanismo de interfaz generic0 para la integration de arquitecturas abiertas. O Las aplicaciones Web de gran escala requieren aha disponibilidad y reajustabilidad respecto del nfimero de clientes, gesti6n de conexiones, etc. Tradicionalmente, el ndmero de clientes y sus conexiones activas resultan caras en un EIS y 10s adaptadores personalizados carecen de apoyo para mecanismo de gesti6n de conexiones proporcionados por servidores de aplicaci6n. O La gestion de la seguridad y de las transacciones distribuidas con mtiltiples aplicaciones en segundo plano es extremadamente compleja y carece de mecanismos fiables. Esto significa que no existia La arquitectura de conectores J2EE ninguna soluci6n disponible de infraestructura estindar para proporcionar un mecanismo de seguridad neutral en relacidn con el vendedor y apoyo genkrico de gesti6n de transacciones para rnGltiples gestores de recursos EIS. Esto puede plantear importantes problemas con la irnplementaci6n de EAI. Enfrentindose a estos retos, Sun Microsystems ha lanzado la Arquitectura de Conectores J2EE 1.0 para ofrecer una arquitectura estindar para la integraci6n de servidores J2EE con recursos EIS heterogkneos. Su objetivo principal es sirnplificar el proceso de desarrollo para la integraci6n definiendo un API comlin y un conjunto comGn de servicios dentro de un entorno J2EE consistente. La Arquitectura de Conectores JZEE (JCA) proporciona u n Mcil enfoque para que 10s desarrolladores integren sin fisuras 10s Sistemas de Informaci6n de Empresa (EIS) con componentes de la plataforma JZEE. El siguiente diagrams muestra la nueva cara de un servidor de aplicacidn J2EE 1.3 con componentes JCA y ejernplo de Sistemas de Informaci6n de Ernpresa potenciales: 1 [~ontenedorWeb I ' . -- -' i EIS f - Por lo tanto. si necesitamos intercrar una adicacibn de base T2EE con un EIS existente. s61o necesitamos instalar el conector EIS apropiado (un adaptador de recursos que se ajuste a JCA) en nuestro servidor de aplicaci6n. Con el adaptador instalado, podemos desarrollar componentes J2EE para que actGen de interfaz utilizando el API de la Interfaz Comb de Cliente (CCI), del mismo modo que podemos utilizar JDBC para que actGe de interfaz con bases de datos relacionales. En otras palabras, se sirnplifica el desarrollo con programaci6n no especifica de EIS y con una configuraci6n completamente independiente del EIS en segundo plano. La idea es que todos 10s vendedores de servidores de aplicaci6n irnplementarin eventualmente servicios JCA y 10s vendedores de EIS irnplementarin adaptadores de recursos de EIS que se ajusten a JCA. Apoyando la Arquitectura de Conectores JZEE, se garantiza que todos 10s servidores de aplicaci6n que se adapten a JZEE manejan rndltiples y heterogineos recursos EIS. Asi, J C A fomenta la productividad de 10s desarrolladores de aplicaciones J2EE paralelamente a la reducci6n de costes de desarrollo y la protecci6n de la inversidn existente en sisternas EIS proporcionando una soluci6n de integracidn reajustable a travks de J2EE. Capitulo 20 La Arquitectura de Conectores JZEE y sus elementos JCA es implementado en un servidor de aplicacidn que se ajuste a J2EE 1.3, con un adaptador de recursos JCA proporcionado por un vendedor EIS. Este adaptador de recursos es una componente J2EE conectable, especifico de EIS en el servidor de aplicacidn, que proporciona una interfaz para comunicaciones con el sistema EIS subyacente. Bisicamente, J C A define la siguiente lista de elementos y servicios: 0 Contratos y servicios de nivel de sisterna- Define el estindar entre 10s componentes J2EE, el proveedor del servidor de aplicaci6n y el sistema EIS. Estos contratos y servicios son implementados en el servidor de aplicacidn por el proveedor del servidor y tambiCn en el adaptador de recursos por el vendedor EIS. La implementacidn de contactos y servicios define una separacidn 16gica (no fisica) entre el servidor de aplicacidn y el adaptador de recursos en tirminos de roles y responsabilidades de nivel de sistema. Esto permite la coordinacidn entre el servidor J2EE y a1 adaptador de recursos (por ejemplo, reserva de conexiones, seguridad y transacciones). Ademis, permite que el adaptador de recursos adaptado a JCA sea conectable a cualquier servidor J2EE. 0 La Interfaz C o m u n de Cliente (CCI) JCA- Define un API cliente que utilizan 10s componentes J2EE (como JSP, EJB, etc.) para conectar e interactuar con sistemas EIS. Ademis de 10s componentes cliente J2EE, tambiin permite que las aplicaciones no gestionadas (como applets Java y clientes de aplicaci6n) se integren con un EIS utilizando un adaptador de recursos adaptado a JCA. 0 Interfaces de ernpaquetado y despliegue- Permiten a 10s diversos adaptadores de recursos EIS conectarse a aplicaciones J2EE. El siguiente diagrama ilustra la arquitectura de conectores J2EE y 10s componentes que acceden a recursos EIS: Contrato de Cornponentes de Contenedor bmponentes Gestor de Conexlones Gestor de Transacclones - - Gestor de Segurldad Recursos 1 La arquitectura de conectores J2EE El adaptador de recursos puede percibirse claramente como el componente fundamental del JCA, ya que sirve como conector central entre 10s componentes JZEE, el servidor de aplicaci6n y el sistema EIS. En un sistema de aplicacion J2EE que utiliza JCA, 10s vendedores de EIS proporcionan adaptadores de recursos que se ajustan a JCA con C C I como parte de su implementaci6n. Los vendedores de servidores J2EE proporcionan servidores de aplicaci6n que apoyan contratos de nivel de sistema que capacitan a estos adaptadores de recursos para conectar con 10s servidores de aplicaci6n y proporcionar conectividad con recursos subyacentes EIS. Esto permite a 10s desarrolladores de aplicacibn J2EE desarrollar componentes de integration utilizando CCI. Por lo tanto, pueden mantenerse alejados de 10s mecanismos de conexion, seguridad y transacciones destinados a la conectividad con un EIS o hiiltiples recursos EIS. La especificacion JCA apoya dos tipos de entornos, basados en el tip0 de aplicaci6n cliente que utiliza el adaptador de recursos: 0 Entorno gestionado Define una aplicacidn de base J2EE, con capacidad Web, multi-nivel que accede a EIS. La aplicacion puede contener uno o mis componentes de aplicacidn (por ejemplo, EJB, piginas JSP, servlets), que se implementan en sus respectivos contenedores. En el contexto de JCA, estas aplicaciones son referidas como aplicaciones gestionadas. 0 Entorno n o gestionado La arquitectura de conectores apoya el acceso a EIS desde clientes como applets o aplicaciones cliente de Java. Habitualmente, un cliente de aplicaci6n utiliza directamente una libreria de adaptadores de recursos en una arquitectura de dos gradas. En este caso, el adaptador de recursos proporciona a sus clientes transacciones y seguridad de nivel inferior. En un contexto JCA, estas aplicaciones son referidas como aplicaciones no gestionadas. Analizaremos ambos entornos mis adelante, en este mismo capitulo. Comparacion de JCA con JDBC En general, JCA y JDBC son tecnologias sirnilares con idhticos mecanismos con respecto de la gesti6n de conexiones y transacciones. - Los adaptadores de recursos para sistemas EIS son anilogos a 10s controladores JDBC para bases de datos relacionales. La siguiente tabla presenta una comparaci6n entre JCA y JDBC, y demuestra las similitudes (y diferencias) entre 10s dos: - I JDBC 2.0 JCA 1.0 Definicion Proporciona una interfaz genkrica para interactuar con bases de datos relacionales Proporciona una arquitectura estindar para que J2EE y aplicaciones Java integren e interactiien con recursos EIS API Define un API Java estandar para acceder a bases de datos relacionales Utiliza la Interfaz Comiin de Cliente (CCI) paraproporcionar un API independiente de EIS Conexion Usa controladores JDBC especificos para RDBMS Utiliza un adaptador de recursos EIS para interactuar con un EIS I La tabla continua en la pcigina siguiente Capitulo 20 JDBC 2.0 JCA 1.0 Los servidores J2EE im lementan mecanismos de reserva l e conexiones DBC para crear conexiones a una ase de datos Los servidores J2EE implernentan contratos de servicio JCA para establecer una factoria de conexiones y gestionar conexiones con un EIS Apoya aplicaciones no gestionadas (aplicaciones de dos niveles), que uthzan JDBC Apoya aplicaciones no gestlonadas (aplicaciones de dos niveles), que utilizan C C I Apoyo a la Interfaz de Proveedor de Servicios (SPI) Proporciona apoyo (desde JDBC 3.0) y relacion con SPI JCA JCA define SPI para servicios integradores de servidor de aplicaci6n, como transacciones, conexiones y seguridad Apoyo de transacc16n Apo a transacciones XA y no-XA con ruentes de datos XA rubyacentes Apoya transaccionesXA y no-XA con recursos EIS subyacentes Apoyo JTA Pro orciona una interfaz para el apoyo y JTS a Apoyo a JTA con un contrato entre el estor de transacciones J 1 ~gestor ~ de recursos EIS Implementaci6n de Servidor i PA 5 Asi, desputs de la comparaci6n, la diferencia entre las dos tecnologias esti clara: JDBC proporciona controladores y un API cliente para conexion e integration con aplicaciones de base de datos relacionales, rnientras que JCA proporciona adaptadores de recursos y un API cliente (CCI) para capacitar la integraci6n sin fisuras con recursos EIS. El adaptador de recursos y sus contratos El adaptador de recursos contiene una biblioteca especifica EIS (que puede ser escrita en Java o con componentes nativos de interfaz) que proporciona la conectividad a1 EIS que representa. En el servidor de aplicacion J2EE, el adaptador de recursos se ejecuta en el espacio de direcciones del servidor de la aplicacion y gestiona la conectividad a1 EIS subyacente. JCA requiere que todos 10s adaptadores de recursos EIS y servidores de aplicacion J2EE que se ajusten a JCA apoyen 10s contratos de nivel de sisterna. JCA tambitn recomienda (pero no establece obligatoriamente) que todos 10s adaptadores de recursos apoyen C C I como su API cliente. Esto proporciona una soluci6n basada en J2EE para el desarrollo de aplicaciones que integre multiples EIS y permita esa "conectabilidad de adaptadores de recursos EIS en un servidor de apkaci6n, en colaboraci6n con todos 10s mecanismos de nivel de sistema. Segun la especificaci6n JCA, 10s adaptadores implementan generalmente dos tipos principales de contratos, que analizaremos en las siguientes secciones. En general, un contrato en este context0 es sirnplemente una declaraci6n de responsabilidades entre capas de la aplicaci6n que implementa una interfaz estdndar entre dichaos niveles. Contratos de aplicacion Los contratos de aplicacion definen el API de Interfaz C o m h de Cliente (CCI) a travts del cual un componente cliente J2EE (un EJB o un servlet, por ejemplo) o un cliente no gestionado se comunica con 10s recursos EIS subyacentes. La arquitectura de conectores J2EE Contratos de nivel de sistema Los contratos de nivel de sistema definen un conjunto de contratos de sistema, que permiten a1 adaptador de recursos vincularse a 10s servicios del servidor de aplicaci6n para gestionar las conexiones, las transacciones y la seguridad. La especificaci6n JCA define una serie de contratos de nivel de sistema para que el adaptador de recursos y el servidor de aplicaci6n J2EE 10s implementen. Son analizados detenidamente en las siguientes subsecciones. Gestion de conexiones La gesti6n de conexiones esti representada por un contrato de servicios que permite a1 servidor de aplicacidn ofrecer sus servicios para crear y gestionar reservas de conexiones con el recurso EIS subyacente. Proporciona una funci6n de gesti6n de conexiones reajustable para apoyar un gran numero de clientes. El contrato de gesti6n de conexiones pretende realizar las siguientes funciones: O Establecer una prictica consistente de programacidn de aplicaciones para proporcionar la adquisicidn de conexiones tanto para aplicaciones gestionadas (aplicaci6n J2EE) como para aplicaciones no gestionadas (de dos niveles). o Capacitar a1 adaptador de recursos EIS para proporcionar una factoria de conexiones e interfaces de conexi6n basadas en la C C I especifica para el tip0 de adaptador de recursos y el EIS. O Proporcionar un mecanismo genirico para 10s componentes J2EE gestionados por el que un servidor de aplicaci6n J2EE puede ofrecer servicios como transacciones, seguridad, reserva avanzada, seguimiento/registro de errores, etc. o Proporcionar apoyo para reserva de conexiones. Gestion de transacciones Este contrato amplia la capacidad transaccional del servidor de aplicaci6n a 10s gestores de recursos EIS. En el context0 de JCA, un gestor de recursos EIS gestiona un conjunto de recursos EIS compartidos para participar en transacciones. U n gestor de recursos puede gestionar dos tipos de transacci6n: 0 Transacci6n XA Estas transacciones estin controladas y coordinadas por gestores externos de transacciones. Son compatibles con contratos de gesti6n de transacciones XAResource con un adaptador de recursos que se ajusta a JCA y su gestor subyacente de recursos EIS. Esto tambiin significa que el recurso EIS participante t a m b i h apoya transacciones XA de base JTA implementando un XAResource a travks de su adaptador de recursos. La interfaz JTA XAResource permite a dos gestores de recursos participar en transacciones coordinadas por un gestor externo de transacciones. Esto permite que la transacci6n sea gestionada por un gestor de transacciones externo a1 adaptador de recursos. Cuando un componente de aplicaci6n J2EE demarca una solicitud de conexi6n EIS como parte de una transacci6n, el servidor de la aplicaci6n es responsable de alistar el recurso XA con el gestor de la transacci6n. Cuando el cliente cierra la conexi6n, el servidor de aplicaci6n retira el recurso XA del gestor de transacciones y, una vez que se ha completado la transacci611, limpia la conexi6n EIS. Esto permite a1 componente de empresa participar en situaciones de realizaci6n en dos fases. O Transacci6n local Son transacciones gestionadas internamente, es decir, ningun gestor de transacci6n externo implicado. En este caso, las transacciones son demarcadas por el contenedor del servidor J2EE (gestionado por contenedor) o por el componente J2EE (gestionado por componente). Esto permite a1 servidor de aplicaci6n gestionar recursos locales a la aplicaci6n y a su adaptador de recursos. En las transacciones gestionadas por componentes, 10s componentes J2EE utilizan la interfaz JTA U s e r T r a n s a c t i o n o un API de transacci6n especifico del EIS. Cuando un componente de aplicaci6n solicita una conexi6n EIS, el servidor de aplicacion inicia una transacci6n loca utilizando el contexto de transacci6n disponible en ese momento. Cuando el componente de aplicaci6n cierra la conexihn, el servidor de aplicacion realiza ( o deshace, si es necesario) la transacci6n local y limpia la conexi6n EIS. Estos dos tipos de transacciones permiten a1 gestor de transacciones provisto en el servidor de aplicaci6n gestionar transacciones en mdtiples gestores de recursos EIS. Gestion de seguridad Este servicio permite al desarrollador definir la seguridad entre el servidor de aplicaci6n y el recurso EIS. Hay una variedad de mecanismos utilizados para proteger un EIS contra accesos no autorizados y otras amenazas de seguridad, que incluyen: 0 Identification de usuario, autentificacibn y autorizaci6n. 0 Comunicaci6n segura entre el servidor de aplicaci6n y el recurso EIS, utilizando protocolos de seguridad de comunicaci6n de red abierta como Kerberos, que proporcionan seguridad de extremo a extremo con servicios de autentificaci6n y confidencialidad. 0 Activar mecanismos de seguridad especificos de EIS. Fundamentalmente, el contrato de seguridad entre el servidor J2EE y el adaptador de recursos EIS amplia el contrato de gesti6n de conexiones junto con la seguridad. Este contrato de seguridad proporciona el siguiente mecanismo EIS de acceso: 0 Pasar la solicitud de conexi6n desde el adaptador de recursos al servidor de aplicaci6n J2EE y capacitar a1 servidor con sus servicios de autentificacidn y autorizaci6n. 0 Propagar el contexto de seguridad con credenciales de seguridad desde el servidor de aplicaci6n a1 adaptador de recursos. Acceso a EIS En una nueva conexi6n a EIS, crear una conexi6n a EIS crea normalmente un proceso de acceso. Esti basado en el contexto de seguridad, que crea un proceso de autentificacion y autorizaci6n para que un usuario obtenga las reglas de acceso. En cualquier caso, si cambia el contexto de seguridad, se requiere reautentificaci6n para la conexi6n. U n acceso a EIS requiere uno o mis de 10s siguientes pasos: 0 Determinar el principal del recurso (identidad del oyente iniciador) bajo cuyo contexto de seguridad se estableceri una nueva conexi6n a un EIS. 0 Autentificar el principal de 10s recursos si la conexi6n a h no esti autentificada. 0 Establecer una asociaci6n segura entre el servidor de aplicaci6n y el EIS. T a m b i h pueden desplegarse mecanismos adicionales como SSL o Kerberos. 0 Controlar el acceso a recursos EIS. Una vez se ha establecido una asociaci6n segura, la conexi6n se asocia al contexto de seguridad del usuario iniciador. Posteriormente, todas las invocaciones de nivel de aplicaci6n a la instancia EIS que utilicen la conexi6n tiene lugar en el contexto de seguridad de ese usuario. JCA recomienda que 10s vendedores de servidores J2EE proporcionen y sean compatibles con el acceso gestionado por contenedor para aplicaciones J2EE gestionadas y acceso gestionado por aplicaci6n para aplicaciones n o gestionadas. Definamos estas dos tkcnicas de acceso: La arquitectura de conectores J2EE 0 Acceso gestionado por aplicaci6n El componente cliente proporciona las credenciales de seguridad (habitualmente, nombre de usuario y contrasefia) mientras obtiene una conexion a un EIS. Acceso gestionado por contenedor El componente de cliente J2EE n o presenta ninguna credencial de seguridad y es responsabilidad del contenedor J2EE encontrar las credenciales necesarias de acceso y proporcionarles el adaptador de recursos mientras solicita una conexion a un EIS. En esta situaci6n, el contenedor debe encontrar el principal de recurso (identidad del llamante iniciado) y proporcionar informaci6n sobre este principal de recurso a1 adaptador de recurso en forma de tema de Servicio de Autentificacion y Autorizaci6n Java (JAAS). Empaquetado e implernentacion de un adaptador de recursos JCA define 1as interfaces de empaquetado e implementaci6n, de modo que varios adaptadores de recursos pueden conectar ficilmente con un servidor de aplicacion J2EE adaptado de un mod0 modular y portitil. Esto se conoce como modulo de adaptador de Recursos ( . r a r ) y es similar a un m6dulo de aplicaci6n J2EE (. e a r ) , que puede incluir componentes Web y EJB. El siguiente diagrams ilustra 10s pasos del proceso de empaquetado e implementaci6n de un modulo de adaptador de recursos destinado a conectar una aplicaci6n J2EE con un recurso EIS. Habitualmente, este proceso es muy similar a la implementacidn de componentes EJB y Web en un contenedor J2EE. I 1 -Adaptador de Recurso Adaptador de Recutso Recursos b -, Ernpaquetado Procedente de Modulo de Procedente del lncluir M6dulos J2EE Servidor de Aplicacion J2EE Contenedor Adaptador de - - -- - - Conf~gurac~on del Entorno Procedente del Desplegador _ __ / I- 1 Adaptador de Recursos Especif~co de EIS Asi, el proceso de empaquetado e implementaci6n de un m6dulo de recursos es el siguiente: 0 El proveedor del adaptador de recursos EIS (normalmente, el vendedor de EIS) desarrolla un conjunto de interfaces y clases de utilidad Java como parte de la implernentaci6n del adaptador de Capitulo 20 recursos. Estas clases Java implementan 10s contratos JCA y la funcionalidad especifica de EIS proporcionada por el adaptador de recursos. 0 Las clases y bibliotecas nativas Java (si estin disponibles) proporcionadas por el proveedor del adaptador de recursos son empaquetadas, junto con un descriptor de implementaci6n, para construir un m6dulo de adaptador de recursos (archivo RAR). Similar a otros descriptores de implementaci6n del componente J2EE, el descriptor del m6dulo del adaptador de recursos define 10s atributos de contrato de servicio entre el proveedor del adaptador de recursos y un implementador para un adaptador de recursos. 0 Durante la implementaci6n, el implementador de la aplicacidn instala un m6dulo del adaptador de recursos en un servidor de aplicaci6n y despuks lo configura con el servidor de aplicaciones J2EE y el entorno subyacente EIS de destino. Como hemos mencionado anteriormente, el proceso de empaquetado e implementaci6n de un m6dulo de adaptador de recursos para una aplicaci6n es similar a otros procesos de empaquetado e implementaci6n JZEE, especialmente para componentes Web y EJB. Sin embargo, 10s roles y las responsabilidades implicadas en el empaquetado e implementaci6n de un adaptador de recursos son ligeramente diferentes comparadas con otros componentes J2EE. Empaquetar un adaptador de recursos U n adaptador de recursos EIS es un componente de servidor J2EE contenido en un archivo RAR. Puede hospedar uno o mis adaptadores de recursos en un directorio y empaquetarlos como archivos . r a r . La siguiente lista de tareas indica la secuencia habitual que conlleva empaquetar un adaptador de recursos: I. Crear un directorio de hospedaje temporal. 2. Compilar o copiar las clases Java de adaptador de recursos en el directorio de hospedaje. 3. Crear un archivo .r a r para almacenar las clases Java del adaptador de recursos y afiadir este archivo j a r a1 nivel superior del directorio de hospedaje. . 4. Crear un s u b d i r e c t o r i o M E ~ ~INF - en el directorio de hospedaje. 5. Crear un archivo de descriptor de implementaci6n r a .xml en el s u b d i r e c t o r i o ~ INF ~ ~ ~y- afiada entradas para el adaptador de recursos. 6. Crear un descriptor de implementaci6n especifico del vendedor J2EE en el s u b d i r e c t o r i o ~ ~ ~ ~ INF y afiada entradas para el adaptador de recursos. 7. Cuando todas las clases y descriptores de implementaci6n del adaptador de recursos se hacen disponibles en el directorio de hospedaje, puede crear el archivo . r a r del m6dulo del adaptador de recursos con un comando j a r , como kste: jar c v f wroxResourceAdapter. rar -C staging-dir . Finalmente, podemos implementar este archivo .rar en cualquier servidor J2EE que se ajuste a JCA o empaquetarlo en un archivo . j a r de aplicaci6n. Observe que la opci6n - C s t a g i n g d i r define el comando j a r para cambiar el directorio s t a g i n g - d i r de mod0 que las rutas de directorio definidas en el archivo rar sean relativas a1 directorio donde ha hospedado 10s adaptadores de recursos. U n mddulo de adaptador de recursos empaquetado define el contrato entre un proveedor y un ' implementador de adaptador de recursos EIS, e incluye 10s siguientes elementos: La arquitectura de conectores J2EE O Las clases e interfaces Java requeridas para la implementaci6n de 10s contratos de arquitectura de conectores y de la funcionalidad del adaptador de recursos. o Las clases de utilidad Java para el adaptador de recursos. O Librerias nativas dependientes de la plataforma requeridas por el adaptador de recursos O Archivos de ayuda y documentaci6n. Meta-informaci6n descriptiva que vincula a 10s elementos anteriores. El proceso de implementacidn empieza con el archivo .rar o con un directorio de implementaci6n, ambos contienen las interfaces y las clases de implementaci6n del adaptador de recursos compiladas proporcionadas por el proveedor del adaptador de recursos. Los adaptadores de recursos en una entorno J2EE utilizan un formato comb de directorio. U n adaptador de recursos esti estructurado en un directorio como se muestra en el siguiente ejemplo: \J2EEserverHome \config \wroxdnrns i n \applicstioris \wroxResourceAdapter \imaqrs \ra. jpg \ rsadrnz. htrnl \els .jar \utilities. j ar \windos.dl; \solaris. s n \META-INF \ r a .xml \XYZServerFrnvider-ra. xrnl Este mismo formato puede utilizarse a1 empaquetar un adaptador de recursos como archivo . rar. Despues de crear un archivo .rar,su instalacion de servidor J2EE queda asi: En la estructura anterior, ra .xml es el descriptor de despliegue para el adaptador de recursos. XZYServerProvider- ra .xml es el descriptor de despliegue delvendedor J2EE, que definelos parimetros operativos exclusivos del proveedor del servidor. Examinaremos mis detalladamente el descriptor en la pr6xima secci6n. ei s . ja r y utilities .j ar contienen interfaces y clases de implementaci6n Java del adaptador de recursos EIS. Los archivos windos .dl1 y solaris. s o son ejemplos de librerias nativas. El descriptor de implernentacion del adaptador de recursos (ra .xml) Similar a otras aplicaciones J2EE, 10s adaptadores de recursos EIS tambien utilizan descriptores para definir el contrato entre un proveedor de adaptador de recursos EIS y un implementador de este entorno. ~ s t o proporcionan s 10s atributos destinados a que el implementador permita la implementaci6n de un adaptador de recursos EIS en su entorno. El vendedor J2EE tambien requiere un descriptor adicional, que defina 10s parametros operativos exclusivos del proveedor del servidor. Capitulo 20 U n modulo de adaptador de recursos tambiCn inchye 10s requisitos de implementacion especificados por el proveedor del adaptador de recursos en el descriptor. Para configurar las propiedades de implementacion necesarias para el adaptador de recursos, es necesario editar el archivo r a . xml empaquetado con un adaptador de recursos. La definition del tip0 de documento XML del descriptor para un modulo de adaptador de recursos esta disponible en http://java.sun.com/dtd/connector~l~O.dtd. El proveedor de adaptador de recursos es responsable de proporcionar el descriptor de implementaci6n para un adaptador de recursos especifico de EIS. C o m o sucede con JCA 1.0, la siguiente informacion esta disponible en un descriptor provisto por un proveedor de adaptador de recursos EIS: 0 Informaci6n general sobre un adaptador de recursos. Como vemos en el siguiente extract0 de codigo, esta informacion puede incluir detalles como el nombre del adaptador de recursos, el nombre del vendedor que proporcionar el adaptador de recursos, el tip0 de sistema EIS en que se basa, la version del JCA en que se basa, etc. Por ejemplo: 0 La c l a s e ~ a n a ~ e d ~ o n n e c t i o n ~ a el c tproveedor or~; del adaptador de recursos especifica el nombre cualificado completo de la clase Java que implementa la interfaz javax.resource.spi.ManagedConnectionFactory.~ore~emplo: a La interfaz y clase de i m p ~ e m e n t a c i o n ~ o n n e c t i o n ~ a c t oelr yproveedor ; del adaptador de recursos especifica el nombre cualificado complete de la interfaz y clase de implementaci6n Java para la factoria de conexiones. Por ejemplo: ]avax.sql.DataSource corn. sun. connector. blackbox. JdbcDataSource a Clase de implementacion de la conexion; el proveedor del adaptador de recursos especifica el nombre completo cualificado de la clase de implementaci6n para la interfaz de conexion: U Apoyo transaccional; el proveedor del adaptador de recursos especifica el nivel de compatibilidad de transaccion proporcionado por la implementaci6n del adaptador de recursos. El nivel de compatibilidad transaccional es normalmente uno de 10s siguientes: N o T r a n s a c t i o n , LocalTransactionoXATransaction.~orejemplo: Propiedades configurables de l a i n s t a n c i a ~ a n a ~ e d ~ o n n e c t i o n ~ a c teloproveedor r~; del adaptador de recursos define nombre, tipo, description y valores predeterminados opcionales para las propiedades que han sido configuradas para cada instancia d e ~ a n a g e d ~ o n n ei cot n ~ a cotr y La arquitectura de conectores J2EE (observe que estamos utilizando la base de datos por defect0 Cloudscape, C l o u d s c a p e D B , en este ejemplo): Mecanismo de autentificacion; el proveedor del adaptador de recursos especifica todos 10s mecanismos de autentificacion apoyados por el adaptador de recursos. Incluye el apoyo proporcionado por la implementacion del adaptador de recursos pero no la instancia subyacente EIS. Los valores estindar son B a s i c P a s s w o r d y Kerbv5, por ejemplo: BasicPassword javax.resource.security.PasswordCreder~tia1 0 Apoyo de reautentificacion; el proveedor del adaptador de recursos especifica si su adaptador de ' recursos apoya la reautentificacion de una conexion existente: El siguiente ejemplo ilustra un descriptor de implementacion completo para un adaptador de recursos de caja negra, sin apoyo de transacci6n (incluido en el archivo . r a r ) : < ! DOCTYPE cor~nector PUBLIC '-//Sun Microsystems, Inc. //DTD Connector 1.0/ /EN' 'http: //j ava. s u n . corn/ j2ee/dtds/connector 1 O . d t d l > com. sun. connector. blackbox . N o T x M a r ~ a g e d C o r ~ r ~ e c t i o r ~ F a c t o r y javax.sql.DataSource com.sun.cor~r~ector.blackbox.JdbcDataSource j ava. sql . C o n r ~ e c t i o r ~ < / c o n r i e c t i o r ~ - i n t e r f a c e > com. sun. connector. blackbox. JdbcConnection N~Tra~i~a~tior~ con fig-property> Capitulo 20 Connect ionURL j ava. lar~q. Strlnq jdbc:cloudscape:rmi:CloudscapeDB;create=true BasicPasswqrd javax.resource.security.PasswordCredentia1 fa1se Roles y responsabilidades de la irnplementacion Los roles y responsabilidades especificas de la implementaci6n son 10s siguientes: Proveedor del adaptador de recursos El proveedor del adaptador de recursos, como el nombre sugiere, es responsable de proporcionar un adaptador de recursos para un EIS. U n vendedor EIS o su vendedor de terceros proporciona habitualmente el adaptador de recursos y su sistema de herramientas de implementaci6n de la aplicaci6n. T a m b i h es responsable de especificar el descriptor para su adaptador de recursos, que incluye: 0 Informacidn general: detalles generales del adaptador de recursos (nombre, descripci6n, nombre de vendedor, licencia, apoyo EIS, version, etc.). 0 La c l a s e ~ a n a g e d ~ o n n eicot n ~ a cotr y : especifica el nombre cualificado completo de la clase Javaque implementalainterfaz ja v a x .r e s o u r c e . s p i . M a n a g e d C o n n e c t i o n F a c t o r y . 0 La interfaz y clase de i m p l e m e n t a c i 6 n ~ o n n e c t i o n ~ a c t o respecifica y: el nombre completo cualificado de la interfaz y clase de implementacion Java para la factoria de conexiones. ad especifica el nivel de apoyo de transacci6n proporcionado por la o C ~ m ~ a t i b i l i d transaccional: implementaci6n del adaptador de recursos ( N o T r a n s a c t i o n , L o c a l T r a n s a c t i o n o XATransaction). 0 Mecanismo de autentificacibn: especifica 10s mecanismos de autentificaci6n en 10s que se basa el adaptador de recursos. Incluye el apoyo d e ~ a s i c ~ u t h e n t i c a t i yo Kn e r b e r o s v5. Vendedor del sewidor de aplicacion El vendedor del servidor de aplicaci6n proporciona la implementaci6n JCA en su servidor de aplicaci6n J2EE, que apoya las aplicaciones basadas en componentes JCA. T a m b i h se conoce como proveedor del contenedor, aisla 10s componentes de aplicaci6n J2EE de 10s servicios de nivel de sistema subyacentes. Proveedor del componente de aplicacion El proveedor del componente de aplicaci6n desarrolla el componente de aplicaci6n J2EE que interactlia con 10s EIS para proporcionar funcionalidad a la aplicaci6n. El proveedor desarrolla programas utilizando La arquitectura de conectores J2EE la CCI, pero no programa especificamente las transacciones, la seguridad, la concurrencia y la distribution. En su lugar, utiliza el sewidor J2EE para proveer estos sewicios. lnplementador El implementador es responsable de configurar un adaptador de recursos en el entorno J2EE de destino. La configuraci6n de un adaptador de recursos esti basada en 10s atributos definidos en el descriptor de implementaci6n como parte del modulo del adaptador que incluye las siguientes tareas: O Configurar la propiedad establecida porManagedConnectionFactory para crear conexiones a varias instancias EIS subyacentes. O Configurar el senidor de aplicacion para la gestion de transacciones basindose en el nivel de compatibilidad de transaction especificado por el adaptador de recursos. O Configurar la seguridad en el entorno operativo basindose en 10s requisitos de seguridad especificados por el adaptador de recursos en su descriptor de implementacion. Opciones de implementacion U n adaptador de recursos puede implementarse de las siguientes formas en una Implementaci6n de Referencia JZEE: O Dinimicamente, utilizando la linea de comando deploytool (o la consola U I de la herramienta de implementaci6n), por ejemplo: deploytool -deployConnector %J2EE~HOME%\lib\connector\blackbox-tx.rar localhost O C o m o parte de una Aplicaci6n de Empresa JZEE, implementindolo como un fichero de archivo llamado .ear. Analizaremos mis detenidamente esta opci6n en la siguiente seccibn. lmplementar un adaptador de recursos como una aplicaci6n J2EE Como hemos visto, J C A tambikn especifica la posibilidad de i n c h un archivo de fichero ( .rar) del adaptador de recursos en un archivo de la aplicaci6n de empresa ( .ear) e implementar despuks la aplicacion en un sewidor JZEE. Las siguientes tareas estin implicadas en la implementacidn de una aplicacion J2EE que contiene un archivo del adaptador de recursos: O Incluir el archivo . rar en el fichero . ear igual que incluiria un archivo .war (componente Web) o .j ar (componente EJB). O Crear un archivo vilido application. xml y situarlo en el directorio META-INF del fichero .ear. Al crear un appl icat ion. xml,asegurese de que el descriptor de implementaci6n de la aplicaci6n contiene un nuevo elemento para identificar el archivo del adaptador de recursos en el fichero .ear. Por ejemplo: Hasta el momento, hemos analizado 10s adaptadores de recursos, 10s contratos de adaptadores de recursos y 10s procedimientos de empaquetado e implementaci6n de un adaptador de recursos. Demostremos ahora la configuraci6n e implementaci6n de un adaptador de recursos utilizando 10s adaptadores de recursos de caja negra provistos por la implementaci6n de referencia J2EE 1.3 de Sun. Capitulo 20 En el momento de publicacio'n de este libro, 10s adaptadores de recursos EIS apenas estaban disponibles ni siquiera corno una implementacio'n beta. Por ello, en nuestros ejemplos, estamos utilizando 10s adaptadores de recursos de caja negra provistos en la Implementacio'n de Referencia JZEE, que estdn destinados a poner a prueba el proceso de empaquetado e implementacio'n y la C C I . Los adaptadores de caja negra no estdn diseriados para aplicaciones de produccidn. Adaptadores de recursos de caja negra Los adaptadores de caja negra son iguales que 10s adaptadores de recursos EIS per0 utilizan una base de datos relational corno EIS subyacente y estin diseriados hicamente para fines de prueba. Sin embargo, son ideales para el prop6sito de nuestras sencillas dernostraciones. Los adaptadores de recursos de caja negra se utilizan principalmente para probar la conectividad de extremo a extremo con un servidor de aplicaci6n J2EE adaptado a JCA y su compatibilidad J2EE segGn la especificacion JCA 1.0. en esta seccibn, exarninaremos el uso de 10s adaptadores de recursos de caja negra integrados en la Implernentaci6n de Referencia J2EE 1.3 de Sun. Estas cajas negras utilizan llarnadas JDBC para interactuar con un DBMS. Los adaptadores de recursos de caja negra no estiin destinados a sustituir a JDBC; simplemente proporcionan un sencillo entorno sirnulado con fines de prueba unicamente. Los ejernplos que analizarernos en este capitulo utilizan el servidor de la Irnplernentacion de Referencia J2EE 1.3 y Cloudscape corno base de datos. Utilizar un adaptador de caja negra. El ejemplo DemoConnector DemoConnector es un ejemplo que rnuestra un adaptador de recursos de caja negra accediendo a una base de datos Cloudscape utilizando JDBC. El ejemplo es una entidad EJB que realiza transacciones utilizando el adaptador de caja negra configurado con una base de datos y presenta la salida. Analizarernos el ejernplo Democonnector en el siguiente orden: 0 Selecci6n de un adaptador de caja negra y el nivel de transacci6n de la Irnplementaci6n de Referencia J2EE O Configuraci6n e implernentaci6n del adaptador de caja n e g a a Prueba del adaptador de caja negra en una transacci6n utilizando un bean de entidad Seleccionar un adaptador de caja negra Examinernos 10s adaptadores de caja negra disponibles en la Irnplernentaci6n de Referencia J2EE 1.3. prirnero, debemos asegurarnos que nuestra instalacidn incluye adaptadores de recursos de caja negra. Norrnalrnente, estin localizados en el directorio % J2EE-HOME% \lib\connector \. Debernos tener cinco adaptadores de recursos de caja negra (identificados por su extensi6n .rar) para apoyar diferentes niveles de transacci6n, corno hernos visto anteriorrnente, en la secci6n sobre gesti6n de transacciones de adaptadores de recursos. Estos adaptadores estin descritos en la siguiente tabla: La arquitectura de conectores J2EE Adaptador de recursos de caja negra Descripci6n 1 blackbox-notx. r a r Para apoyarNO-TRANSACT I O N ( blackbox-xa. r a r I b l a c k b o x - t x .r a r Para apoyarLOCAL-TRANSACT I O N Para apoyarXA-TRANSACT I O N Implementado con C C I para apoyar LOCAL-TF7ANSACTION Implementado con C C I para apoyar XA-TRANSACTION En nuestro ejemplo, utilizaremos el adaptador de recursos b l a c k b o x - t x . r a r para demostrar el uso de transacciones locales. Transaccioner XA y no-XA que utilizan un adaptador de caja negra Todos 10s adaptadores de recursos de caja negra requieren un URL para crear factorias de conexiones con EIS subyacentes. Estos adaptadores de recursos de caja negra utilizan generalmente drivers JDBC para conectar con la base de datos. Para recursos transaccionales no-XA, es necesario que configuremos la propiedad c o n n e c t i onURL, mientras que para recursos XA, es necesario configurar la propiedad XADataSource. En este ejemplo, utilizaremos el sewidor de la base de datos Cloudscape en la Implementacidn de Referencia J2EE; 10s valores por defect0 proporcionados en el descriptor de implementacibn de un adaptador de caja negra son 10s siguientes: 0 Para adaptadores de caja negra no-XA (que utilizan niveles de transaccibn no-XA): O Para adaptadores de caja negra XA (que utilizan niveles de transaccihn XA): XADataSource = jdbc/XACloudscape-xa Implementation del adaptador de recursos de caja negra Para configurar e implementar un adaptador de recursos de caja negra, siga estos pasos: O Configurar su base de datos y drivers JDBC, y crear sus tablas especificas de aplicacibn 0 Implementar su mbdulo empaquetado de adaptador de recursos de caja negra Configurar la base de d a t a y la tabla Demoaccount Para implementar y poner a prueba el adaptador de recursos de caja negra mencionado anteriormente, utilizaremos la base de datos Cloudscape de la Implementacibn de Referencia J2EE 1.3. Para crear la tabla, inicie el sistema Cloudscape (con el c o m a n d o ~ l o u d s c a p e - s t a r tdesde el directorio %J2EE-HOME%\ b i n ) y ejecute entonces el siguiente SQL: CREATE TABLE demoaccount ( ); accountid VARCHAR(3) CONSTRAINT Demoaccount pk PRIMARY KEY, firstname VARCHAR(25), lastname VARCHAR(251, balance DECIMAL(12,2) Capitulo 20 Puede ejecutar este S Q L utilizando C l o u d v i m o guardar el SQL en un archivo de texto y ejecutarlo desde la invitacidn a mandato con c l o u d s c a p e - i s 9 1 c r e a te-demoa c c o u n t - t a b l e . sql Ya estamos preparados con la configuraci6n de la base de datos. Implementation del adaptador de recurooo Primero necesitamos iniciar el senidor JZEE, utilizando j 2 e e -verbose, con el que seguro ya esti familiarizado. Una vez se esti ejecutando el senidor, podemos implementar el adaptador de caja negra utilizando la herramienta de implementaci6n. Primero crearemos una nueva aplicacidn para nuestro I Application File N a n : c:\WroxZProJavaSe1venCh20\81ackbo~BIackbo~.ear ( 1 ~rowse,. I I ApplicationDisplayName: I QK II cancel II ... I Help Seleccione entonces Add to (Agregar a) I Resource-adapter RAR (Adaptador de recursos RAR) del men6 File (Archivo): La arquitectura de conectores J2EE Ile NamP [email protected]~Ch?bRlachboylB!~chbOx ear Appllcmort DISIIIW Name: - I Coraenls: MNIFEST MF ~ppltcallonxml M-12ee-n xml Desde el cuadro de diilogo abierto, navegue hasta donde e s t i n localizados 10s archivos RAR ( B J 2 E E-H O M E # \ l i b \ c o n n e c t o r ) y seleccioneel a r c h i v o b l a c k b o x - t x . r a r , y aiiidaloa la aplicaci6n: file Help *IS iampGqm p1ppqEqF --F l J fl'Ej@1-p J -- - 9 UFIIP; Q flApplications 9 0 Blackbox ~ ~ S ~ J P C I I ~ ~ A Fj ) Ip~l ~Pl rSl ~ o ~Filackbox ?b AlackRo~Lo nlTx ~ 1 1 6 &¶l~ flw--~ + I GF*~ ) fi BIackBowLocalTx 9 @ Sewers f l localhost Managed Cnclnscllon raclory. I ... Version ~ m m a t m Puede ver en el cuadro de didogo General que la factoria de conexi6n para este adaptador de recursos es, de hecho,simplementeun j avax. sql .Datasource. Para desplegar el adaptador, seleccione la aplicaci6n Blackbox y utilice la opcion Deploy (Implementar) del mend Tools (Herramientas): La arquitectura de conectores J2EE contacted sewer ... Application Blackbox transferred Blackbox has 0 ejbs, 0 web componenls lo deploy Deploying Ejbs .. Processing beans ... Making client JARS Makinp sewer JARS ... Deployment of Blackbox is complete. ... Amplie el n o d o Servers (Servidores) de m o d 0 que pueda ver el servidor adjunto de la Implementaci6n de Referencia; selecci6nelo. En la ventana de la parte derecha cambie a1 panel Resource-adapters: Pulse el b o t h New (Nuevo) para afiadir una nueva factoria de conexi6n. Verl que el adaptador b l a c k b o x - t x . r a r ya estl seleccionado; lo 6nico que tenemos que aiiadir es el JNDl Name ( e i s / WroxEIS, en este caso): omection Factow JNDl Name: I Configur&ion Properties I I Recovery Settings -User Name: - I 1 Observe que la propiedad ConnectionURL estd apuntando a una base de datos Cloudscape. Obviamente, el valor de esta propiedad necesitaria ser modificado si utilizamos una base de datos diferente. Pulse el bot6n OK (Aceptar) y, si todo ha funcionado, obtendrl una invitaci6n de confirmaci6n: El panel Resource-adaptersdebe aparecer ask lo66 La arquitectura de conectores J2EE Ya estamos preparados para crear el bean de entidad y poner a prueba este adaptador. Poner a prueba el adaptador de recursos de caja negra El ejemplo Democonnector es un bean de entidad y sencillo cliente que utiliza el adaptador de recursos de caja negra para tramitar con una base de datos Cloudscape. Presentaremos ahora el c6digo fuente para el EJB. Observe que todo el cddigo fuente para 10s ejemplos que se muestra en este capitulo (y el resto de ejemplos de este libro) estrin disponibles para su descarga en http://www.wrox.coml import import import java.uti1 .Collection; java.rmi.RemoteException; javax.ejb.*; p u b l i c i n t e r f a c e DemoAccountHorne e x t e n d s E J B H o m e public DemoAccount c r e a t e ( S t r i n g accountid, S t r i n g firstName, String lastNarne, double balance) t h r o w s RemoteException, CreateException; public DemoAccount findByPrimaryKey(String accountid) Capitulo 20 throws FinderException, RemoteException; public Collection findByLastName(String lastNarne) throws FinderException, RemoteException; public Collection findInRange(doub1e low, double high) throws FinderException, RemoteException; La interfaz remota import j avax .ejb. EJBObject; i m p o r t java.rmi.RemoteException; public interface DemoAccount extends EJBObject ( public void debit (double amount) throws ProcessingException, RemoteException; public void creditidouble amount) throws RemoteException; public String getFirstName ( ) throws RemoteException; public String g e t L a s t N a m e 0 throws RemoteException; public d o u b l e getBalance ( ) throws RemoteException; 1 La clase de implementaci6ndel bean import import import import import java. sql. + ; javax. sql. + ; java.util.*; j avax. e j b . + ; j avax. naming. + ; public class DemoAccountBean implements EntityBean private private private private private private private { String accountid; String firstName; String lastName; double balance; EntityContext context; Connection con; String elsName = "java:comp/env/eis/WroxEIS"; public void debit (double amount) throws ProcessingException 1 if (balance - amount < 0) { throw n e w ProcessingException ( ) ; 1 balance -= amount; \ public void credit(doub1e amount) { balance += amount; ) public String g e t F i r s t N a m e 0 return firstName; { I public String g e t L a s t N a m e 0 return 1astName; I public double getRalance() ( return balance; 1 { La arquitectura de conectores J2EE public Strir~g ejbCreate(Strir1g accountid, String firstName, String lastName, double balance) throws CreateException { if (balance < 0.00) [ throw n e w CreateException ("Negative balance not permitted. " ) ; I try { insertRow(accountid, firstName, lastName, b a l a n c e ) ; ) catch (Exception e x ) { t h r o w n e w EJBException ("ejbCreate: " t ex.getMessage ( ) ) ; 1 I this. accountid = accountid; this.firstName = firstName; this.lastName = lastNarne; this.balance = balance; return accountid; I public String ejbFindByPrimaryKeyiString prirnaryKey) throws FinderException { boolean result; try 1 result = selectByPrimaryKey(primaryKey); 1 catch (Exception e x ) { t h r o w n e w EJBExceptior~("ejbFindByPrimaryKey: " t ex.getMessage()); \ if ] (result) { return primaryKey; else [ t h r o w n e w ObjectNotFoundException("Account Id " t primaryKey " not found. " ) ; i 1 public Collection ejbFindByLastName(String lastName) throws FinderException { C o l l e c t i o n result; try 1 result = selectByLastName(1astName); ] catch (Exception e x ) { t h r o w n e w EJBException ( " e jbFindByLastNarne " + ex. getMessage ( ) ) ; I return result; I publlc Collection ejbFindInRange(doub1e low, double high) throws FinderExceptior~ { C o l l e c t i o n result; try I result = selectInKange ( l o w , high) ; I catch (Exception ex) { t h r o w n e w EJBException ( "ejbFindIr1Range: " t ex. getMessage ( I return result; \ public void e j b R e m o v e 0 { try 1 deleteRow(accountid); ) catch (Exception ex) 1 t h r o w n e w EJBException ("ejbRemove: " t ex. getMessage ( ) ) ; ) ) ; Capitulo 20 public void setEntityContext(EntityContext context) [ this. context = context; try I makeConnection0; 1 catch (Exception ex) I throw new EJBException("database failure " + ex.getMessage()); 1 \ public void unsetEntityContext() I try I con. close ( ) ; ) catch (SQLException e x ) I throw new E J B E x c e p t i o n ( " u n s e t E n t i t y C o n t e x t : " + ex.getMessage()); 1 public void ejbActivate ( ) [ accountid = (String)context .getPrimaryKey( ) ; 1 public void ejbpassivate ( ) accountid = null; I public void e j b L o a d 0 I try I loadRow( ) ; ) catch (Exception ex) I throw new EJBException("ejbLoad: " ex.getMessage0 ) ; + I public void ejbStore0 try I I storeRow( ) ; ) catch (Exception ex) i throw new EJBException ("ejbStore: ex.getMessage0 1; " + 1 public void ejbPostCreate(String accountid, String firstNarne, String lastNarne, double balance) I ) private void makeconnection() throws Narnir~gException, SQLException InitialContext ic = new Initialcontext ( ) ; DataSource ds = (DataSource) ic.lookup(eisNarne); corl = ds. getconnection ( ) ; ) private void insertRow (String accountid, String firstNarne, String lastNarne, double balance) throws SQLException I String insertstatement = I La arquitectura de conectores J2EE "INSERT INTO demoaccount VALUES ( ? , ? PreparedStatement prepStmt = con.prepareStatement(ir1sertStatement); prepstmt. setString (1, prepStmt. setstring (2, prepStmt.setStringi3, prepStmt.setDouble(4, , ? , ? accountid) ; f irstName) ; 1astName); balance); private void deleteRow(String accountid) throws SQLException String deletestatement = "DELETE FROM demoaccount WHERE accountid PreparedStatement prepStmt = con.prepareStatement(de1eteStatement); private boolean selectByPrimaryKeyiString throws SQLException { = ? primaryKey) String selectStatement = "SELECT accountid " t "FROM demoaccount WHERE accountid = ? "; PreparedStatement prepStmt = con.prepareStatement(se1ectStatement); prepStmt.setString(1, primaryKey); ResultSet rs = prepStmt.executeQuery(); boolean result = rs.next ( ) ; prepStmt.close(); return result; private Collection selectByLastName(String throws SQLException { lastName) String selectstatement = "SELECT accountid " + "FROM demoaccount WHERE lastname = ? "; PreparedStatement prepstint = con.prepareStatement(se1ectStatement); prepStmt.setString(1, lastName); ResultSet rs = prepStmt . executeQuery ( ArrayList a1 = new ArrayList( ) ; ) ; while (rs.next ( 1 ) [ String accountid = rs.getString(1); al. add ( accountid) ; 1 prepStmt . close ( return al; } ) ; )"; "; { private Collection selectInRange(doub1e throws SQLException { low, double high) String selectstatement = "SELECT accountid FROM demoaccount " t "WHERE balance BETWEEN ? and ? " ; PreparedStatement prepStmt = con.prepareStatement(se1ectStatement); prepStmt.setDouble(1, low); prepStmt.setDouble(2, high); ResultSet rs = prepStmt.executeQuery(); ArrayList a1 = new ArrayList ( ) ; while (rs.next()) [ String accountid = rs.getString(1); al.add(accountid); I prepStmt.close0; return al; I private void loadRow( ) throws SQLException { String selectstatement = "SELECT firstname, lastname, balance " t "FROM demoaccount WHERE accountid = ? " ; PreparedStatement prepStmt = con.prepareStatement(se1ectStatement); ResultSet rs = prepStmt.executeQuery0; if (rs.next()) { this.firstName = rs.getString(1); this. lastName = rs.getStrinq(2) ; this.balance = rs.getDouble(3); prepStrnt.close(); I else I prepstmt. close ( ) ; throw new NoSuchEntityException("Account " " not found"); t + accountid t I private void storeRow() throws SQLException { String updatestatement = "UPDATE demoaccount SET firstname = . "lastname = ? , balance = ? " t "WHERE accountid = ?"; PreparedStatement prepStmt = con.prepareStatement(updateStaternent); prepStmt.setString(1, prepStrnt.setString(2, prepStmt.setDouble(3, prepStmt.setString(4, firstName); 1astName); balance); accountid); ? ," + La arquitectura de conectores J2EE int rowCount = prepstrnt. executeupdate prepStrnt.close0; ( ) ; if (rowcount == 0 ) [ throw new EJBException("Account update" + accountid + " failed."); I I public class Processir~gException extends Exception public ProcessingException ( ) [ [ 1 public ProcessingException (String rnsg ) superirnsg); [ I El dercriptor de implementation EJB < ! DOCTYPE ejb-j ar PUBLIC '-//Sun Microsysterns, Inc. //DTD Enterprise JavaBeans 2.0//EN1 'http://java.sun.corn/dtd/ejb-jar 2 O.dtdl> lmplementacion del bean Compile 10s diversos archivos j ava y Cree el archivo JAR EJB. Despuks, con nuestra apkaci6n Blackbox seleccionada en la herrarnienta de implementaci6n, afiada a la aplicaci6n el archivo JAR que acaba de crear: Capitulo 20 9i YF I I P ~ 9 d Applications 9 0 Wackbox 9 @ DemoAccount 8 DemoAccount fi BlackBoxLocalTx Ref Type -resource I Referenced Bv DemoAccount I Reference Name I JNDI Name 1 e~sNdroxElS e ~ s M l r c ~I5 xf - 1 A continuacidn, necesitamos proporcionar a la aplicacidn 10s nombres JNDI mostrados anteriormente y, finalmente, implementar la aplicaci6n Blackbox en el servidor ejecutado, recordando crear el archivo JAR del cliente. El cliente Este es el cddigo del cliente: import import import import j a v a .util.*; javax.naming.Context; j a v a x .naming.InitialContext; j a v a x . rmi. P o r t a b l e R e m o t e O b j e c t ; public class D e m o A c c o u n t C l i e n t { public static void main(Strinq[] args) [ try ( Context i n i t i a l = n e w InitialContext ( ) ; O b j e c t o b j ref = initial. l o o k u p ( "DemoAccount') ; DemoAccountHome home = ( D e m o A c c n u n t H o m e )Portab1eRemoteObject.narrow(objre£, La arquitectura de conectores J2EE DemoAccount ramesh = home.create("lOO", "Ramesh", "Roger", 0.00); ramesh.credit(50.00); ramesh.debit(l0.15); double balance = ramesh.getBalance(); System.out.println("Account Balance = " + String.valueOf(balance) ) ; ramesh.remove( ) ; DemoAccount craig = home.create("200", "Craig", "Berry", 0.00); craig.credit(100.59); DemoAccount nikki = home. f indByPrimaryKey ("200"); nikki.debit (2.00); balance = nikki.getBalance(); System.out.println("Account Balance = " + String.valueOf(balance)); DemoAccount bill = home.create("300", "Bill", "Clinton", 0.00); bill.credit(2000.00); DemoAccount bob = home .create ("400", "Bob", "Clinton", 0.00) ; bob.credit (1000.00); DemoAccount jim = home.create("500", "Jimmy", "Clinton", 0.00); jim.credit(1000.00); Collection c = home. findByLastName ("Clintonn') ; Iterator i=c.iterator(); while (i.hasNext ( ) ) { DemoAccount account = (DemoAccount)i.next(); String accountid = ( S t r i n g ) a c c o u n t . g e t P r i m a r y K e y ( ) ; double amount = account.getBalance( ) ; System.out.println(accountid + ": " + String.valueOf(amount)); I while (i.hasNext ( ) ) { DemoAccount account = (DemoAccount)i.next(); String accountid = ( S t r i n g ) a c c o u n t . g e t P r i m a r y K e y ( ) ; double amount = account.getBalance0; System.out.println(accountid + " : " + String.valueOf(amount) ) ; \ ) ) catch (ProcessingException ex) { System.err.println("Caught an ProcessingException: + ex.getMessage ( ) ) ; catch (Exception ex) { System.err.printlr1 ("Caught an exception." ex.printStackTrace0; " ); 1 I 1 Finalmente, ejecute ~ e m o ~ c c o uCnl ti e n t , desde una ventana de comando, recordando incluir el archivo B l a c k b o x c l i e n t . j a r en su ruta de clase. El cliente debe mostrar 10s siguientes resultados en su ventana de comandos: Capitulo 20 La lnterfaz Comun de Cliente (CCI) La Interfaz Comdn de Cliente (CCI) proporciona un enfoque sencillo para el problema de escribir una interfaz Jnva mis compleja para un recurso EIS subyacente. Hasta la aparici6n de CCI, este problema ha sido una cuesti6n entre desarrolladores Java y vendedores EIS conocida com~inmentecomo "caos de integraci6nW.Implementando C C I en adaptadores de recursos, 10s vendedores EIS pueden proporcionar una interfaz Java a sus productos EIS que se ejecutadn en cualquier servidor de aplicacion que se ajuste a J2EE 1.3. La C C I define un API cliente independiente de EIS para componentes de aplicaci6n J2EE que permite que tales componentes se integren e interactien en recursos EIS heterogheos. Define las interfaces de llamada de funci6n remota para ejecutar consultas y transacciones con un EIS y obtener asimismo 10s resultados. Bisicamente, C C I proporciona API de llamada de funcibn para servidores de aplicaci6n JZEE y sus componentes a travCs de u n adaptador d e recursos JCA para crear y gestionar conexiones con u n recurso EIS, para ejecutar una operacibn con u n recurso EIS y para gestionar objetos/registros de datos corno entrada, salida o valores de retorno. La especificacih JCA recomienda que C C I debe formar la base para una funcionalidad mis rica y un modelo extensible de programacion proporcionado por 10s vendedores de adaptadores de recursos EIS, en lugar de ser el API utilizado por la mayoria de desarrolladores de aplicaci6n. Aunque C C I es independiente de un EIS especifico (por ejemplo, tipos de datos especificos de un EIS), CCI puede ser controlado por metadatos especificos de EIS procedentes de un repositorio. El C C I tambikn estd disefiado para utiliza la arquitectura JavaBeans y el sistema de sistema c o l l e c t i o n s de Java. Por ejemplo, un adaptador de recursos puede implementar la i n t e r f a z ~ a n a g e d ~ o n n e c t i o n ~ a c t o r y como un JavaBean, que mejoraria la capacidad de las herramientas del sistema JavaBeans para gestionar la configuraci6n de i n s t a n c i a s ~ a n a g e d ~ o n n ei cotn F a c t o r y . La especificaci6n J C A 1.0 recomienda (pero n o establece como obligatorio) que 10s adaptadores de recursos EIS implementen C C I como su API cliente, a la vez que t a m b i h requiere que estos adaptadores de recursos proporcionen 10s contratos de sistema con un servidor de aplicaci6n J2EE. Es conveniente sefialar que un adaptador de recursos tambien puede optar por tener un J2EE cliente adicional diferente de CCI, similar al API cliente provisto por el vendedor disponible en implementaciones JDBC. Los resultados de utilizar C C I son una mayor productividad para el desarrollador, un reducido coste de integraci611, c6digo portitil, sistemas de aplicaci6n reajustables y mantenimiento. Interfaces y clases CCI JCA define las interfaces y clases C C I que representan la siguientes partes: La arquitectura de conectores J2EE 0 Interfaces de conexi6n- Representan la factoria de conexiones y una conexidn de nivel de aplicacion: 0 Interfaces de interacci6n- Proporcionan un componente para controlar una interaccion (especificado utilizando I n t e r a c t i o n r j p e c ) con una instancia EIS: 0 Interfaces de representaci6n de datos- Utilizadas representar estructuras de datos implicadas en una interaccion con una instancia EIS: Interfaces de metadatos- Proporcionar informaci6n bisica de metadatos sobre una implementacidn de adaptador de recursos y una conexion especifica de EIS: 0 Clases de excepci6n y advertencia- Proporcionan control de excepciones y advertencias de recursos durante la interacci6n con un recurso EIS: A continuacion, presentamos una lista de interfaces/claes/m~todosJava del API C C I que es conveniente recordar: 0 j a v a x . r e s o u r c e . c c i .C o n n e c t i o n F a c t o r y - Unainterfazptibli~a~ueperrniteconexionesa una instancia EIS a traves de un adaptador de recursos. U n adaptador de recursos EIS proporciona normalmente esta interfaz. Una aplicaci6n busca una instancia C o n n e c t i o n F a c t o r y desde el espacio de nombres J N D I y la utiliza para obtener conexiones EIS, como muestra el siguiente fragment0 de codigo: public interface javax.resource.cci.ConnectionFactory extends java.io.Serializable, javax.resource.Referenceable public RecordFactory getRecordFactory0 { throws ResourceException; public Connection getconnection0 throws ResourceException; public connection getConnection(javax.resource.cci.ConnectionSpec properties) throws ResourceException; public ResourceAdapterMetaData getMetaData0 throws ResourceException; 1 o getconnection ( ) - Creaunainstancia Connection. Utilizar el m k t o d o g e t ~ o n n e c t i o n( ) con el parametro j a v a x . r e s o u r c e . c c i .C o n n e c t i o n s p e c requiere informacidn de seguridad y parametros de conexi6n. . especifica de lasolicitud 0 j avax . resource cci .connect i o ~ p e cProporcionalainformaci6n de conexi6n y propiedades como nombre de usuario, contraseiia y otros pardmetros a Connect ionFactor y mientras realiza una conexi6n a un EIS. . 0 j avax resource. cci .Connect ion-Representa una conexi6n a un recurso EIS y se utiliza para posteriores operaciones con un EIS subyacente. 0 createInte raction ( ) - Crea un objeto Interaction pararealizar operaciones especificas de EIS. . 0 j avax. resource. cci Interaction- Creaunainteraccibn con un EIS conectado con operaciones especificas, como muestra el siguiente extract0 de c6digo: public interface javax.resource.cci.Interaction ( public Connection getconnection0 ; public void c l o s e 0 throws ResourceException; public boolean execute (Interactionspec ispec , Record input, Record output) throws ResourceException; public Record execute(1nteractionSpec ispec, Record input) throws ResourceException; 0 Interact ionspec-Define la interacci6n que proporciona las propiedades de objeto especificas de EIS (por ejemplo, tipos de datos, esquema, etc.) asociadas a un EIS. 0 U n Record es la representaci6n Java de una estructura de datos utilizada como input o output de una funcidn EIS. 0 LocalTransaction- Crea un context0 de transaccidn para realizar, obviamente, una transacci6n local (similar a UserTransact ion) y gestiona su propia transacci6n y persistencia. javax. resource. cci .~ocal~ransactiondefineunainterfazdedemarcaci6npara transacciones locales de gestor de recursos, como se muestra a continuaci6n: public interface javax.resource.cci.Lo~a1Transaction public void begin() public void commit ( 1 ( throws ResourceException; throws ResourceException; public void rollback0 throws ResourceException; Para establecer una conexion a un recurso EIS y para efectuar interacciones como consultas y transacciones, el desarrollador necesita ajustarse a1 enfoque estdndar definido por la especificaci6n JCA 1.0. La especificaci6n explica dos situaciones para obtener una conexi6n a un EIS, que incluyen andlisis sobre la conexi6n a una aplicaci6n gestionada (aplicaci6n J2EE) y la conexi6n a una aplicaci6n no gestionada (applets o aplicaciones Java de dos gradas). En las siguientes secciones, analizaremos las dos situaciones y 10s pasos necesarios para conectar a interactuar con ellas. La arquitectura de conectores J2EE Conexion con una aplicacion gestionada (JZEE) En este caso, la aplicaci6n obtiene una conexi6n proporcionada por la factoria de conexiones, configurada durante la implementaci6n de un m6dulo de adaptador de recursos en el senidor J2EE. Esta factoria de conexiones se define normalmente en el descriptor de implementaci6n del adaptador de recursos. El siguiente diagrama de secuencias UML muestra 10s pasos relacionados con la situaci6n en la que una aplicacion gestionada obtiene una conexi6n a una instancia EIS desde una factoria de conexiones y despues interactua con un EIS: getConnection(Subject, ConnectionRequestlnfo) createlnteraction rn -I Examinemos mLs detenidamente 10s pasos implicados. 1. El ensamblador de la aplicaci6n especifica 10s requisites de la factoria de conexi6n para un componente de aplicaci6n J2EE utilizando su descriptor de implementacidn (es decir, Web. xml o e j b - j a r .xml). Esta referencia de factoria de conexiones es parte del elemento < r e s o u r c e r e f > del descriptor para componentes EJB o Web (en lugar del adaptador de recursos). Asi, un ensamblador de recursos especifica 10s siguientes elementos en el descriptor de implementacidn para una referencia de factoria de conexiones: 2. El senidor de aplicaci6n J2EE utiliza el adaptador de recursos configurado para crear conexiones a1 recurso EIS subyacente. 3. El componente J2EE busca una instancia de factoria de conexiones en el entorno utilizando senicios JNDI. MLs concretamente: //Obtener context0 inicial d e Nombrado Capitulo 20 Context initctx = new Initialcontext ( ) ; / / B f i s q u e d a JNDI p a r a o b t e n e r l a f a c t o r i a d e c o n e x i o n e s j avax. resource. c c i Cor~r~ectionFactory cf = ( j a v a z .r e s o u r c e . c c i . C o r ~ n e c t i o r ~ F a c t o r y ] . initctx.lookup("java:cornp/er~v/eis/wroxEIS"); Los resultados de la b h q u e d a J N D I en una instancia de factoria de conexiones de tip0 j a v a . r e s o u r c e . c c i .~onnection~actorycomoseespecificaene~ descriptorde implementacidn de la aplicaci6n. Tambikn debemos sefialar que, aunque no ha sido analizado, existe otro tip0 de factoria de conexidn para la Interfaz de Proveedor de Servicios (SPI). 4. La aplicaci6n invoca el mktodo g e t c o n n e c t i o n ( ) en la factoria de conexiones para obtener una conexidn EIS. Devuelve una instancia C o n n e c t i o n , que representa un controlador fisico para un EIS. Observe tambikn que el componente de aplicacidn puede obtener mdtiples conexiones invocando g e t c o n n e c t i o n ( ) en la factoria de conexidn como se requiere: j avax. r e s o u r c e . c c i . C o n r ~ e c t i o n cx = Entonces la aplicacidn utiliza el m k t o d o c r e a t e I n t e r a c t i o n ( ) del o b j e t o c o n n e c t i o n p a r a c r e a r u n a i n s t a n c i a ~ n t e r a c t i o n .ja v a x . r e s o u r c e . c c i . I n t e r a c t i o n p e r m i t e a u n a componente ejecutar sus funciones EIS. El componente de la aplicaci6n crea instancias R e c o r d utilizando mktodo de crear R e c o r d F a c t o r y (~osmktodosdisponib~esinc~uyencreate~ndexed~ecord (), c r e a t e M a p p e d R e c o r d ( ) o c r e a t e ~ e s u l t ~ 0). et El componente de la aplicacidn u t i l i z a ~ o c a l ~ r a n s a c t i odefiniendo n un context0 de transacci6n para realizar operaciones con un EIS. j a v a x . r e s o u r c e . c c i . LocalTransactiondefineunainterfazdedemarcaci6nde transacci6n para transacciones locales de gestor de recursos. El componente de aplicaci6n J2EE utiliza la interfaz L o c a l T r a n s a c t i o n para demarcar transacciones locales. Una vez que la aplicacibn J2EE termina con la c o n e x h , cierra la conexi6n utilizando el mktodo c x c l o s e ( ) en la interfaz c o n n e c t i o n . Si la aplicacidn n o cierra una conexidn asignada despuks de su uso, la conexi6n se considera no utilizada y el servidor de aplicaci6n se encarga de la limpieza de conexiones sin utilizar. . Conexion a una aplicacion no gestionada (de dos niveles) En una situacidn de conexidn de aplicacibn n o gestionada, que implica a un applet a o a una aplicacidn Java de dos niveles, es responsabilidad del desarrollador de la aplicacibn crear un modelo de conectividad utilizando 10s API de nivel inferior expuestos por el equivalente del adaptador de recursos a1 de una aplicaci6n gestionada configurada en un entorno J2EE. Habitualmente, una aplicacidn n o gestionada conlleva la b h q u e d a de una instancia de factoria de conexibn, obteniendo una conexidn EIS, utilizando la conexidn para operaciones EIS y cerrando la conexi6n. Este modelo es similar a1 mod0 en que un cliente de a p k a c i 6 n JDBC de dos niveles accede a un sistema de base de datos en un entorno n o gestionado. El siguiente diagrama de secuencias muestra 10s pasos implicados en el proceso en que una aplicacidn no gestionada obtiene una conexidn a una instancia EIS desde una factoria de conexiones y despuks interactha con un EIS: La arquitectura de conectores J2 EE 0 Recurso EIS Gestionad Recursos EIS 1 eManaged Connection I I I I Por lo tanto, la secuencia es de este modo: I. El componente de aplicacidn no gestionada invoca un metodo sobre la instancia j avax. resource. cci .ConnectionFactory (devueltodelabusquedaJNDI) paraobtener una conexi6n a1 recurso EIS subyacente. 2. La i n s t a n c i a ~ o n n e c t i o n ~ a c t o delega ry la solicitud de conexidn procedente de la aplicacidn no gestionada en la instancia ConnectionManager provista por el adaptador de recursos. SegGn la especificacidn JCA 1.0, el adaptador de recursos EIS proporciona la implementaci6n de ConnectionManager como equivalente a1 servidor J2EE. 3. Entonces la instancia ConnectionManager crea una nueva conexidn a1 recurso EIS invocando e~m~todo~anaged~onnection~actor~.createManagedConnection(). 4. Lainstancia~anaged~onnection~actory manejael mktodo createManagedConnection ( ) creando una nueva conexi6n a1 recurso EIS representado por unainstanciaManaged~onnection.La i n s t a n c i a ~ a n a g e d ~ o n n e conFactory ti utiliza Connect i onReques t Info y su conjunto configurado de propiedades (como el nGmero de puerto, nombre de servidor, etc.) para crear una nueva i n s t a n c i a ~ a n a g e d ~ o n n e c t i o n . 5. La i n s t a n c i a c o n n e c t i o n ~ a n a g e rinvocael mktodo Managedconnection getconnection ( ) para obtener un dispositivo de conexi6n de nivel de aplicaci6n. Este, en realidad, proporciona un dispositivo temporal para que el cliente de aplicacidn no gestionada acceda a la instancia s u b y a c e n t e ~ a n a g e d ~ o n n eicon. t . 6. Entonces la instancia ConnectionManager devuelve el dispositivo de la conexi6n a la instancia Connect i onFact ory, que devuelve entonces la conexi6n a1 cliente de aplicaci6n no gestionada que inicia una solicitud de conexidn. Capitulo 20 7. La aplicaci6n utiliza entonces el m k t o d o c r e a t e ~ n t e r a c t i o n( ) del o b j e t o c o n n e c t i o n p a r a c r e a r u n a i n s t a n c i a ~ n t e r a c t i o nj.a v a x . r e s o u r c e . c c i . I n t e r a c t i o n p e r m i t e a u n componente ejecutar funciones de EIS. 8. El componente de aplicaci6n crea instancias R e c o r d utilizando 10s mktodos de creaci6n R e c o r d ~ a c t o (rq~u e i n c l u y e n c r e a t e ~ n d e x e d ~ e c o(r)d, c r e a t e ~ a p p e d R e c o r d( ) c r e a t e R e s u l t S e t 0). 9. El componente de aplicaci6n utiliza L o c a l T r a n s a c t i o n definiendo un context0 de transaction para realizar operaciones con un EIS. 10. Finalmente, una vez que la aplicaci6n no gestionada termina con la conexion, debe cerrar la conexidn utilizando el mktodo c x . c l o s e ( ) sobre la interfaz c o n n e c t i o n . En el momento de publicacidn de este libro, 10s adaptadores de recursos con apoyo C C I apenas estaban disponibles, ni siquiera como implementacidn beta. Como tal, hemos estado utilizando 10s adaptadores de recursos de caja negra C C I provistos en la implementacidn de referencia J2EE en nuestros ejemplos. Observe que 10s adaptadores de recursos estaban en realidad destinados a probar el proceso de empaquetado y de implementacidn, asi como C C I . En la siguiente seccibn, ilustraremos un ejemplo de uso de adaptadores de recursos de caja negra C C I y explicaremos c6mo escribir clientes de aplicaci6n J2EE para invocar mktodos de API C C I disponibles desde el adaptador de recursos. Tambikn analizaremos c6mo utilizar las diferentes clases e interfaces definidas por la C C I para acceder a un adaptador de recursos para una base de datos o un EIS. Utilizar una CCI con adaptador de caja negra . El e,i e m ~ l oes una a~licacionde libreria ficticia Dara aaadir libros nuevos v obtener la cantidad total disponible desde una base de datos. En este ejemplo, implementaremos un bean de sesi6n con estado, que utiliza un adaptador de caja negra de C C I para ejecutar procedimientos almacenados de SQL para consultar y ejecutar transacciones con un RDBMS. Es bastante similar a una aplicaci6n JDBC pero, en lugar de utilizar llamadas JDBC, el API C C I se utiliza para pasar parimetros y ejecutar 10s procedimientos almacenados de SQL en la base de datos subyacente. Los pasos necesarios en la implementaci6n del ejemplo B o o k s t o r e utilizando un adaptador de caja negra de C C I son 10s siguientes: 0 Implementaci6n de bean de sesi6n utilizando C C I Implementaci6n del adaptador de caja negra de C C I 0 Implementaci6n del bean de sesi6n 0 Prueba del adaptador de caja negra de C C I Implementation de un bean de sesion con CCI En este ejemplo Bookstore, se utiliza un bean de sesi6n con estado para mantener un registro del nlimero de libros en la tienda de libros. Nuestro bean invocari llamadas C C I sobre un adaptador de caja negra de C C I para ejecutar procedimientos almacenados en una base de datos. Como es habitual, nuestro EJB de sesidn contiene una interfaz initial ( B o o k s t oreHome), una interfaz remota (BookSt o r e ) , una clase de implementaci6n de bean (Book S t o r e B e an). Veamos ahora cdmo esta implementaci6n de bean de sesi6n utiliza llamadas CCI, analizando las interfaces y clase del b e a n ~ o o k s t o r e . La arquitectura de conectores J2EE La interfaz inicial BookStoreHome simplemente define un metodo create ( ) para devolver una referencia a la interfaz remota Book: import j avax. ej b. * ; import j ava. rmi. RemoteException; public interface BookStoreHome extends EJBHome [ Booksstore c r e a t e 0 throws RemoteException, CreateException; 1 La interfaz remota Bookstore contiene la definicidn para dos metodos de empresa: import j avax. ejb.EJBObj ect; import java.rmi.RemoteException; public interface Bookstore extends EJBObject { public void insertBooks(String name, int quantity) throws RemoteException; public int getBooksCount0 throws RemoteException; I La clase de implementation del bean BookStoreBean es la clase de implementacidn del bean, que utiliza C C I . ~ o o k ~ t o r e ~ importa ean las interfaces CCI (es decir, j avax resource. cci *) y tambiknlas clases de la interfaz (com.sun.connect or. cciblackbox *) especificas del adaptador de cajanegra, junto con . . . javax.resource.ResourceException: import import import import import import import java.math.*; java.util.*; j avax. ejb. * ; javax.resource.cci.*; javax.resource.ResourceException; j avax. naming. *; com.sun.connector.cciblackbox.*; public class BookStoreBean implements SessionBean { En el mktodo setsessioncontext ( ) , el bean utiliza variables de entorno para el nombre de usuario y la contrasefia para instanciar una ConnectionFactory para el adaptador de caja negra de CCI: private private private private public public public public SessionContext sc String user; String password; ConnectionFactory void void void void ejbRemove ( ) { I ejbActivate ( ) ejbpassivate ( ) ejbcreate ( ) throws CreateException { ) public void setsessioncontext (Sessioncontext sc) { try { this.sc = sc; / / Establecer un context0 inicial JNDI Context ic = new Initialcontext ( ) ; / / Utilizar el mktodo 1ntialContext.lookup para tomar Capitulo 20 / / 10s valores de usuario y de contraseRa. user = (String) ic.lookup("java:comp/env/user"); password = (String) ic.lookup("java:comp/er~v/password~~ j; / / IJtilizar el mktodo de bkqueda para localizar ConnectionFactory y / / obtener una referencia a 6ste. cf = (ConnectionFactory) ic. lookup ("java: comp/env/eis/wroxCCIEIS" ) ; 1 catch (NamingException ex) { ex.printStackTrace ( ) ; I 1 El bean utiliza su mktodo privado g e t c c I c o n n e c t i o n ( ) para establecer una conexibn con la base de datos utilizando el adaptador de caja negra. Con anterioridad a g e t c c I c o n n e c t i o n ( ) ,instancia un nuevo objeto c c i c o n n e c t i o n S p e c , que representa la implementacidn de l a i n t e r f a z ~ o n n e c t i o n ~ p econ c , 10s valores de usuario y de contraseiia obtenidos del context0 del bean, e invoca el mktodo g e t c o n n e c t i o n ( ) para obtener la conexibn. Se crea un controlador de conexibn al recurso EIS subyacente: private Connection Connection con = try i / / Instanciar / / valores de getCCIConnection null; j { un nuevo objeto CciConnectionSpec con 10s usuario y de contraserla ConnectionSpec spec // // // // ( ) = new CciConnectior~Spec(user, password) ; Utilizar CCIConnectionSpec para proporcionar 10s parimetros especificos de la conexi6n requerida a ConnectionFactory y y utilizar el mktodo getconnection de ConnectionFactory para obtener la conexibn a la base de daros. con = cf.getConnection(spec); catch (ResourceException ex) ( ex.printStackTrace0; I return con; I El bean tambikn contiene un mktodo privado c l o s e c c I c o n n e c t i o n ( ) para cerrar una conexidn con el gestor de recursos. El bean de sesidn utiliza este mktodo internamente para invocar el mktodo c l o s e ( ) del o b j e t o c o n n e c t i o n . C o m o ya hemos aprendido anteriormente, si la aplicacibn n o cierra una conexidn asignada despuks de su uso, se considera que la conexibn n o esti utilizada y el servidor de la aplicacibn se encarga de la limpieza de conexiones sin utilizar (esto se aplica solamente a conexiones de aplicacidn gestionada). Esto finaliza una conexidn con el recurso EIS subyacente: private void closeCCIConnection[Connection con) { try i con. close ( ) ; ] catch (ResourceException ex) { ex.printStackTrace0; I I Ahora que hemos definido 10s mktodos que permiten a nuestro bean interactuar con el recurso subyacente utilizando C C I , creemos 10s mktodos para efectuar operaciones con el recurso, en este caso, una base de datos. La arquitectura de conectores J2EE El bean de sesi6n B o o k s t o r e implements un mktodo i n s e r t B o o k s 0, que ejecuta una transacci6n local para insertar nuevos registros en la tabla ~ o o de k la base de datos. Este mktodo invoca el procedimiento INSERTBOOKS almacenado en la base de datos que ahade un nuevo registro con dos valores como argumento. Siendo lo habitual en una llamada de mktodo JDBC, el mktodo i n s e r t B o o k s ( ) establece primer0 una conexi6n a la base de datos (a travks del adaptador de caja negra) utilizando g e t c c I c o n n e c t i o n ( ) , despuks crea una nueva instancia I n t e r a c t i o n . Entonces el bean instancia un nuevo objeto C c i I n t e r a c t i o n S p e c para definir las propiedades de interacci6n de la base de datos requeridas para comunicar con una base de datos (como la configuraci6n del nombre almacenado de procedimiento y sus parimetros): public void insertBooks(String name, int q t y ) [ try I / / Establecer una conexidn Connection con = getCCIConnection(); // Crear una Interaction Interaction ix = con.createInteractioni) ; / / Instanciar un obj eto CciInteractionSpec CciInteractionSpec iSpec = new CciInteractionSpec(); // // Confiqurar las propiedades de Interaction (Observe que 'null' configura el catilogo por defecto). iSpec. setFunctionName ("INSERTBOOKS"); iSpec.setSchema(user); iSpec.setCatalog(nul1); / / Utiliza ConnectionFactory para obtener RecordFactory RecordFactory rf = cf .getRecordFactory ( ) ; / / Invocar el metodo createIndexedRecord ) ; IndexedRecord iRec = rf. createIr~dexedRecord("Ir~putRecord" / / Configurar 10s valores boolean flag = iRec.add(name) ; flag = iRec.add (new Integer iqty) ) ; / / Ejecuta la interacci6n ix.execute(iSpec, iRec); 1 I finally { / / Cierra la conexidn closeCCIConnection(con); System.out.println("C10sed connection"); 1 1 El mktodo g e t B o o k s C o u n t 0, utilizando CCI, lee registros desde una tabla de base de datos subyacente ejecutando el procedimiento a ~ m a c e n a d o ~ 0 ~El~ mktodo ~ ~ 0 0utiliza ~ ~ .un I n d e x e d R e c o r d (elGnico registro apoyado en la actualidad por el adaptador de caja negra de CCI), que alberga sus elementos en una colecci6n indexada basadaen j a v a .u t i 1 .L i s t : public int getBooksCount ( int count = -1; try I ) I / / Obtener una conexi6n Connection con = getCCIConnection0; / / Crear una nueva instancia Interaction Interaction i x = con.createInteraction0; Capitulo 20 / / Instanciar un objeto CciInteractionSpec CciInteractionSpec iSpec = new CciInteractionSpec(); / / Configurar 10s par6metros para Interaction iSpec.setSchema(user); iSpec.setCatalog(nul1); ) ; iSpec. set FunctionName (ispec.setFunctionNameo;'COUNTBOOKS" / / Utilizar ConnectionFactory para obtener RecordFactory RecordFactory rf = cf .getRecordFactory ( ) ; / / Utilizar el metodo createIndexedRecord IndexedRecord iRec = r f . c r e a t e I n d e x e d R e c o r d ( " I n p u t R e c o r d " ) ; / / Ejecutar la interacci6n Record oRec = ix. execute (iSpec, iRec) ; / / Utilizar Iterator para recuperar elementos Iterator iterator = ( ( I n d e x e d R e c o r d ) o R e c ) . i t e r a t o r ( ) ; while(iterator.hasNext0) [ / / Extraer el elementos como un objeto Java Object obj = iterator.next ( ) ; if (obj instanceof Integer) { count = ( (1nteger)obj) . intvalue ( ) ; ) else if(obj instanceof BigDecimal) { count = ( ( B i g D e c i m a l ) o b j ) . i n t V a l u e ( ) ; I I I finally { / / Cerrar la conexi6n closeCCIConnection(con); System.out.println("C1osed Connection"); I return count; 1 El detcriptor do implementadon EllB Observe que, estavez, en el descriptor de implementacih, el elemento (destacado en negrita) e ~ d e t i ~ o j a v aresource. x. c c i .ConnectionFactory: < ! DOCTYPE ej b-j ar PUBLIC \-//Sun Microsystems, Inc. //DTD Enterprise JavaBeans 2.0//ENf \http://java.sun.com/dtd/ejb-jar 2 O.dtdf> La arquitectura de conectores J2EE El cliente El cliente invoca 10s mktodos getBooksCount probar el adaptador de caja negra de CCI: import import import import () y insertBooks ( ) sobre el bean de sesi6n para java.uti1. * ; j avax. naming. Context; javax.naming.InitialContext; j avax. rmi. PortableRemoteObj ect; public class BookStoreClient { public static void main(String[] args) { try I Context initial = rlew InitialContext ( ) ; Object obj ref = initial. lookup ("Bookstore") ; BookStoreHome home = (BookStoreHome)PortableRemoteObject.r~arrow(objref, BookStoreHome.class); Bookstore book = home.create ( ) ; int count = book.getBooksCount ( ) ; System. err.println("Current Book count = " t count) ; System.err.println("Insertir~g 2 new books.. . " ); book. insertBooks ("USA Tour guide", 100); book. insertBooks ("Europe Tour guide", 20); ] count = book. getBooksCount ( ) ; System. err.printli-I("Current Book count = " + count); catch (Exception ex) { System. err .println ("Caught an unexpected exception! " ) ; ex.printStackTrace0; I I 1 Implementation del adaptador de recursos de caja negra de CCI Como sucede con el ejemplo anterior ~ e m o ~ c c o u n kste t , es un proceso de dos fases. Primero, necesitamos configurar la base de datos para crear la tabla y afiadir 10s procedimientos almacenados y, en segundo lugar, necesitamos implementar el adaptador. Capitulo 20 Configurar la base de datos ~ s t es e un proceso ligeramente rnis complejo que el del ejemplo anterior porque, ademis de crear la tabla ~ o o k stambien , sera necesario que creemos 10s dos procedimientos almacenados. Utilizaremos de nuevo Cloudscape; sin embargo, esta base de datos tiene un metodo de manejo de procedimientos almacenados bastante inusual. Explicaremos el metodo inmediatamente, per0 antes creemos la tabla ~ o o k s . Utilice el siguiente SQL para crear la sencilla tabla ~ o o k s : CREATE TABLE Books (name VARCHAR(32), qty INTEGER); Volvamos ahora a 10s procedimientos almacenados. Para utilizarlos con Cloudscape, necesitamos escribir una clase Java que proporcione la implementaci6n del procedimiento utilizando JDBC bisico. Entonces, en la base de datos, creamos un ALIAS para 10s procedimientos almacenados que apuntan a esta clase. Asi, para nuestro procedimiento almacenado COUNTBOOKS, afiadiremos un metodo a nuestra clase que sea como el siguiente: import j ava. lang. Integer; import j ava. sql. * ; import java. lo.*; public class BookProcs implements Serializable { public static int c o u n t B o u k s 0 [ int count = 0; try { Connection con = DriverManager. getConnectior~( " j d b c :cloudscape: ;current=truel'); Preparedstatement ptstmt = con.prepareStatement ("SELECT COUNT ( * ) FROM BOOKS") ; Resultset rs = ptstmt.executeQuery(); while (rs.next ( ) ) { count = rs.getInt ( 1) ; I ptstmt.close(); 1 catch (Exception ex) ex.printStackTrace { ( ) ; I return count; Entonces afiadimos el s i g u i e n t e a~la~base ~ ~de ~ datos Cloudscape: CREATE METHOD ALIAS COUNTBOOKS FOR BookProcs.countBooks; Recuerde que puede ejecutar SQL bien utilizando directamente Cloudview o desde una linea de comando utilizando la invitation c l o u d s c a p e - i s q l desde % 5 2 EE-HOME% \ b i n . Observe que, para que esto funcione, necesitamos asegurarnos que la clase B o o k P r o c s se encuentra en la ruta de clase de la base de datos. El modo ma's fa'cil de realizar esto es modificando la variable B J P E E - C L A S S P A T H I (configurada en elarchivo u s e r c o n fig. b a t ) . Para el procedimiento almacenado INSERTBOOKS, afiada otro metodo a B o o k s P r o c s : public static void insertBooks (String name, int q t y ) [ try Connection con = DriverManager .getConnectior~("jdbc:cloudscape: ;currer~t=true") ; La arquitectura de conectores J2EE Preparee2Statemer1t ptctrnt c i i n . ~ t r e ? a r e S t a t e m e r ~{t" I N S E R T p t s t m t . s e t S t r i n g (1, n a m e ) ; p t s t r n t . s e t 1 n t ( 2 , qty); ptztrnt executeUpdateI) ; ptstmt.clcse0; c a t c h ( E x c e p ti a n e x ) ! cx.prir,tStackTrace ( ) ; INTO BOOKS VF.LI.IES I ?, ? ) " ) ; . j i 1 C'PEATf blETHOI? ALIAS 1NSERTBOOk:S FOR Fn\?kProc.=.insertRnr,ks; Irnplementacion del adaptador Utilizaremos un mktodo similar al utilizado anteriormente, excepto que, csta vez, implementaremos el archivocciblackbcx-tx. rar. C o n cl servidor d e la Implementaci6n d e Referencia 12EE 1.3 ejecutindose, abra la hcrramienta d e implelncntaci6n y Cree unn nueva aplicacidn I l a n l a d a C C I A d a p t e r : - 1 1Ch20~.CCIAdaptenCc3'IAdapter.ear . Browse... . Afiada entonces un archivo r a r del adaptador dc rccursos existente c o m o hiciCramos anteriormente pcro,estave~,se~eccioneelarchivo'J2EE-HOME\ 1 ~ b \ c o n n e c t o r \ c c ~ b l a c k b o x - t e xr.a r antes de implernentnr la npl1caci6n de empresa. Arnplie el nodo del servidor hasta que pueda ver su servidor cn ejecucidn (con toda probabilidad, l o c a l h o s t ) y selcccione el servidor de In ventnna de la parte izquierda. En la ventana de la dcrecha, cnmbie a la opcion Resource-adapters y haga clic en el boton New. En el cuadro de d i d o g o New Connection Factory (Nueva factoria de conexion), s e l e c c ~ o n e c c ~ ~ d a p:tcecrl b l a c k b o x - t x . r a r corno Resource-adaptery otorguele un Nornbre JNDI, e i s / W r o x C C I E I S , c o m o se muestra a continuaci6n: Capitulo 20 C o n w c l l u r ~Factory JNOI Nnrrln: rrj.;.hriiaxi:cIEgi, Cor~fiijlrralinnPropeflies- PropertV ConneclronURL I Twe String -1 value jdbc cloudscape rml Clou Aseglirese d e que la propiedad ConnectionURL apunta a In base de datos correcta (en nuestro caso, CloudscapeDB) y haga clic en OK para afiadir el adaptador: FTiiGiFo; p ~ blackbox-tx rar cp elwWroxE1S @ CClAdapler 9 tclblatkbox-bcrar eisl~row~~l~w 1 EM." I La arquitectura de conectores J2EE Ahora que ya hemos irnplernentado el rn6dulo del adaptador de recursos de caja negra de C C I con una factoria de conexiones en el servidor de la Irnplernentaci6n de Referencia J2EE 1.3 y hernos creado las tablas de la base d e datos y 10s procedirnientos alrnacenados, estarnos preparados para irnplernentar el bean de sesi6n y ejecutar el cliente. Implernentacion y prueba de l a aplicacion CCI Compile 10s archivos java EJB, recordando afiadir el archivo c c i b l a c k b o x - t x . r a r (que se encuentra en el fichero c c i b l a c k b o x - t x . rar) a su ruta de clase y afiidalos entonces a la herrarnienta de irnplementaci6n utilizando el asistente de creaci6n de EJB o generando su propio archivo J A R EJB: 9 C j Applical~ons 0- 0 Blackbox 9 0 CClAdapter 0- @ BookStore G% CciBlackBoxLocalTn 8 P Sewers Ref Type !esource - I Referenced By ( Reference Name BookStore ewWroxCCIEIS -1 1 JNDl Name I s i s W i r o ~ 7 :lE_ISU Afiada 10s nornbres J N D I relevantes e irnplernente de nuevo la aplicaci6n, recordando crear esta vez el archivo J A R del cliente. Finalmente, ejecute el cliente utilizando una linea de cornando corno rnostrarnos a continuaci6n. Si t o d o funciona corno es debido, o b t e n d r i el siguiente resultado: Capitulo 20 Asi concluye nuestro e j e ~ n p l oB o o k s t o r e que utiliza el adaptador d e recursos de caja negra de C C I para interactuar con una base d e datos Cloudscape. Ventajas de la arquitectura de conectores JZEE C o n el esito de JZEE en aplicacibn d e elnpresa de base Web, se preve claramente que J C A se alzarl como el principal mccanismo d e integracidn para interactuar con recursob EIS de segundo plano. En conveniente recordar un par de importante ventajas: -1 J C A permite a las orgnnizaciones aumentar las ventajas d e sus sistemas EIS existentes y d e JZEE. -1 J C A permite a 10s desarrolladores escribir (o reescribir) nuevas aplicaciones utilizando JZEE, cncapsulando partes funcionales de aplicaciones existentes en EJB o en componentes Web. Annlicemos brevemente algunas situnciones en las que J C A ofrece una soluci6n potential, centrindonos en las ventajas obvins. Integration de aplicacion de empresa (EN) con JCA Gestionar e integrar diversas aplicaciones EIS para compartir datos y procesos habitualmente aiiade retos al desarrollo, transacciones, seguridad y reajustabilidad de una aplicaci6n. C o m o 10s recursos EIS se construyen esclusivamente con su propio API d e propiedad y sus propios mecanibmos de transacci6n y s e p r i d a d , se hace e x t r e m ~ d a m e n t ecomplejo construir un sistema EAI utilizando mliltiples API de propiedad y adaptando mecanismos nativos. Aunque m a estrategia EAI requiere un catllogo de requisitos, con una combinaci6n de diferentes tecnologias de adaptador, en la mayoria de 10s casos se termina con unas limitaciones y cuestiones relacionadas con la reajustabilidad del sistema debido a un API d e propiedad o a mecanismos no estindar. En ocasiones, puede terminar m l s bien como un k t i d o de aplicaciones de empresa que corno una integracibn. J C A proporciona una arquitectura estindar que arregla esas deficiencias de soluciones EAI comunes. C o n una larga lista de vendedores de EIS respaldando J C A mientras proporcionan adaptadores de recursos especificos de EIS, J C A presenta caracteristicas de integracibn sin fisuras con su API de C C I independiente de la aplicacibn, apoyando las transacciones distribuidas y mecanismos de seguridad genkricos y especificos d e la aplicacibn. Portales de empresa capacitados con JCA Los portales de empresa normalmente cubren la necesidad de ofrecer un linico "escritorio" corporativo que unifica toda la informacibn, servicios, aplicaciones y procesos para 10s miembros de una empresa, como empleados, socios y clientes. Integrar contenido y aplicaciones utilizando una infraestructura La arauitectura de conectores J2EE genirica afiade complejidad si ello conlleva la integracion con aplicaciones heterogineas de segundo plano y sistemas de legado con arquitecturas de propiedad y mecanismos de seguridad. Los portales generalmente requieren un acceso global que requiere apoyo centralizado de autentificacion y autorizaci6n para aplicaciones heterogineas y transacciones distribuidas con multiples sistemas de informacidn de empresa. Por lo general, 10s portales son aplicaciones con una misi6n esencial que demandan gestionabilidad central y de alta disponibilidad. Fornlando parte de la familia J2EE, JCA es ideal para construir portales de empresa. C o n el exit0 de 10s portales basados en J2EE, J C A mejora 10s recursos EIS distintos de Java permitiindoles formar parte de un portal de empresa de base J2EE. Las mejoras relevantes inchyen: O API C C I independiente de la aplicacion 0 Mecanismo de acceso EIS que apoyan mecanismos de autentificacion especificos de la aplicaci6n Transacciones distribuidas basadas en componentes J2EE con apoyo XA D e este modo, JCA representa claramente una solucion perfecta para elevar aplicaciones EIS a un portal de empresa. Integracion empresa-a-empresa con JCA La integracih empresa-a-empresa (B2B) mejora la automatizaci6n del proceso de extremo a extremo y permite la interaccion de la aplicaci6n en el interior de una empresa y entre socios a travis de Internet. Para apoyar verdaderamente la's interacciones externas de socios comerciales, 10s sistemas internos de segundo plano necesitan estar integrados sin fisuras en el mismo proceso. Sin ello, la integracion de procesos de extremo a extremo n o puede lograrse. Aunque XML sobre H T T P proporciona integracion de cliente B2B dentro de una empresa y en Internet, tiene sus propias limitaciones en cuanto a integracion aplicacion-a-aplicaci6n, seguridad y transacciones. JCA resuelve el puzzle B2B proporcionando e ~ ~ e c i f i c a m e nintegracion te con recursos EIS de segundo plano y demuestra una integracion genuina de proceso de extremo a extremo. J C A puede ser implementado para consultar y trasladar datos con recursos EIS de segundo plano, y 10s datos pueden ser convertidos posteriormente en XML utilizando 10s API XML de Java para la interacci6n B2B con socios. C o n la capacidad de C C I y sus desarrolladores de API independientes de la aplicaci6n, podemos manejar cualquier mecanismo de seguridad de nivel de aplicaci6n y cualquier transacci6n distribuida con multiples recursos EIS. Contar con aplicaciones de servidor de empresa basadas en la plataforma J2EE para utilizar J C A permite tener aplicaciones B2B de gran reajustabilidad son comprometer el valor y la funcionalidad de recursos EIS. Queda claro que J C A ofrece innumerables ventajas a 10s usuarios reduciendo el coste de construir complejas soluciones EAI, mejorando la productividad del desarrollador, la protecci6n de la inversion de arquitecturas estindar y la ampliaci6n de aplicaciones personalizadas. Elementos que faltan en JCA 1.0 En las secciones anteriores, hemos analizado las funciones y 10s factores m i s prometedores de la Arquitectura de Conectores J2EE 1.0; concluyamos ahora analizando 10s elementos que faltan en esta version de la especificaci6n. Capitulo 20 Los dos elementos clave que faltan en la especificaci6n 1.0 de la Arquitectura de Conectores J2EE son: 0 La actual especificaci6n no es compatible con la comunicaci6n asincrona y s61o es compatible el modelo de comunicacidn sincrono solicitud/respuesta. Esto puede resultar un problems restrictivo para conectar con colas de mensajes. 0 N o existe un mecanismo integrado de compatibilidad XML disponible para recuperar datos XML, aunque C C I puede utilizarse para compatibilizar XML. Estas limitaciones se resolverin en la siguiente versidn de la especificacion (JCA 1.1). para mas detalles, consultehttp://java.sun.com/j2ee/connector/. En este capitulo, hemos realizado un recorrido por la Arquitectura de Conectores J2EE 1.0, demostrando con ejemplos el uso de adaptadores de recursos de caja negra provistos con la ImplementaciCln de Referencia T2EE 1.3. Hemos analizado c6mo se enfrenta la arauitectura de conectores T2EE a sus soluciones para resolver cuestiones de integration de aplicacidn surgidas en la industria actual. Este capitulo tambikn ha explicado y demostrado 10s pasos implicados en la integraci6n e interacci6n con un EIS utilizando el API de Interfaz Comun de Cliente (CCI). Hemos analizado: 0 El rol de la Arquitectura de Conectores J2EE U La Arquitectura de Conectores J2EE y sus elementos 0 Los adaptadores de recursos 0 Implementaci6n y prueba de un adaptador de recursos 0 Programaci6n con la Interfaz Comun de Cliente (CCI) 0 ImplementaciCln y prueba de una aplicaci6n debase J C A 0 Ventajes potenciales de J C A 0 Estado actual de la especificaci6n y elementos ausentes En el siguiente capitulo, examinaremos algunas de las consideraciones de diseiio mis importantes que se deben tener en cuenta a la hora de desarrollar nuestras aplicaciones J2EE. C o n la ayuda de algunos diagramas UML, veremos una serie de patrones especificos de J2EE que pueden aplicarse para resolver algunas cuestiones comunes de diseiio. Consideraciones de diseiio para aplicaciones JPEE La Plataforma Java 2, Enterprise Edition (J2EE) ofrece una gama completa de tecnologias 6tiles. Hasta ahora, hemos dedicado gran parte de este libro a tratar esas tecnologias y a estudiar cdmo deben ser aplicadas. La clave para crear aplicaciones aprovechables, flexibles y mantenibles estP e n aplicar tecnologias apropiadas a1 contexto del problema a resolver. En este capitulo, examinaremos algunas de las formas mls comunes de aplicar tecnologias J2EE para resolver cuestiones de disefio en determinados contextos. Analizaremos 10s siguientes temas: CI Q u i queremos decir cuando hablamos de disefio y arquitectura O La relacidn entre disefio y el contexto en que tiene lugar Las fuerzas que intervienen en el disefio de una tipica aplicacidn de e-comercio para la plataforma J2EE Una variedad de patrones especificos de J2EE que resuelven cuestiones comunes de disefio que surgen a1 disefiar sistemas de empresa basados en J2EE 0 Las ventajas y desventajas de varias tecnologias J2EE a1 ser aplicadas en ciertos contextos de diseho Capitulo 21 El mundo sigue cambiando Cuando 10s vendedores de software (normalrnente enfrentados) estin de acuerdo en algo, ies un buen o un ma1 presagio? Considere las plataformas de aplicaciones de empresa prornovidas p o r - ~ u ny por Microsoft. Desde un nivel superior, la Plataforrna Java 2 Enterprise Edition (J2EE) y .NET Framework (anteriorrnente personificado en Windows Distributed Internet Architecture, o D N A ) asustan un poco. Arnbas cornbinan rndtiples niveles, clientes infradotados o dotados, ~rotocolosde obietos distribuidos. API de acceso estandar, servicios de rnensajeria, entornos de cornponentes de grada media y transacciones. .. La llegada del cornercio electr6nico y las escalas de tiernpo de Internet ha carnbiado el modo de definicibn y desarrollo de la rnayoria de las aplicaciones de ernpresa. Los requisitos son mds exigentes que antes y las escalas de tiernpo son rnenores. Hay una necesidad creciente de soluciones rnis adaptables ya que, segurarnente, 10s requisitos de ernpresa de rnafiana no serin 10s rnismos que 10s de hoy. Para disefiar y desarrollar aplicaciones en estas condiciones, necesitarnos ayuda seria (algunos dirian "profesional"). Esta ayuda norrnalrnente adopta dos forrnas: sistema estandarizado en el que las aplicaciones pueden ser construidas y desplegadas. El sisterna debe proveer niveles apropiados de funcionalidad y debe tarnbitn ayudar a autornatizar la creaci6n de "conexiones" estindar para conectar la aplicaci6n a si rnisrno. EI U n CI U n conjunto de las mejores pricticas para utilizar ese sistema. Los desarrolladores de software no tienen una cantidad de tiernpo infinita para invertir en la conternplaci6n de la filosofia del disefio o en aprender 10s rnodos rnis eficientes de utilizar ciertos API. Lo que necesitamos son directrices que les ayuden a escribir buenas aplicaciones utilizando el sisterna. En tirminos Java, el sistema para el desarrollo de aplicaciones de empresa distribuidas es JZEE. Las caracteristicas y funcionalidad de la plataforma permiten la creaci6n de aplicaciones reajustables, distribuidas, flexibles y basadas en componentes. Los cliches anteriores son s61o unos cuantos de los que se aplican regularmente a J2EE en la "propaganda" media del rnercado. Son rnuy flciles de prorneter per0 rnucho rnis dificiles de ofrecer. A la hora de crear aplicaciones o cornponentes de aplicaci6n, 10s requisitos corno nivel de reajustabilidad deben ser especificados y disefiados. La arquitectura subyacente de la aplicaci6n es un elernento clave a la hora de deterrninar si esos requisitos son asequibles. J2EE proporciona 10s cirnientos sobre 10s que puede construirse la arquitectura de las aplicaciones rnodernas Java, de ernpresa y de cornercio electronico. Ahora, con la versi6n 1.3, la plataforrna J2EE ofrece rnis sofisticaciones en el uso de Enterprise JavaBeans (EJB), apoyo XML nativo, seguridad perfeccionada y un sisterna gentrico de conectores de recursos. Aunque esto acarrea algunas herrarnientas y estrategias rnis, no cambia el rnodo fundamental en que se aplica J2EE. Las estrategias de disefio siguen siendo pricticarnente iguales. De hecho, la naturaleza del disefio es que la mejor aplicaci6n de herrarnientas y tecnologia s61o se descubre desputs de que tstas hayan sido utilizadas durante un tiernpo. El andlisis de 10s patrones presentados en este capitulo en una buena reflexi6n sobre esta cuesti6n. El carnbio desde la version 1.2 a la versi6n 1.3 de J2EE ha consistido, en realidad, en afiadir rnis funcionalidad per0 ?es una ventaja o una lacra? Recienternente, incluso 10s vendedores han llegado a cornprender que 10s desarrolladores necesitar ayuda para explotar el octano de funcionalidad que ya se encuentra a su alcance. Sun Microsystems ha creado las Directrices de Disefio Blueprints Sun para J2EE (referidas aqui como "J2EE Blueprints") y Java Pet Store para ilustrar las rnejores prdcticas para la plataforrna J2EE. Puede encontrar J2EE Blueprints en http://java.sun.com/j2ee/blueprints/. Consideraciones de diseho para aplicaciones J2EE N o existe un mod0 facil de obtener 10s conocimientos requeridos para un disefio efectivo de aplicacih en una plataforma de empresa. La version 1.0 de J2EE Blueprints tiene alrededor de 350 piginas. Ademis, existe tambikn una multitud de diversos recursos, como libros, e-mail/grupos de noticias, informes y articulos que proporcionan nuevas perspectivas, anilisis, consejos y, en ocasiones, opiniones controvertidas sobre la creaci6n de aplicaciones de empresa. A continuaci6n, una muestra de estos recursos: O Software Architecture in Practice, Bass, Clements y Kazman. ISBN 0-201-19930-0 O Client/Sewer Programming with Java and C O R B A , Orfali y Harkey. ISBN 0-471-24578-X O Enterprise JavaBeans, Second Edition, Mozon-Haefel. ISBN 1-565-92869-5 O The Java 2 Enterprise Edition Developer's Guide (referenciado en la documentacion J2EE y disponible enhttp://java.sun.com/j2ee/docs.html) O Lista de e-mail para debates sobre Patrones J2EE en Sun, registrese en http:// developer.java.sun.com/developer/technicalArticles/J2EE/patterns/WhatsNext.html O Debates sobre disefio en http://theserverside.com/discussion/index.jsp Los pensamientos y las opiniones que se encuentran en estas fuentes (y muchas mas) no pueden condensarse en un capitulo. Por lo tanto, el resto del capitulo examina algunos de 10s principales puntos del desarrollo de empresa y 10s tipos de solucion que se aplican en un entorno J2EE. Arquitectura y diseno El uso de 10s tkrminos "arquitecto" y "arquitectura" en el mundo del desarrollo de software es el tema central de algunos debates. En tkrminos de construccion, el papel de un arquitecto es razonablemente bien comprendido. En tkrminos de software, se utiliza regularmente y es intercambiable con el tkrmino "diseiio". La arquitectura de una aplicacion puede definir algunos o todos 10s puntos siguientes: O Los componentes que realizan las tareas de empresa de la aplicaci6n 0 El tip0 de interaccidn entre dichos componentes o Los servicios utilizados por esos componentes La plataforma subyacente que ofrece o apoya esos servicios O Otras caracteristicas o capacidades (como reajustabilidad) que se enfrentan a la no funcionalidad En conjunto, la arquitectura de una aplicaci6n proporciona un sistema en el que se pueden tomar decisiones individuales, de disefio detallado. La idea de que una aplicaci6n se ajusta a un determinado tip0 de diseiio puede contribuir a aclarar su estructura completa. A1 considerar estos temas, utilizaremos el tCrmino arquitectura en su significado general de la estructura o forma de una aplicaci6n. - Estilos de arquitectura Se hace referencia a arquitecturas basadas en servicios y arquitecturas constituidas por capas o gradas. Sin embargo, n o consiste en hacer una eleccion directa entre 10s tkrminos. Muchos sistemas utilizan aspectos de multiples estilos de arquitectura para resolver diferentes partes de su problema general. Capitulo 2 1 Las arquitecturas estratificadas y gradificadas tienen mucho e n comun. E n muchos sentidos, las arquitecturas gradificadas pueden percibirse c o m o una forma concreta de arquitectura estratificada. El principal objetivo es abstraer algunos elementos de u n sistema para simplificar la estructura general. Una capa o estrato representa u n cluster de funcionalidad o componentes que tienen caracteristicas similares, p o r ejemplo, tipo de funcion o localizaci6n fisica. Cada capa proporciona funcionalidad a las capas que le rodean. A1 analizar arquitecturas estratificadas, muchos pensarin en capas descendentes, como las que vemos en una pila de sistemas. En el modelo O I S de una pila de sistemas, por ejemplo, la capa de transporte hace uso de la funcionalidad provista por la capa de red, que, a su vez, utiliza la funcionalidad de la capa de vinculo de datos. Esta estratificacion proporciona a b s t r a c c i h de las capas subyacentes para permitir la sustituci6n. En tirminos de nuestra aplicacion, la plataforma JZEE proporciona multiples niveles: hardware, sistema operativo, J2EE y la misma aplicacibn, como se muestra en este diagrama: ---- Nlvel de Hardware 1 Puesto que la aplicaci6n se asienta sobre la plataforma JZEE, el hardware o sistema operativo subyacente puede ser modificado para proporcionar mejores caracteristicas (por ejemplo, mas rapidez, menos costes, rnis estabilidad) sin necesidad de rescribir partes de la aplicaci6n. Las arquitecturas de nivel son un tipo especifico de arquitectura estratificada basadas e n una vista del sistema centrada en el usuario. E s t o provoca una division desde la parte frontal hacia atris con el usuario situado en la parte frontal y 10s datos subyacentes (y demis) en la parte posterior. U n a tipica arquitectura de tres niveles consiste en: 0 U n nivel de interfaz de usuario que representa 10s datos de aplicacion para el usuario y, a travis de la cual, el usuario interactua con la aplicacion. O U n nivel de empresa que encapsula la 16gica de ernpresa de la aplicaci6r1, por ejemplo, 10s pasos implicados en la presentacion de una reclamaci6n de seguros. 0 U n nivel de datos que proporciona acceso a fuentes de datos subyacentes, como bases de datos, aplicaciones Enterprise Resource Planning (ERP) o sistemas principales. Este nivel tambiin se denomina a veces nivel de Servicios de Informacion de Empresa (EIS). Los niveles reflejan cierta forma de division fisica, de tal mod0 que 10s tres grupos de componentes existirin en diferentes procesos y, habitualmente, en diferentes miquinas. La comunicacion fluiri entre 10s diferentes niveles a medida qua la aplicaci6n realiza sus funciones. El uso de niveles hace que la separaci6n de problemas sea rnis ficil de juzgar. U n a d e las motivaciones clave para arquitecturas estratificadas en que reducen el acoplamiento entre componentes de diferentes capas. Los componentes altamente acoplados tienen conocimientos detallados de 10s otros componentes con 10s que interactuan. Esto significa que son rnis dificiles de sustituir o de reubicar individualmente. Definiendo las funciones en conjunto desempehadas por 10s componentes en cada nivel, resulta rnis ficil crear interfaces fijas entre niveles y reducir asi el acoplamiento entre 10s componentes de esas capas. La separacion de la interfaz de usuario, la logica de empresa y el acceso a datos nos permite sustituir mejores productos o ticnicas en cada nivel sin perturbar a1 resto. Esto desemboca en una aplicaci6n rnis flexible. Consideraciones de diseiio para aplicaciones J2EE U n a aplicaci6n t a r n b i h puede utilizar una arquitectura gradificada por rnotivos de reajustabilidad. El desacoplarniento entre niveles nos perrnite afiadir rnis capacidad a cada nivel a rnedida que el sisterna se reajusta. U n ejernplo consistiria en afiadir rnis servidores Web en el nivel de interfaz de usuario para servir a rnis clientes. Esto n o requeriria autorniticarnente rnis servidores de bases de datos en el nivel de datos (aunque podria). Podernos ver a continuaci6n una arquitectura de tres niveles de base Web: Grada EIS I I 4 Serv~dorde Datos I' Chente Web Nwel de Presentac~bn N~vel U n a arquitectura basada en servicios percibe 10s cornponentes de u n sisterna en tkrrninos de servicios de caja negra. U n ejernplo desde el punto de vista del nivel de sistema seria un servicio de transacci6n, corno el A P I de Transaccion Java (JTA) provisto p o r J2EE. E n este caso, el usuario del servicio s610 se encarga de la interfaz y de las caracteristicas del sisterna, n o de su irnplernentacion. Las arquitecturas basadas en servicios pueden ser percibidas corno una forrna mayor de arquitectura de cornponentes puesto que las aplicaciones serin creadas por prograrnas de creaci6n o directivas que invocan diferentes servicios para ejecutar sus tareas requeridas. El concepto de u n servicio cornienza a alejarse del concepto de clientes y servidores fijos puesto que 10s servicios pueden solicitar a otros servicios que realicen sus tareas. N o existe ningun requisito irnplicito para que las llarnadas fluyan en una direction concreta. Los servicios pueden ser verticales u horizontales: 10s servicios verticales reflejan requisitos funcionales, corno servicios de aprobaci6n para pedidos de cornpra, rnientras que 10s servicios horizontales proporcionan rnecanisrnos subyacentes, como autentificacion o persistencia. Contexto de diseno El software se desarrolla para resolver u n problerna. Ese problerna puede ser de naturaleza ernpresarial, tip0 c6rno reducir la cantidad de tiernpo que supone para una organizaci6n procesar el pedido de u n cornprador, o puede ser rnis tkcnico, corno garantizar que un sisterna de control por satilite responde correctamente cuando se le instruye para rnodificar la trayectoria. E n arnbos casos, n o se puede ernitir u n Capitulo 2 1 juicio absoluto de la calidad de la soluci6n propuesta. So10 se puede juzgar la soluci6n en el contexto del problema que debe ser resuelto. Considere el diseiio de un avi6n. La sabiduria convencional sugeriria que la estabilidad es un factor muy importante para el disefio de un avi6n. Sin embargo, muchos modernos aviones de guerr? son diseiiados intencionadamente para ser inestables puesto que esto mejora su capacidad de maniobra. Esta es una buena decision de disefio para un caza puesto que una ligera mejora en la capacidad de maniobra puede suponer la diferencia entre el kxito o el fracas0 de una misi6n. Asimismo, las organizaciones que utilizan aviones estin dispuestas a pagar 10s caros sistemas de procesamiento informitico que contribuyen a convertir una miquina inestable en una miquina que puede ser controlada por un piloto humano. Si modifica el contexto del problema, por ejemplo analizando en un pasajero del avian, las consideraciones de seguridad son primordiales. De repente, la estabilidad se convierte en un punto muy importante, mucho mas que la capacidad de maniobra. Para un avi6n de este tipo, la capacidad extra de maniobra no merece arriesgar la seguridad o el coste de sistemas operativos extra para controlar un avi6n inherentemente inestable. Por ello, la correcta decision de diseiio en un contexto puede, en un contexto ligeramente diferente, ser la decision err6nea. Ninguna decision de diseiio es inherentemente buena o mala, todo depende del contexto y de 10s factores internos y externos que influyan en el disefio (a menudo denominados fuerzas). Esto se aplica a1 modelado de la soluci6n propuesta y a la asociacion del modelo a la plataforma subyacente. Entonces, % 1 1..* - FachadadeSesh 1 ..* . Objeta de Empresa L < < U B de EnI~dadz > < > ObJetode Empesa2 ObJetode Empresa3 H Objeto de Acceso a Datos Una Fachada de Sesi6n encapsulard habitualmente la funcionalidad para uno o mis casos de uso de empresa. Puede conseguirse m6ltiples operaciones de empresa a travis de una llamada a la fachada (esto se denomina en ocasiones patr6n/locuci6n distribuida de Mitodo de Lote). En lugar de un bean de sesi6n que devuelve un grupo de Objetos Valor que deben ser tratados por el cliente, la operaci6n que el cliente desea realizar puede ser trasladada a la Fachada de Sesi6n. La iteraci6n en 10s datos tiene lugar en el servidor solo con 10s resultados pasados de vuelta a1 cliente. Esto reduce el trifico de la red, a pesar del coste de cierto sobregasto de procesamiento del servidor. Patrdn de localizador de sewicios En tirminos de c6dig0, el sobregasto de utilizar 10s metodos sobre una interfaz de empresa de EJB es relativamente pequeiio (simplemente el manejo de excepciones remoras). Sin embargo, la creaci6n de EJB requiere c6digo de base JNDI, especifico, para descubrir la interfaz inicial y crear el EJB requerido. Esto obliga el cliente a incluir c6digo J N D I que se encargue de la creaci6n del contexto, las blisquedas y la reducci6n de referencias. De nuevo, cualquier sofisticaci6n adicional, como cachetizar las referencias de interfaz inicial, debe ser duplicada por cada cliente. El patr6n de Localizador de Servicios define c6mo un linico objeto puede realizar las tareas de blisqueda y creaci6n asociadas a mliltiples EJB para mliltiples clientes. El cliente simplemente encuentra el Localizador de Servicios y solicita una referencia para el EJB requerido. Toda interacci6n con las interfaces inicial J N D I y EJB se delega en el Localizador de Servicios. El siguiente diagrama de secuencia muestra la interacci6n entre el cliente, el Localizador de Servicios y las implementaciones de empresa e iniciales EJB: Consideraciones de disefio para aplicaciones J2EE Obtener instancias Obtener Objeto Busqueda I Fadoria 1 Obtener Objeto de ~&resa I I I I de empresa 1 1 I I I I I I I I I Cresr un Buscar -I I I I -.- < > Objetode Ernpresa - I I * Observe que el Localizador de Servicios se implementa habitualmente con10 un semifallo con el objetivo de compartir 10s beneficios del uso de la cachC. Patrbn de Objeto valor Los sinlples objetos de datos expondrin normalmente sus datos como propiedades. Un cliente accederi a esas propiedades utilizando mCtodos set o get siempre que fuera necesario. El sobregasto relativamente bajo asociado a llamadas de mCtodo durante el proceso ha hecho de Csta una prdctica comlin, particularmente en entornos tip0 Integrated Development Environments (IDE) para crear interfaces de usuario basadas en JavaBeans. Sin embargo, una vez se ha introducido una red entre el cliente y el objeto de datos, esta programaci6n basada en propiedades provoca un feo efecto "diente de sierra" ya que 10s datos pasan constantemente en ambas direcciones a traves de la red. Cuando esto sucede. la comunicaci6n domina el procesamiento, la mayor parte del tiempo requerido para acceder a datos se invierte en esperar que regresen las llamadas de red y el rendimiento de la red se degrada debido a la gran cantidad de datos pasados. Esta cuesti6n puede verse a1 acceder a datos o a semicios centrados en datos expuestos por EJB. El efecto se amplifica si 10s datos se propagan a mGltiples EJB, puesto que se debe acceder a cada EJB de forma individual por la red. Capitulo 21 O t r a considerncion a tener en cuenta nqui es la mayor parte cle 10s accesos a 10s datos t i m e c o m o objetivo la lectura en lugar de la escritura. Estos problemas pucden resolverse mediante la creaci6n de un O b j e t o Valor. El O b j e t o Valor encapsuln datos de empresa en forma d e un objeto Java ordinario en lugar d e un pesado objeto distribuido c o m o un EJB. En lugar de realizar multiples solicitudes, cadn una para una propicdad d e EJB, se emite una unica solicirud a u c dcvuelve el O b i e t o Valor. El O b i e t o Valor s e r i asa ado de vuelta al cliente, habirualmente mediante scrinlizaci6n ~ a v aEI . cliente accede entonces a las Gopiedades del O b j e t o Valor en s u espacio de direcci6n local, ahorrando asi muchas idas y venidas por la red. La relacion entre el EJB y su O b j e t o Valor ri"; Objeto V a k r La inrcraccion cntre el cliente, el EJB y el O b j e t o Valor es la siguiente: Consideraciones de disefio para aplicaciones J2EE 4 El Objeto Valor en realidad consiste en d o s instancias fkicas, una en el sewidor y otra en el cliente Hay difercntes variacioncs que puedcn ser utilizadns dependiendo dc los requisites de la aplicClci6n.El Objcto Vnlor puedc enc.lpsular stilo parte dc los datos de empresn rcpresentados por el EJU, podria ser actualizndo con c,lmbios propagados d e vuelta a su EJB progcnitor, o el Objeto Valor poclria adoptar In forma d e un docurnento XML si se rcquiere interoperatividad distinta de Java. Los objetos valor pucden ser utilizltlos con EJB de entidad, EJB de sesion y Objetos d e Acceso n Datos nllidondc sea adccundo. Patron de Delegado de empresa N o es una bucna idea que los clicntes interactljcn directmnente con servicioh de cmpresa. Esto les cspone a c ~ m b i o spotenciales en In implerncnt,~cicin.Es posible encapsulnr pnrte de In internccion con servicios de cmpresa cn un ljnico EJB aplicanclo el patr6n de Fachada d c Sesi6n. Incluso asi, el cliente todavia tiene que hacerse cargo d e la blisqueda, la instanciaci6n y el rnanejo de crrores rcmotos requerido pala rnanipular un EJB. Cualquier sofisticaci6n mayor en el tratnmiento con la cnpa de empresn, corno el almacemmiento e n cnchi y agrupacion por lotes de llamndas tambi6n quecla en manos del cliente. C o m o soluci6n. un Dclcgado d c Ernprcsa ncthn c o m o unn ;ibstracci6n de lado cliente de un servicio cle cmpresa. Puedc potencialmente funcionnr directnmente con cornponentes individuales de empresa o puede .lctuar como la pnsarela dc lado clicnte a unn Fachada d e Sesi6n. El Delegado d e Ernpresa se encargari de toda la intcracci6n especifica d e EJB y proporciona una interfaz local para el cliente. Esta interfaz puede proporcionnr metodos que sinran para encapsul~rrnljltiples inter.lccioncs de servidor. El Delegndo de Empresa tanrbiin puedc nsociar cxcepciones remotas a escepciones de aplicacibn con significado. El Delegado de Ernpresa es el espacio 16gico para ejecutar el almacenamiento en cache de lado cliente de inforrnaci6n de ernpresa, como Objetos Valor, o para reintentar llnmadas f,lllidas o relevos a diferentcs servidores. La relaci6n entre el cliente, el Delegado de Ernpresa y el objeto de ernpresa es la siguiente: Capitulo 21 'F'-l+. L. y crear .Buscar Cliinte - . 1 ..* 1 4 Delegado de Ernpresa I..*- , r, --.A * Objelode Empresa P P cz Objeto de Ernpesa2 ObJetodaEmprew3 i El Localizador de Serviciosdel diagrama d e clase es o t r o patr6n que puede ser utilizado por separado o en conjunci6n con un Delegado de Ernpresa. De nuevo, la intention es ocultar las complejidades de tratar con servicios de nombrado y proporcionar una localization conveniente para aiiadir almacenamiento en cache y optimizaciones a la recuperaci6n d e referencias a objetos d e empresa y sus factorias. Patron de Objeto de acceso a datos Casi todas las aplicaciones utilizan datos de algun tipo. Estos datos pueden ser almacenados en diversos sitios, como bases de datos, sistemas principales, ficheros planos u otros servicios externos. El c6digo de empresa y d e interfaz d e usuario d e la aplicacidn requeriri acceso a 10s datos para ejecutar tareas para el usuario. Las tareas llevadas a cabo sobre 10s datos son normalmente indevendientes de c6mo son almacenados esos datos. Incluir c6digo especifico d e acceso a datos en la 16gica de ernpresa y d e presentation vincula ese c6dicro ., a una fuente esvecifica d e datos. Esto reduce la flexibilidad de la soluci6n puesto que el c6digo requerirj. cambiar sie~npreque cambie la fuente de datos. Los cambios efectuados la fuentes de datos subyacente puede incluir un cambio d e base d e datos (Servidor S Q L a Oracle, por ejemplo) o carnbios al modelo global como migrar desde el acceso a datos basado en JDBC a acceso a travis de EJB d e entidad. La soluci6n consiste e n proporcionar un Objeto de Acceso a Datos ( D A O ) para abstraer el acceso a 10s datos. EL D A O encapsular6 el c6digo requerido para localizar y acceder a la fuente de datos. Toda la 16gica de empresa o d e presentaci6n utilizarj. el D A O para recuperar y almacenar datos como se muestra a continuaci6n: -. -- nte de ~ a t ~ ; 1 Consideraciones de disefio para aplicaciones J2EE La interfaz de DAO define la rehcidn entre la lbgica de empresa o de presentacidn y 10s datos. Si el mecanisrno de localizacidn subyacente y de almacenamiento utilizado para acceder a 10s datos cambia, puede crearse un nuevo DAO para acceder a 61. Puesto que el DAO tiene una interfaz fija para sus clientes, Csta no requeriri ningfin cambio en la 16gica de empresa o de presentacidn, como se muestra a continuation: i I I utiliza 1 encapsulado base de datos Sybase La verdadera implementacidn del DAO variari dependiendo del contexto. Si el cliente es una JSP, el DAO puede ser una clase Java ordinaria, un servlet o un EJB. Si el cliente es un EJB, entonces es probable que el DAO sea una clase ordinaria Java o posiblemente otro EJB. Patron de Ayudante de vista Una inadecuada divisi6n entre mecanismos de presentacibn y lbgica de empresa desemboca en sistemas inflexibles y costes crecientes de mantenimiento. El uso de piginas JSP para interfaces de usuario de base Web es un ejemplo fundamental, ya que es ficil incluir demasiado cbdigo Java en la JSP. Si este cddigo adopta la forma de 16gica de empresa, entonces esto sirve para aumentar el acoplamiento entre ldgica de presentacidn y ldgica de empresa, que es perjudicial para la flexibilidad. Bien sea el cddigo de empresa o de presentacibn, la inclusidn de grandes cantidades de c6digo Java en una JSP significa que no puede ser mantenida y adaptada hicamente por diseiiadores Web. Tambi6n provoca potencialmente la repeticidn de cbdigo en distintas piginas JSP. Utilizando el patrdn de Ayudante de Vista, el cddigo Java es encapsulado en clases de ayuda, como JavaBeans o etiquetas personalizadas. La vista delega el procesamiento de empresa o de presentacidn en el objeto ayudante. En el caso de una JSP, elimina el cddigo de la JSP y permite a 10s diseiiadores Web interactuar con 61 mediante el uso de etiquetas JSP estindar o personalizados. A continuaci6n, se muestra una tipica interacci6n de secuencia: Capitulo 21 0 Observe cbnio, en este caso, la vista simpleniente instancia el avudante v obtiene 10s datos de 61. Si el ayudante es implementado como un ~ a v a ~ c auna n , JSP puede &ceder a ia funcionalidad requerida a travks de las etiquetas e s t i n d a r u s e ~ e a ny g e t p r o p e r t y . En este caso, el ayudantc accede a la funcionalidad d e ernpresa; sin embargo, 10s Ayudantc d e Vista tarnbiin pueden scr utilizados para encnpsular procesarniento d e presentaci6n o estado temporal. Patron de Vista de lanzador Este patr6n sugiere un mod0 de combinar 10s patrones de Controlador Frontal y d e Ayudante dc Vista con el objetivo d e crear unn soluci6n integrada para 10s problcrnas a 10s que se enfrentan. Estos problemas incluyen ldgica d e ernpresa repetida y dispersa, la necesidad dc separar flujo d e trabajo d e presentaci6n y la necesidad d e imponer servicios comunes como la autentificaciAn. El patr6n de Vista d e Lanzador es una cornbinacion de un Controlador Frontal y mhltiples vistaa y Ayudantes de Vistas. A diferencia del patron de Servicio al Trabajador (que analizarenios a continuacicin), en 1.1 Vista de Lanzador el Controlador Frontal y el lanzador n o instancian Ayudantes de Vista y utilizan sus datos para deterrninar la vista d e destino. Cualquier seleccibn de este tipo se realizari basindose en inforrnaci6n d e la solicitud del usuario. Cuando se propaga la solicitud a la vista, 10s Ayudantes d e Vista apropiados serin instanciados y accederin a 10s datos requeridos por la vista. La relaci6n entre las diferentes clases es tal y c o m o se muestra en esta figura: c r 1 Cliente 1 Controlador Frontal 1 % Lanzador 1I..*. Vista - Ayudante ,,* . 7 C o m o puede ver, en este rnodelo todos 10s accesos a datos esternos tienen lugar solo despuks de acceder a la vista. Consideraciones de disefio para aplicaciones J2EE Patron de Servicio al trabajador Este patr6n sugiere un nlodo d e combinar 10s patrones d e Controlador Frontal y Ayudante de Vista con el objetivo d e crcar una solucicjn integrada para 10s problemas a 10s que se enfrenta. Estos problemas incluyen 16gica d e empresa repetida y dispersa, la necesidnd de separar flujo de trabajo de presentacibn y la necesidad de imponer servicios comunes con10 autentific~ci6n. El patr6n de Servicio al Trabajndor esti bahado en un Controlador Frontal. El Controlador Frontal delega el acceso a datob en Ayudantes de Vihtd, que son creados y poblados antes d e acceder a la vista. U n I.~nzador,que forma parte del Controlador Central, decide quC vista nlostrar al cliente y propaga la solicitud junto con 10s Ayudantes d e Vista. La relacicjn entre Ins diferentes clases se muestra a < r Vista I 1 1 I 1 1 I..*I..* I Ayudante Avud LAprincipal diferencia entre este patrcin y el de Vista de Lanzador es que Servicio al Trabajador es m i s pro pi ado alli donde se requiere procesamiento frontal. El Controlador Frontal y el lanzador interactlian con 10s Ayudantes de Vista antes de reenviar la solicitud a la vista. Por ejemplo, en Servicio al Trabajador, algunos de 10s datos recuperados pueden en realidad controlar la viata a la que se lanza la solicitud. Patron de Manejador de lista de valores (Iterador pirgina-a-pagina) Al acceder a grandes cantidades de datos, el cliente debe intentar evitar repetidas solicitudes de red para acceder a cada objeto de datos sucesivamente. Este sencillo uso de objetos remotos que encapsulan datos, como EJB de entidad, por ejemplo, pueden ser muy ineficientes en tC-rminos de uso de recursos d e red y de servidor. El Manejador de Lista d e Valores se implemente comirnmente como un bean de sesi6n con estado que consulta fuentes d e datos subyacentes para obtener 10s datos requeridos. La fuente de datos podria ser una base de datos, un conjunto d e EJB de entidad o cualquier otra fuente de datos encapsulados como un Objeto de Acceso a Datos. Los datos serin almacenados en la memoria caches y despueh proporcionados nl cliente al ser solicitados. La relaci6n entre un cliente Web, un Manejador de Lista de Valores y un conjunto de EJB d e entidad subyacentes es la siguiente: Capitulo 21 ' lor de 4 laloreg .- Nivel Web -- -- I I I I El patron de Manejador de Lista de Valores generari Objetos Valor para representar 10s datos subyacentes. Estos Objetos Valor se guardarin en cache y ofrecidos de vuelta al cliente al ser solicitados. El cliente puede controlar el nlirnero de Objetos Valor devueltos en una vez a travks de la interfaz iteradora. Las relaciones entre las clases irnplicadas se rnuestran en el siguiente diagrarna de clases: -El Objeto Valor Lista de Valores I ) proporciona datos I --" Consideraciones de diset7o para aplicaciones J2EE El diagrama de secuencia tiene este aspecto: Obtener datos -&llect~on> Obtener pr6x1mo I I I I I I I I I I I I I subconjunto 4- - - -- --- I I I I Observe que este patron es denominado Manejador d e Lista d e Valores en el catilogo d e Patrones JZEE de Sun Java Center per0 que, Blueprints JZEE de Sun, aparece como Iterador Plgina-a-Plginn. Patron de Lector de via rapida Aunque 10s EJB de entidad son un potente mecanisrno para acceso concurrente a datos y persistencia, son bnatante pesados para enumerar grandes cantidades d e datos. Tomando el ejemplo de enumeration de datos e n un catilogo, el requisito habitual consiste en obtener datos d e solo lectura para navegar. Asimismo, 10s datos subyacentes cambiarin con poca frecuencia y n o es esencial que cualquier instantdnea de datos refleje el Gltirno estado absoluto de 10s datos. Acceder a estos a travks de metodos buscadores de EJB tendrd como resultado la creaci6n de muchos EJB para poco trabajo de utilidad. Esto supone un gran sobregasto en una situacibn en la que la velocidnd es normalmente el factor clave en la utilidad d e la aplicacibn. La solucion es evitar 10s EJB d e entidad asociados a 10s datos y acceder a 10s datos de forma m i s directa a travks d e un O b j e t o d e Acceso a Datos. U n D A O d e este tipo encapsularia normalmente acceso a base de datos, por lo que, efectivamente, 10s datos proceden directamente de la base de datos. Esto provocaria un mayor rendirniento sin deseatabilizar la aplicacibn. El Lector de Via Rdpida puede irnplementarse como un DAO o como un EJB de Sesion que acttie c o m o m a Fachada de Sesi6n para DAO. La relacion entre el cliente y el Lector d e Via Rdpida es la siguiente: Capitulo 2 1 7 Lector de Via Ra id I \r"" ut~lizapara actualizar Objeto de Empresa E l A h a , armados con los detalles de fondo d e estos p.itroncs de disciio, podcmos comcnznr con continnza el anilisih del principio de nuestra .iplicaci6n de orden de compm, nnturalmente con una lista de productos. Comenzar por el principio Debelnos comenznr el esamcn del sistcma por algun lugar, asi quc vamos a empeznr con lo primer0 que necesita cl usuario: 10s productos catalogaclos. Puesto que el sistema d e pedidos d e compra debe scr utilizado c o m o parte de una Intranct, necesitaremos proporcionarle una interfnz HTML. Pnra gcnernr el H T M L rcquerido, la interfaz de usuario, como la funcionnlidad del catilogo de productos, podria ser implernentada como un conjunto de JavaSenrer Pages (piginas JSP) o d e servlets. D e las dos tecnologias, las piginas JSP s o n m i s adecuadas para la g e n e r a c i h d e HTML, por lo que la interfaz de usuario parn Flujo d e Trabajo d e Pedidos (Ordering Workflow) y Flujo dc Trnbnjo de Aprobacicin (Approvnl Workflow) del sistema de pedidos de compra (rernitase a nuestro diagrama U M L original) consistiri en gran medida en un conjunto d e pjginas JSP. Sin embargo, 10s servlets tambikn desemperiarin un pnpcl importante en la provision de servicios cornunes y en el control del flujo tle trabajo p m estas p x t e s dcl sistemn. Observe que lo siguiente n o e s un anilisis sobre el m o d o en que, en realidad, funcionan 10s servlets y piginas JSP, puesto que ya hemos dado suficiente cobertura a estos ternas en capitulos antcriores. En su lugar, se revisarin cicrtos nspcctos de cstns tecnologias dcsde el punto de vista del cliseno. Presentacion de datos del producto al usuario Podernos csplorar algunas de 12s principales cuestiones de disefio de JSP y de servlets considerando c6mo podrian irnplernentarse ciertns partes dcl Flujo de Trabajo de Pedidos. Al catnlogar productos para su selection por parte del usuario, el uso d e una o niis piginas JSP podria funcionar. Los datos del producto pueden obtenerse directamente desde la basc de datos a travbs d e JDBC. Esta sencilla arquitectur~cs la que mostramos J continuaci6n: Consideraciones de diseiio para aplicaciones J2EE JSP reserva de conexiones Base de datos lncluso en esta sencilla etapa, pueden tomarse decisiones de diseiio para crear un sistema m i s flexible y mantenible. U n aspecto es el uso de las reservas de conesiones d e bases de datos para contribuir a la capacidad de reajustabilidad cornpartiendo de un modo rnis efectivo las conesiones d e bases de datos entre piginas JSP o servlets quc Ins utilicen. La cuestidn de la reajustabilidad y el reciclaje de recursos seanalizarj. rnis adelante en cste capitulo. El acceso a 10s datos de producto se requeriri probablernente desde el interior piginas JSP. La5 piginas JSP facilitan relativamente la combinaci6n del diserio visual d e interfaces de usuario con el c6digo Java requerido para extraer 10s datos de producto de la base de datos. Si retrocedernos un momento, podemos definir algunos principios d e guia que pueden beneficiar este sencillo diseiio: 1-1 Abstraer el acceso a datoh 3 Distinguir entre funcionalidad y presentaci6n 3 Separar el control de la interacci6n de usuario de la presentacibn y el manejo de datos Examinemos cada uno d e estos puntos por separado. Abstraer el acceso a datos De andisis previos sobre patrones de disefio J2EE hemos aprendido que, en casos en 10s que un componente recupera datos, pueden obtenerse beneficios utilizando un Objeto d e Acceso a Datos ( D A O ) para abstraer la fuente de datos subyacente. Si n o sabemos si la fuente de datos subyacente cambiari con el tiempo, un D A O aporta mucha flesibilidad. Por ejemplo, en el caso del sistema de pedidos de compra, la implementaci6n inicial del catilogo puede conllevar el acceso direct0 a la fuente de datos a trav6s de JDBC. A medida que evoluciona el sistema, el uso de fuentes de datos de terceros puede requerir el uso de EJB o d e x c e s o basado en senicios Web. Si deben incorporarse mdtiples catilogos de proveedores, el cddigo asociado d e empresa y d e presentaci6n puede convertirse ripidamente en un desorden de instrucciones cabo. El uso de un D A O permite aiiadir nuevas fuentes d e datos de un modo relativamente inofensivo. Los inconvenientes de utilizar un D A O son dos: 3 Casi cualquier forma de abstracci6n conlleva fases y manejo de datos extra. Esto significa que el rendirniento puede verse afectado. Se requiere inicialmente m l s esfuerzo en diseiio y en c6digo para implementar en D A O . Igual que sucede con cualquier decisi6n d e disefio, siempre hay una concesi6n. Tendri que decidir si las ventajas de flesibilidad y mantenibilidad de un D A O pesan m i s que la cantidad que esfuerzo inicial extra Capitulo 2 1 rcquerido y la reduccidn potencial del rendimiento. Puesto que el sistema de pedidos de compra abarca a mdtiples proveedores, casi con toda probabilidad merceria la pena realizar este tip0 de inversion importante. Distinguir entre funcionalidad y presentacion El principal dogma de disefio para piginas JSP es elirninar la mayor cantidad de c6digo posible de las piginas. Esta separaci6n de la presentaci6n y el c6digo tiene rnuchas ventajas, tales corno: 2 El c6digo cornGn puede ser cornpartido por mGhiples piginas, proporcionando servicios comunes y reduciendo en esfuerzo de mantenimiento U La reduccicin o eliminaci6n del c6digo facilitari la vida a1 diseiiador de piginas Web sin c6digo 3 La mayoria de 10s cambios en el funcionarniento del c6digo no requeriri las piginas que utilicen ese c6digo para ser editados Esto garantiza que cualquier uso de las piginas JSP rnis all; de las formas rnis sencillas irnplicari esta distinci6n entre HTML y codigo Java. La separaci6n puede tornar diversas formas, incluido: a El c6digo para la pigina puede ser encapsulado en alguna forma de componente Java siguiendo el patron de Ayudante de.Vista u Las piginas Web que comparten elementos cornunes de funcionalidad, de information o de navegacion pueden ser construidas a partir de un conjunto de cornponentes comunes siguiendo el patr6n de Vista de Cornposici6n El uao del patron de Ayudante de Vista reduce la cantidad de c6digo necesario en las piginas JSP que proporcionarin la presentacion para el Flujo de Trabajo de Pedidos y el Flujo de Trabajo de Aprobaci6n en nuestro sisterna de pedidos de cornpra. Que 10s ayudantes sena JavaBeans o etiquetas personalizadas depender6 del contest0 especifico en el que se necesite un ayudante. Puede que se decida utilizar un estilo de ayudante, corno JavaBeans, de forma consistente para contribuir a la mantenibilidad o a la cornpatibilidad descendente, Es conveniente seiialar que 10s patrones integrarin y utilizarin otros patrones. Por ejemplo, dada la decisi6n anterior de utilizar D A O en el sistema de pedidos de compra, siempre que el c6digo de la implementaci6n del Ayudante de Vista necesite acceder a datos, utilizari el D A O adecuado. Este tip0 de relacibn es tipica de un lenguaje d e patrbn, en lugar d e ser solamente una lista de patrones. Los patrones de u n lenguaje d e patrones mantienen s d i d a s relaciones. Cada patr6n resuelve problemas concretos dcntro &I sistema y dele@ funcionalidad e n implementaciones para otros patrones siempre y cuando sea apropiado. D e nuevo, n o se trata Bnicarnente d e cxtraer una soluci6n a partir d e un puzzle de patrones, sin0 que ciertos patrones funcionan bien juntos y se encuentran comfinmente desempeiiando funciones similares en sisternas similares. La interfaz de usuario de Flujo de Trabajo de Pedidos p de Flujo de Trabajo de Aprobaci6n consistiri en piginas HTML, o vistas, que contengan catilogos dc productos y forrnularios que debe cumplimentar el usuario. La usabilidad de un sistema quc, contenga mdtiples vistas se ve reforzada en gran medida proporcionindole un nivel de consistencia en estilo y contenido (por ejemplo, posicion y contenido consistentes de una barra de navegaci6n). En una interfaz de usuario de este tipo, h a b d ciertas partes consistentes de la pantalla del usuario rnientras que el resto varia dependiendo del contexto, como ir desde la vista detallada del product0 hasta vista del pedido de compra completo. Consideraciones de disefio para aplicaciones J2EE Este estilo d e interfaz d e usuario puede alcanzarse aplicando el patr6n de Vista de Composition para romper sub-vistas coniunes, c o m o cabeceras y navegaci6n, y volver a combinarlas con contenido especifico de vistas. Aden& de proporcionar consistencia para el usuario, la Vista d e Conlposici6n facilita el niantenimiento y desarrollo del sistema. C o n i o ejemplo, la navegaci6n en todas las vistas existentes puede ser actualizada simplemente actualizando la sub-vista de navegaci6n compartida. Igualmente, la creaci6n de una vista nueva se simplifica puesto que sus partes de mayor tamafio pueden ser estraidas de plantilla. Unn variaci6n a destacar aqui consiste en que algunas partes del Flujo d e Trabajo d e Aprobaci6n pueden estar destinadas inicamente a gestores (con10 cifras sobre niveles actuales de presupuesto del departamento). E n este caso, la Vista de Composici6n proporciona estrategias que implican a gestores de vistas que puedcn actuar como filtros sobre la presentaci6n del contenido. Por ello, un gestor puede ver diferente contenido en una pigina de registro de pedido que un usuario nienos privilegiado. Separar interaccion de usuario, presentacion y datos Estrategias corno el Ayudante d e Vistas proporcionan u n rnodo conveniente de separar 16gica de ernpresa d e 16gica d e presentacibn. Si embargo, cierta 16gica de aplicaci6n funciona mejor al ser procesada antes de acceder a la vista. C o m o sugieren sus nombres, Flujo de Trabajo de Pedidos y Flujo de Trabajo de Aprobaci6n requieren ambas una secuencia de pasos que deben ponerse en prictica para guiar al usuario a travCs de 10s procesos de pedido y aprobaci6n. Si se pierde un paso, puede perderse informacidn vital, dando lugar a u n pedido incorrecto. LIsccuenciaci6n d e tales pasos puede construirse en las vistas. Cada vista tendria vinculos hacia las vistas posterior y anterior en el flujo de trabajo. Sin embargo, esto da lugar a un flujo de trabajo muy fdgil que no puede alterarse ficilmente. La soluci6n es separar el flujo d e trabajo de la vista, rnanteniendo cada vista independiente en su lugar e n el flujo d e trabajo y atiadiendo el potencial para reutilizacion d e vistas. Podernos considerar al Ayudante del Vistas corno un m o d 0 de separar el flujo de trabajo, per0 la cuesti6n clave aquies que estas decisiones de flujo de trabajo necesitan tomarse antes de que se acceda a la vista. Se necesita un mecanismo que intercepte la solicitud del usuario, que determine ddnde se encuentra el usuario en el flujo de trabajo actual y que lo lance entonces a la vista apropiada. Para llevar a cabo este tipo d e procesaniiento previo, podemos introducir un servlet para que actue como Controlador Frontal, tal y c o m o se define en el patr6n de Controlador Frontal, analizado anteriormente. El Controlador Frontal es habitualmcnte un sewlet cuya linica tarea en la vida es procesar information de entrada de usuario (en ocasiones Ilamada gestos de usuario). El s e n l e t n o contiene c6digo para generar salida para el usuario; en su lugar, captura datos procedentes del usuario, 10s procesa y decide qu6 vista debe ser mostrada a1 usuario. En t6rminos de aplicaci6n de orden de compra, el Controlador Frontal es el lugar ideal para albergar procesamiento comun tipo autentificacibn. La autentificacion es particularmente iniportante puesto que tanto la presentaci6n como la aprobaci6n d e pedidos d e cornpra depende firrneniente de autentificar la identidad del usuario. C o n i o henios niencionado anteriorrnente, algunas de las Vistas de Composici6n del Flujo d c Trabajo d e Aprobaci6n quizis s61o muestren cierta informaci6n a los gestores. Es por lo tanto esencial que la autentificacibn siempre se lleve a cabo antes de acceder a las vistas (observe que esto n o significa que el usuario tenga que registrase antes de cada vista d e pigina; sirnpleniente significa que se comprueban las credenciales para algunos formularies. Esto puede adoptar In forma d e un cuco de autentificacibn pasado desde el navegador del usuario). El Controlador Frontal es el lugar ideal para afiadir estos servicios comunes. Capitulo 21 U n sistema puede tener m6ltiples Controladores Frontales. En el caso de nuestro sistema de pedidos d e compra, habrd como minimo dos: u n o para el Flujo de Trabajo d e Pedidos y otro para el Flujo de Trabajo de Aprobaci6n. Estos Controladores Frontales proporcionardn flujo de trabajo durante la creaci6n y aprobaci6n de pedidos de compra. Para garantizar que el c6digo de autentificaci6n (y cualquier o t r o servicio comun) es compartido por 10s Controladores Frontales y son reimplementados cada vez, el Controlador Frontal puede delegar la aplicaci6n d e tales servicios e n otros objetos o componentes. El Controlador Frontal tambiCn puede realizar procesamiento ndicional que construya estado, utilizndo por 1.1 vista a la que se reenvin la solicitud. Este estado es pnsado como objetos de ayuda. Un Controlador Frontal que utiliza objetos ayudantes es parte de una via hacia la arquitectura de Controlador de Vista dc Modelo (MVC) popularizada por Smalltalk y utilizada en m a forma niodificadn en In Clases de Fundacibn Java (JFC). El Controlador Frontal contiene el conocimiento de lo que deberin suceder en un punto determinado del tiempo en respuesta a un gesto de usuario. La,Vista refleja el estado de estn parte del sistema a1 usuario. La parte final de la ecuaci6n es el Modelo. Esta es 1.1 pnrte de datos del sistema. La vistn hace referencia al modelo para recuperar 10s datos que debe niostrar al usuario. El controlador alterari el estado y 10s contenidos del niodelo de forma apropiada basindose en 13 entrada de usuario. La siguiente figura muestrn c6mo priginas JSP, servlets y JavaBcans pueden ser utilizados para crear un modelo que reparte responsabilidades del mismu mod0 que MVC: L7s clases dc Ayudantes de Vista que conformnn el modelo pueden ser sencillas representaciones de datos recuperados por el Controlador Frontal. Alternativamente, estas clases pueden encapsular el acceso a datos para esta parte del sistema. Los dntos representados pueden ser recogidos de la solicitud del cliente o recupcrados desde una fuente de datos cn el servidor. El precis0 equilibrio de responsabilidades entre el Controlador Frontal, 10s Ayudnntes de Vistas y Ins vistas variari dependiendo de la cantidad de recupcracibn de datos necesaria y de si la solicitud puede ser encaminada sin que otros datos sean recuperados. Dos "macro-patrones" que son descritos en cl cntdlogo de Patrones J2EE de Sun Java Center, Servicio a Trabajador y Vista de Lanzador, analizan conlo pueden compartirse estas Consideraciones de disetio para aplicaciones J2EE responsabilidades. Aunque estos patrones han sido presentados anteriormcntc en este capitulo, merece la pena csaminar su documentation completa para llevar a cabo un esamen m i s eshaustivo. Existe un grim debate sobre la idoneidad tiel paradigma MVC conro meta'fora para sistemas de base Web. Gran parte de este debate gira alreciedor de la incapacidad de actualizar la vista del usuario directarnente en respuesta a canrbios err el nrodelo, pcresto que no hay mode de "l7acerlos bajar" a1 navegarlor. Sin embilrgo, si ccrrnple rrn propdsito adecrrado a la hora rle analizar la separrrcidn de roles. Para otms opciones, cornprcrebe 10s arcbivos de las listas de correo rle Patrones J 2 E E (j2eepa [email protected]. corn). Java Pet Store que se adjunta a J2EE Blueprints ofrece crn enfoque interes'rnte. Permite qrre 10s conrponentes del nivel de presentaciiin, cotno delegados de ernpresa, registrerr su interis en cleterrinados nrodelos de datos co)r una instancia de clase local llawada ModelMa nager. Los nrodelos residen en el nivel EJB. En lugar de configurar urr sistenra de eventos clistribuido, cacia ~rccidnliigica presentada a l f l u ~ ode trabajo en el nivel EJB devolvera' urra lista de 10s modelor que ha actcralizado. La instancia ModelManagrr infornrara' entonces a 10s escrrcbantes apropiados en el ni,uel de prcsentacidn de estos cambios y ejto garantiza que 10s clelegados de enrpresa del nivel de presentacion estardn actrrcrlizcdos la prdxirnil .vez que se renueve fa vista. Evolucion del sistema Cualquiera que sea el equilibrio en la implementation, una nrquitectura que gira alrededor de 10s patrones d e Controlador Frontal, d e Ayudantc de Vistas y d e Objeto d e Acceso a Datos nos ofrece algunas vcntajas dignas de menci6n. Los cambios en el flujo de trabajo n o requeririan necesariamente cambios en la vista o en modelo. D e un moclo similar, 10s cambios en el mccanismo de acceso a datos pucdcn hacerse transpnrentes a la vista y al controlador. Esta triple separacibn nos ofrece un gran numero dc opciones, en caso de que se precisaran cambios en el estilo o en In localization dc la interfaz d e usuario. Puesto que la separacibn resultnnte de responsabilidndes se ajusta ampliamente a1 modelo MVC, si el cliente tiene que volver n ser implementado como unn IU Swing, el rnodelo (en f o r m de JnvaBeans) podria seguir siendo el mismo y simplemente ser resituado en el clicnte. Si la I6gica de flujo de trabajo del controlador fuera implernentndn como una clase indepcndiente del servlet, Pste tambien seria ficilmente relocalizablc. Alternnrivamente, podria crcarsc un proxy para ser utilizado en el cliente que asociarin la entrada Swing n 10s gestos apropiados de usuario esperndos por el controlador de JSP/servlet. La vista podria entonces ser sustituida por una que generara XML en lugar de HTML. El prosy del clicnte podria entonces utilizar esta salida para actualizar su tnodelo local. Hay, por supuesto, un pequeiio problema con una d e las estratcgias sugeridas anteriormentc. Traslndar el modelo a1 cliente n o es la sencilla tarea que algunas herramientas le harian creer que es. Si nuestro modelo esti accediendo a In base de datos a travks d e J D B C o d e EJB, traslndar esta funcionalidad desde el servidor nl cliente acarrea algunas cuestiones serias de rendimiento, conec!ividad y seguridad. D e hecho, incluso el traslndo de scrvidor a servidor puede provocar tales problemas. Este es sblo un punto surgido al examinar un modelo basado en JavaBeans. Si estuvi6ramos crcando una aplicncion que tuvicra que ser altamentc reajustable, entonces esta arquitectura demostraria, por lo general, cstar por debajo del nivel bptimo. Albergar estado en el servidor en nombre de un cliente es un asunto espinoso. En estc caso, el modelo contcndrh dntos que ocupan memoria fisicn y (potencialrnente) una conexion J D B C a la base de dntos subyacente a travks d e la cual pueda rcnovar sus contenidos. Por una serie de motivos, sencillamente no es reajustable. Considere las siguientes cuestiones asociadas a esta situacion: 3 Para resolver 10s problemas d e mernoria, puede que sea posiblc scguir aiiadiendo m6s ~nernoria.A rnedid.1 que se alcance el limitc de la memoria fisica del hardwarc. puede aiiadirse o t r o scnridor para Capitulo 21 manejar algunos de 10s clientes. El problerna inmediato es que entonces quedamos bloqueados entre clientes y servidores. Un senridor concreto albergari el nlodelo para un cliente concreto. Esto puede funcionar potencialmente frente a estrategias de equilibria de c a r p utilizadas por el sistema. 3 La memoria fisica es s61o uno de 10s recursos utilizados por una aplicaci6n. En el caso del modelo, tambiCn requiere una conexi6n a base de datos para acceder a sus datos subyacentes. Mientras que la memoria puede ser relativarnente barata, las licencias de bases de datos tienden a no serlo. Si cada modelo alberga uno de estos recursos, se agotarin con bastante rapidez. Si debe crear uno cada vez que necesite renovar o actualizar sus datos, se deteriorari el rendimiento. El uso de recursos reservados, como reservas de conexiones JDBC, puede ayudar a aliviar algunos de estos problemas, igual que puede hacerlo un enfoque apropiado frente a la gesti6n de estado, como verenlos mis adelante. Si ya ha leido 10s capitulos anteriores sobre EJB, probablemente sabri a d6nde nos lleva esto. Para conseguir verdadera reajustabilidad para la mayoria de aplicaciones JZEE, debe introducir EJB en la arquitectura, como mostramos a reserva de conexiones JDBC Base de datos .-- : -k . Y -- :4-"*-' JSP I - b I RMI C - RMI - reserva de conexiones - Base de datos J DBC Blueprints J2EE reconoce que algunas aplicaciones comenzarin a partir de una sencilla base HTMLIJSP y despuks evolucionarin a medida que cambien 10s requisitos del sistema. De hecho, proporcionan lo que se podria considerar un modelo de madurez para aplicaciones J2EE de base Web, como se muestra en la siguiente tabla: I Tipo de Aplicaci6n Tecnologias Complejidad Funcionalidad Solidez Piginas HTML Piginas HTML Muy poca Muy poca Mucha Piginas HTML, piginas JSP, servlets Poca Pocn Poca I Consideraciones de diseAo para aplicaciones J2EE I T i p o d e Aplicaci6n Tecnologias Complejidad Pdginas JSP con componentes modulares Piginas H T M L , Media plginas JSP, servlets componentes JavaBeans, etlquetas personalizados Piginas JSP con cornponentes modulares y Enterprise JavaBeans Piginas HTML, Mucha piginas JSP, servlets componentes JavaBeans, etiquetas personalizados, Enterprise Java eans Funcionalidad Solidez Media Media Mucha fa"ti11aSp Este modelo a c t h c o m o una buena regla bisica a la hora de considerar qu6 tecnologias se precisarin para implementar una determinada aplicaci6n. Sin embargo, sea consciente de que tendrl sus excepciones. Algunas aplicaciones muy reajustables pueden construirse sencillamente con sewlets siempre que utilice 10s productos de servidor adecuados. Anadir el nivel media Volviendo al tema de nuestro ejemplo, vemos que nuestro sistema se ha expandido u n poco porque el estado que utiliza reside ahora en el nivel medio de un EJB. Esto nos presenta varias cuestiones nuevas d e diserio que debemos tratar: U i Q u e tipo d e EJB debemos utilizar para proporcionar acceso a datos? iDebemos modelar la base de datos con10 u n EJB de entidad o debemos utilizar un EJB de sesi6n y lanzar desde alli consultas S Q L a la base d e datos? Las ventajas e inconvenientes de 10s diferentes tipos de EJB ya han sido analizados. Ahora es necesario que consideremos c6mo se aplicarian mejor en el contexto de nuestra aplicacion. i C b m o interactlian 10s componentes del nivel de presentacidn con el EJB? Esto es especialmente importante si 10s datos son modelados como una entidad. Aunque estamos obteniendo reajustabilidad y flexibilidad al utilizar EJB, estamos incurriendo potencialmente en un considerable sobregasto de comunicacidn. Piense de nuevo en la aplicacidn utilizada con10 contexto para esta consideracibn de diseiio. C o m o primer paso, q ~ ~ e r r i a n modelar ~os nuestros datos d e Producto con10 EJB d e entidad. Esto significaria que podriamos aprovechar la Persistencia Gestionada p o r Contenedor (CMP) para ahorrarnos d e escribir cierto c6digo J D B C )r permitir al contenedor optimizar el acceso a datos. Nuestros componentes del nivel de presentacibn utilizarian entonces la interfaz inicial d e la entidad para buscar ~ r o d u c t o apropiados s para su presentacibn basindose e n las preferencias del usuario. El peligro inmediato aqui es que esto degenerari e n un delirio d e programacidn enemiga de la red y basada en propiedades. Para superar esta situaci6n. puede aplicarse el patron de Objeto Valor alli donde se obtengan mliltiples propiedades a la vez. Por ello, en lugar de que la JSP interactlie con el EJB Producto para obtener cada propiedad individualmente, la JSP puede realizar una linica llamada al EJB para obtener P r o d u c t V a l u e O b j e c t , que contendria toda la informaci6n requerida por la JSP para mostrar esa informaci6n del product0 al cliente. TambiCn puede encontrar este patron en algunos sitios bajo el nombre de Atributos Combinados. Capitulo 2 1 Apl~c.lrel O b j e t o Valor para crear un P r o d u c t V a l u e O b ] e c t nos proporcionarb cierta cantidad de optimizaci6n. Sin embargo, el efecto "diente d e sierra" que ya hemos mencionndo rcapareceria r.ipidamentc si el nivcl W e b debiera ncccder repetidamente n rnilltiplcs EJB de entidad Product aolicitando a cadn uno dc cllos su P r o d u c t V a l u e O b i e c t . Esiste una necesidnd aoui de solicitar rnultivles obietos valor en una vez. U n a C o l e c c i o n dc Objetos Valor puede ser entonces devuelta en una (mica respuesta, reduciendo el sobreensto d e red. El Patr6n d e Maneindor dc Lista de Valores define estrntegins varn devolver colecciones " de Objctos Valor n clientcs. El P r o d u c t L i s t e r e n el sistema de pedidos de compra puede aplicar este patrcin para entregar colecciones de P r o d u c t V a l u r O b j e c t s alas piginas JSP que conforman el Flujo d e Trabajo d e Pedidos. El cliente \Web pucde ajustar el numero de Objctos Valor devueltos dependicndo del tamatio dc In pigina HTML. u A Los dntos de producto en cl sistema de pedidos de compra son tipicos d e datos de catilogo porque son en su mayoria d e s61o lectura y su cambio es lento. En casos con10 Cste, el uso de EJB d c entidad para el acceso puede imponer un sobregasto indebido cn la funcionalidad cle busqueda. Podcrnos aplicar el patrbn de Lector de Via Ripida para acelernr el acceso n datos en grupo utilizando un objeto independicnte para proporcionar acceso de d o lectura directanientc a la fuente d e datos (evitando la capa de EJB dc entidad). Esto accleraria el acceso a1 catilogo en la mayoria d e 10s cnsos con nlgfin coste adicional de desarrollo y un pcqueno numento en la complejidad de la aplicacihn. Sin embargo, la decisi6n de aplicnr el patrhn de Lector dc Vin Ripida depende de si el rendinliento que obtiene de un Manejador d e Lista d e Valores en cachh es suficicnte para sus necesidades. En esencia, se trata d e una lucha entre In velocidad y la sencillez. O t r a cuestibn a tener en cuenta a la hora de utiliznr un Objeto Valor es el de In interoperatividad. En la situaci6n Java-a-Java, es ficil pasar ehtos objetos serializados a travCs d e una interfaz RiiI. Sin embargo, si cualquiern d e sus clientes es potencialmente un cliente CORBA, entonces esta interfaz estd potencialmcnte fuera d e 10s limites para cllos. Incluso si el Object Request Broker (ORB) cliente implen~entaIn funcionalidad de objetos-por-valor requerida por C O R B A 3, todavia implica que sc necesita rnis esfuerzo el bean en el cliente. En este caso, puede que sea mejor utilizar una a la hora de leer (rrnnznnhal~n~) representacibn de base XML para que el objeto valor lo consiga en la plataforma. P r o d u c t V a l u e O b j e c t no necesita contener el c o n i ~ m t ocompleto de datos en el Producto. C o m o regla general, 10s datos en bean5 de este tip0 deben ser d e s61o lectura. Puesto que representa una instantdnea de los d ~ t o spuede , haber valor linlitado e n incluir datos voldtiles en el Objeto Valor. Si, por ejemplo, el EJB Producto contuviera el nivel actual de existencias para ese producto, puede que n o fuera relevante para ser incluidc) cn P r o d u c t V a l u e O b j e c t puesto que ehta informacidn podria estaranticuada en el momento dc su uso. Esta informaci6n debe ser recuperada "fresca" d e P r o d u c t o cuando sea necesaria. La Gltima afirmacibn sugiere otra cuestibn. Se considera una prictica errdnea que 10s clientes (clientes de aplicacihn o servlets/plginas JSP) accedan directamente a EJB de entidad. C o m o hemos visto, esto tiende a provocar accesos muy detallados a Ias propiedades d e EJB y acopla a1 cliente m i s intimamente a la implementaci6n d e la lbgica d e empresa y 10s datos. Lo que necesitamos hacer es desacoplar el cliente del detalle de la implementaci6n de la capa de empresn. Esto puede conseguirse aplicando el patr6n de Fachada de Sesi6n. El bean de sesi6n servird para abstraer la estructura del EJB Producto solamente proporcionando acceso a la funcionalidad requerida por el cliente. En el caso del Producto EJB, la intenci6n principal d e esta fachada es ocultar la estructura de datos del mismo EJB Producto. Una Fachada de Sesihn puede, de hecho, ser utilizada para ocultar un subsistema de empresa completo y presentar al cliente una interfaz simplificada. La cuesti6n final relacionada con el P r o d u c t o es si debe renlmente ser ?lodelado como una entidad. En la situaci6n actual, los clientes estin utilizando un Manejador de Lista de Valores (o Lector de Via Ripida) y una Fachada de Sesi6n para acceder a los datos d e entidad. { N o seria mejor que accediiran~osdirectamente a la base d e datos desde estos beans d e sesibn (como hariamos d e todas formas si eligiiramos el Lector de Via Rdpida) y nos olvidiramos de utilizar un bean d e entidad? D e hecho, el uso de colecciones de Objeto Valor podria evitarse pasando de vuelta los R o w s e t s recibidos de las consultas de la base d e datos. R o w s e t s (conjuntos d e filas) fueron introducidos en J D B C 2.0 como un m o d 0 c6modo de representar Consideraciones de diseho para aplicaciones J2EE datos tabulares. Un Rowset aparece conio JavaBean y puede utilizarse micntras se esti desconectado de In base de datos. TambiCn es Serializable por lo que puede pasarse en una llaniada dc tnitodo RMI. Aunque puede resultar muy l i d en ciertas circunstancias, pasar un Rowset noes conipatible con crear nietodos de tipo seguro. Si un rnCtodo toma o devuelve un Rowset, Cste realmente represent3 un tipo dc datos opaco (no hay notificacion sobre la forrna que deberian adoptar 10s datos). Cualquirr Rowset recuperado de una tabla podrb pasarse a un rnitodo de ebte tipo. Esto podria causar errores inPditos durante el procesa~nientodel Rowset. De un mod0 similar, un campo en un Rowset esti potencialmentc nils abierto a interpretaciones incorrectas quc una propiedad de un JavaBean, o que un eleniento o atributo en XML. Pasar datos en un Rowset refleja el uso estendido de Recordset en ActiveX Data Objects (ADO) en aplicaciones de Microsoft Windows. En ambos casos, tiende n bloquear In arquitectura en una tecnologia y a crear dcpendencias frigiles entre el tormato dc los datos y los usudrios progranilticos de 10s datos. Esto afecta seriarnente a la flesibilidad de aplicaciirn frente a1 cambio. N o existen respuestas correctas o incorrectas e n cuanto a1 uso de entidades frente a objetos de acceso a datos o el uso d e Rowsets frente a tipos de datos especificos. Yo, personalmente, me inclinaria por abstraccion frente a acceso directo, a menos que haya serios problemas de velocidad con la aplicaci6n. El uso responsable de la abstraccion aumentari la flexibilidad y mantenibilidad de la aplicaci6n. Tradicionalmente, gran cantidad de coste y del sufrimiento del desarrollador asociados a una aplicaci6n llega despuis del desarrollo inicial, asi que cualquier cosa que simplifique el mantenimiento de la aplicaci6n debe ser bienvenida. A pesar de esto, gran parte dependeri del origen de los datos, de la eficiencia de la base de datos, de la cficiencia del contenedor EJB, de si 10s datos de la entidad son utilizados por mliltiples beans en la grada EJB y de la cantidad de exceso de comunicaci6n entre el contenedor EJB y la base dc datos. Dos grandes factores determinantes aqui son si un ~ r o d u c t otiene funcionalidad asociada, adem.is de datos, y si necesita transacciones. Si un ~ r o d u c t oes simplemente la asociacion de una linica fila de base de datos, debe preguntar si es suficientemente tosco para ser un bean de entidad. De nuevo, afortunadamente, esta prcgunta no tiene una respuesta fija. Las entidades sencillas de datos funcionan bien en algunas situaciones y no en otras. En tCrminos de tnnsacciones, 10s beans de entidad proporcionarin control de transacci6n sobre 10s datos de forma independiente de la base de datos. Sin embargo, si 10s datos de nuestro bean ~ r o d u c t ono pueden ser actualizados, entonces no hay necesidad de apoyo de transacciones. Asi, por cjernplo, la decisidn sobre si incluir o no el nivel de existencias en la clase product en nuestro modelo de UML seria aqui muy importante. De compras Ahora quc podenios catalogar 10s productos, necesitamos realmente hacer algo litil, como permitir al usuario hacer alghn pedido. Crear un pedido de compras tiene asociado un deterrninado flujo de trabajo: 3 Identificar al usuario O Mostrar el catllogo de productos a1 usuario a Permitir al usuario seleccionar uno o m6s productos del catilogo Enviar el pedido de compra completo a1 gestor adecuado Esto tendri iteraciones y otras condiciones pero, de nuevo, captura la esencia de lo que intentarnos hacer. Este flujo de trabajo esti encapsulado por OrderingWorkflow en nuestro diagrarna original dc clase ULM del sistema de pedidos de compra. Capitulo 21 Encapsular el flujo de trabajo de pedidos El Flujo de Trabajo d e Pedidos, es decir, la interacci6n real con 10s objetos de empresa, podria implementarse en la grada Web o en la grada de empresa. Implementar el flujo d e trabajo en el nivel Web significa que la 16gica d e empresa e s t i muy acoplada al cddigo d e interfaz d e usuario. Si la misma ldgica de empresa fuera requerida por otra parte del sistema, tendria que volver a ser implementada. Si el flujo de trabajo es implementado en un EJB de sesi6n, esto desacopla la ldgica de empresa d e la grada de presentaci6n y la convierte en reutilizable y reernplazable. Para un sistema d e grandes dimensiones, como nuestro sistema Acme, otra ventaja d e utilizar un EJB de sesi6n sin estado en lugar de un servlet es el mayor grado de reajustabilidad al utilizar este tipo de componente. Por lo tanto, el Flujo d e Trabajo d e Pedidos se convierte en un EJB de sesidn que oculta la implernentacidn d e la 16gica d e empresa. Puede interactuar con otros EJB de sesi611, EJB de entidad y Objetos de Acceso a Datos. Si esto le suena, es porque esti actuando como una Fachada d e Sesi6n. La Fachada de Sesidn para el Flujo d e Trabajo d e Pedidos es m i s sofisticada que la que oculta el EJB de entidad de Producto. Proporcionari un conjunto d e mktodos, como addLineItemToPurchaseOrder, por ejemplo, que encapsulen una operacidn 16gica de empresa para el cliente. El cliente no se preocupa de cuintas bases de datos u objetos se utilizan para llevar a cabo esta tarea en el nivel d e empresa. Encapsular el Flujo d e Trabajo en u n EJB de sesidn elirnina complejidad del cliente. Sin embargo, el cliente debe todavia contener c6digo para buscar e instanciar el EJB. Invocar mitodos en el EJB puede provocar RemoteException y el cliente debe capturar la excepcibn o reintentar la operaci6n. Seria mejor agrupar toda esta funcionalidad en un lugar d e m o d 0 que la interaction de manejo con la grada de empresa se convirticra en responsabilidad de una clase. El patr6n de Delegado de Empresa ofrece una estrategia para esta opernci6n. El Delegado de Empresa puede ocultar el uso de Objetos Valor y guardarlos en cache para reducir el tr6fico de red. T o d o esto beneficiaria a nuestra aplicacibn distribuida en tCrnminos d e rendimiento y mayor sencillez del cddigo cliente. C o m o ya hemos mencionado, una ventaja de utilizar un Delegado de Empresa es la capacidad d e asociar excepciones remotas a excepciones con significado para el cliente. U n principio general a la hora de disefiar interfaces de objeto y de componente es que deben generar excepciones con significado (por ejemplo, B u d g e t L i m i t E x c e e d e d , P r o d u c t N o t F o u n d ) en h g a r de simplemente propagar las d e nivel inferior ( R e m o t e E x c e p t i o n , A r rayIndexOutOfBoundException). El Delegadode Empresa puede desempeiiar una funcidn Gtil e n esta estratificaci6n de excepciones d e m o d o que pueden capturar o manejar una escepcibn desde un servidor o generar una excepci6n que tenga sentido para sus clientes, como mostramos a continuation: I : : Base d e datos E"cepcibn ecupada, intbntelc I--, TooManyLocks I I I , I I .- I I lnterfaz d e nivel inferior ----..- ! I I lnterfaz d e ni Teniendo en cuenta que existe una Fachada d e Sesidn para el Flujo de Trabajo de Pedidos, podemos decidir que n o s e requiere u n Delegado de Empresa. D e nuevo, esiste un intercambio entre la cantidad de trabajo requerida para implementar y las ventajas derivadas. En este caso, el argument0 principal para utilizar un Delegado de Emprcsa seria climinar el cddigo EJB de busqueda y tle creacidn del cliente. Corno tal, podria aplicarse el patron d c Localizador d e Servicios para ofrecer esta abstracci6n sin forzar todo el acceso a tmvks del Delegado d e Empresa. Consideraciones de diselio Dara a~licacionesJ2EE El elemento clave es que cl Delegado de Empresa y la Fachada de Sesidn se encargan del flujo de trabajo de enipresa (la secuencia de pasos 16gicos para llevar a cabo una tarea de enipresa). Desde la perspectiva de la interfaz de usuario, el lanzador del Controlador Frontal controla 10s pasos dados en la interfaz de usuario para introducir informaci6n y toma decisiones relacionadas con la tarea de empresa global. El lanzador controla la vista que se ha de niostrar a continuaci6n. Es importante distinguir entre estos dos flujos. Los gestos de usuario capturados por el Controlador Frontal pueden corresponderse de forma exacta con las tareas de empresa y cadi uno puede traducirse en un evento lhgico asociados y pasado a la Fachada d e Sesi6n. Alternativamente, puede tomar mdtiples interacciones d e interfaz d e usuario antes de que se invoque un m i t o d o de empresa. Es iniportante distinguir entre estos dos flujos d e trabajo. El andisis del diagrama completo de clase UMLniostrari que la c h s e o r d e r i n g ~ o r klfo w utiliza una clase session p x a albergar el estado del cliente, como 10s contenidos del carro de la compra. Cualquiera que haya trabajado con piginas JSP o servlets reconoceri inmediatamente este concept0 procedente del objeto sesi6n integrado proporcionado por el API del sewlet. Sin embargo, aqui debenios tener cuidado. La clase remesenfa el conceDto de una sesi6n v n o necesariamente se asocia a una inivlenientaci6n de sesi6n de sendet. Al annlizar previamente el albergue de estado en el servidor, hemos destacado varias cuestiones sobre de memoria. el reciclaie de recursos v la almacenar estado d e este mod0 es~ecificodel cliente. La eesti6n " elusion d e bloqueos del sewidor son tareaa m i s dificiles en el contenedor Web que en el contenedor EJB. Puesto que el contenedor EJB tiene un mecanismo definido de reciclaje y persistencia para el estado de cornponenres, 10s recursos utilizados para el carro de la compra serin gestionados de forma m i s eficiente en la grada EJB q u e e n la grada Web. Utilizar un EJB de sesi6n para la funcionalidad del carro de la compra es tambikn m i s flexible en el sentido en que puede ser utilizado por clientes dotados e infradotados. Modelos con estado versus modelos sin estado Puesto que ahora estamos trabajando potencialrnente con varios beans de sesibn, merece la pena desviarse clel tema principal para tratar consideraciones referentes a modelos con estado frente a rnodelos sin estado. En el modelo con estado, una instancia d e componente de lado servidor e s t i dedicada a u n cliente concreto y alberga sus datos en almacenes temporales para un ficil acceso. En el modelo sin estado, n o hay una instancia dedicada d e componente de lado servidor para el cliente y todos 10s datos deben ser recuperados desde almacenaniientos persistentes. La elecci6n entre componentes d e lado servidor sin estado o con estado es el tema d e muchos debates y discusiones. Aunque el niodelo sin estado es indiscutibleniente reajustable, conlleva sobregastos relacionados con al almacenamiento y recuperation de estado para cada acceso d e cliente. El modelo con estado n o tiene tales sobregastos per0 su reajustabilidad depende por completo de reservas efectivas y algoritmos de activaci6n/pasivacicjn proporcionados por el contenedor EJB. Los EJB con estado tambiin presentan un reto frente al fallo. U n EJB sin estado puede dar el relevo a otra instancia de contenedor con s61o una pequefia cantidad de pirdida potencial de datos. Si un EJB de sesi6n con estado ha albergado el estado conversacional y kste se pierde, el usuario puede que tenga que empezar de nuevo su transacci6n. Adenias de requerir rnis transferencia de datos, el niodelo sin estado tambien requiere m i s trabajo por parte del disefiador de la aplicacih cliente, puesto que siempre debe ser notificado q u i estado utilizar. Esto afecta a nuestra eleccion de bean de sesi6n para implementar la funcionalidad en las clases O r d e r i n g W o r k f l o w y ~ r o d u c t ~ i s t e r . T ya c1o m o estin las cosas, el t r a b a j o d e ~ r o d u c t ~ i s t e r e s enteraniente sin estado; se presenta con una categoria y cataloga el product0 en sus interior. Segdn la prictica adecuada, 10s reaultados serian devueltos como una colecci6n de Objetos Valor que n o dejan estado en el servidor. P o r ello, esto sugeriria que P r o d u c t L i s t e r funcionaria bien conio bean d e sesibn sin estado. Sin embargo, para obtener 10s beneficios del uso d e la cachi y la eficacia el uso del patron d e Manejador d e Lista d e Valores, un bean d e sesi6n con estado seria m i s apropiado. Remitase a la descripcion original del patron d e Manejador de Lista de Valores e n 10s patrones de Sun Java Center para un debate m i s detallado d e este tema. O r d e r i n q W o r k f l o w debe tener cierto concept0 de estado para comprender d6nde e s t i el cliente en ese momento e n el proceso de pcdido. Esto plantea una cuesti6n clnve de disetio sobre d6nde debe .~lrnacenarseel estado, con el cliente, en el EJB o en una base de datos: setv~dorEJB JSP Base de d a m - 1 I 4 - C.dn unn tle 1.1s opciones tiene ventajas e inconvenientes: -1 Estado e n el cliente El cliente debc pasar el estado n cadn Ilnmada de mCtodo que lo necesite. Esto perrnite In esistencia de EJB sin estado y ofrece reajustabilidad a todos 10s contenedorcs EJB. Sin embargo. pone m i s pcso sobrc el clientc y In red y puede provocar un riesgo d e seguridad si se hace A travks de cucos pnra clientes infradotados. En algunos casos, la politica de seguridad de lado servidor incapacitari el uso dc cucos. precisnndo el uso de reescriturn de U R L o de campos ocultos. Ninguno d e estos rnecanismos es realtnente adecuado para albergar cualquier gran cantidad d c estado. Cunlquier forma d c cstado albergado por el cliente tan1bii.n sirve pnra complicnr el diserio de la interfaz rernota dc un EJB. el EJB Utilizando un EJB d c sesiGn con estado, cl estado requerido puede ser cargado o adquirido con el tiempo. Esto simplifica el dibetio de una intcrfaz remota de EJB y nligera la carga sobre el cliente y In red. Sin embargo, reduce 1.1 capacidnd del servidor EJB para reutilizar beans y puede tambien provocar que el cliente qucde bloqucado e n un servidor, frustrando el equilibria de cargas. -1 Estado e n Si el sistenla dcbe npoyar clientes infradotadob, entonces deben proporcionnrbe alguno\ metodo5 d o s t i n ~ d o sa asociar cl cliente con el EJB apropiado. El cliente es cntonces utilizado con un cuco que identifica el EJB que contiene su estado. Esta asociaci6n debe ser n~ancjadnpor uno de los componentes del nivel d e presentacibn. -1 Estado e n u n a base d e datos El cstado para un EJB sin estado puede scr almacenado en una base de datos. El clientc es entonces ernitidv con un cuco o identificndor que identifica el estado ( n o r n d m e n t e la clnve prirnarin del registro que contiene cl estado cn In bdse de dntos). Esto afectn en menor medida al disefio d e la interfaz que nlbergar el estado en el cliente per0 tiene cierto impact0 en la carga de la rcd y en la complcjidad del cliente. Sin embargo, si nlantiene la reajustabilidad garantizada de una implementnci6n sin estado a cambio de 1119s tiempo dedicado a buscar y recuperar 10s datos de la base de datos. Recuerde, sin embargo, que utilizar el cache de la base d e datos o modelar el cstado corno un bean d e entidad podria reducir este tiempo considerablerncnte. El tbrmino "base d e dntos" en rcdidad aqui hace rcferencia a cualquier repositorio de lndo servidor, idealnlente uno transaccional. Sin embargo, si el estado no csti destinado a ser persistente, el alnxlcenamiento aiternativo, como un servicio de directorio adaptado a J N D I , funcionaria bien. Los requisitos d e renjustabilidad y rendimicnto desernpefiarin un arnplio papel en la decisi6n referente al alberguc del estndo. Una vez se h a y determinado la locnlizaci6n del estado, esta decisi6n afectari al disetio dc In interhz remota para el EJB de sesi6n. Consideraciones de diselio para aplicaciones J2EE Presentar el pedido U n a vez que el usuario ha p r o g r e d o en el tlujo de trabajo para la selecci6n dcl producto, estari preparado para presentar su ordcn de compra completnd.~para su aprobaci6n. La cLue O r d e r P r o c e s s (de nuevo, remitase nl diagr.~maU M L ) tendria varias responsnbilidades para comprobar el pedido. Ademis de compl-obar !,I validez dcl pedido, debe tambien coniprobar si el d e p n r t x n e n t o tiene suficicnte presupuesto para tal pedido o puede comprobar si a ese usuario concreto be le perniite r e a l i z u pcdidos d e compra d e ese valor. La clase o r d e r p r o c e s s podria ser ~ m p l e m e n t a d ac o m o un bean d e sesi6n sin estado q u e un proceso linico d e ernpresn sobre el estado q u e le ha sido pasado, o podria pasar a forniar yarte d e una implernentaci6n del flujo d e trabajo d e pedidos si es in~plementadacorno u n bean d e sesi6n c o n estado. U n a vez que o r d e r p r o c e s s estP satisfecha c o n el yedido, debe enviarlo para su aprobaci6n. En este punto, surge un asunto importante en diseno distribuido. El gestor del usuario debe aprobar el pedido, per0 n o cs posible incluir al gestor en el sistema. En este nioniento, el sisterna se cowierte en asincrono yuesto que n o hay ningun gestor nl que el proceso de cornprn puede entregar una solicitud de aprobaci6n sincrona. En su lugar, el pcdido de compra debe ser capturado y alniacenado, en espern de quc el gestor puedn exnrninarlo y aprobnrlo. Elegir un mecanismo asincrono T o d x Ins interacciones que henios tratndo hasta cl mornento (RMI y H T T P ) han sido sincronns en nnturnleza. La arquitectura para este requisito asincrono tendrj. que utilizar una tecnologia o enfoque difercntc. El mecanismo utilizndo depender5 de la estrechez tlel acoplamiento entre el siste~nad e yedidos y el sistema de nprobnci6n. Se sugieren tres posibilidades: J E-mail LJaplicaci6n poclria utilizar el API JavaMail para enviar al gestor un e-mail que contenga el pedido de compra. Esto seria muy flexible para el gestor puesto que incluso podria aprobar cl pedido dcsde su cuenta d e correo d e base Web rnientras se encuentra fuera d e la oficina. Sin embargo, presenta m i s cuestiones referentes al procesamiento de la ayrobaci6n o rcchazo del pedido. En prlnier lugar, la aylicaci6n debe poder controlar la respuesta al e-mail y proccsarla cuando Ilegue. La informaci6n d e pedido de compra dcbe haber sido presentada al gestor en forma legible. Para recuyerar la inforrnaci6n original del pedido, la aplicaci6n debe analizar el mensaje de e-mail para toda la informaci6n del pedido o debe, como minirno, recuperar alguna forma dc identificador del pedido. U n identificador de pedido haria referencia a 103 datos del pedido original almaccnados en alg6n lugar en una base de datos. I'ara proporcionar autentificaci6n, el gcstor tendria quc utiliznr u n certificado digital para firmar el e-mail dc rcspuesta. Esta soluc16n ofrecc un buen alcance (es decir, 5610 requiere que el gestor tenga un cliente e-mail para renlizar la aprobaci6n) y e s t i muy debilmente acoplado. Sin embargo, es algo improductivo y p o t e n c d m e n t c Inseguro. U Base d e datos El pcdido podria ser al~nacenadoen una base d e datos dentro del sistema. El gestor tendria entonceb que acceder a cierta forrna d e aplicaci6n que consultnra la base de datos en busca d e pedidos a IJ espera de la aprobacidn dcl gestor. El gestor interactuaria entonces con esa aplicaci6n para aprobar o rechazar 10s yedidos. Puesto que toda la inforrnaci6n e s t i almacenada en una base d e datos, n o habria ningun yroblema en manejar un valor de retorno como con e- nail. Sin embargo, seria yreciso cierta forma dc indicar que el pedido ha sido aprobado o rechazado, como un indicador en la base d e datos o trasl.~dindoloa otra tabla. Se proporcionaria seguridad nutcntificando al gestor antes de que utilizarn la aplicnci6n. Capitulo 21 Esta soluci6n tiene menos alcance puesto que enlaza dos partes de la apkaci6n a una base de datos corndn (aunque puede que esto se requiera de cualquier forrna para acceder a informacibn presupuestaria y del producto). Esto supone rnis responsabilidad para el gestor, puesto que deberi acceder a 10s datos en la base de datos, incluso si su llegada es notificada via e-mail. TarnbiCn esti estrecharnente acoplado a la representacibn dcl pedido. Sin embargo, todo sc lleva a cabo dentro de un dorninio corndn de seguridad y significa que el desarrollador no tiene que tratar esplicitamente con algunos de 10s puntos negativos de las cornunicaciones asincronas (que analizaremos mas adelante). 9 Sewicio d e mensajeria Podriamos utilizar Java Message Service (JMS) para enviar un rnensaje asincrono al gestor a travks d e un sisterna d e rnensajes dedicado. Este rnensaje esperaria en una cola apropiada hasta que pudiera ser entregado ( o recuperado) por la aplicacibn de aprobacibn. Puesto que el mensaje no pretende ser legible, podria ser codificado convenienternente cotno X M L o como un JavaBean serializado. Seria m6s conveniente utilizar el bean serializado para soluciones Java integrales, per0 XML es niis flexible y contribuye a la integracibn. L,? llegada de la funcionalidad XML Data Binding (JAXB) debe convertir a XML en una mejor opcibn, como rnuestra esquernlticarnentc el siguiente diagrarna: Pedido de comora XML Data Binding enviar recibir Analizar Pedido de XML Serv~dord e cola Una vez que el pedido ha sido aprobado o rechazado, podria ser trasladado a una cola especifica "aprobado" o "rechazado". La eleccibn de diseiio aqui esti entre el estado del pedido de cornpra indic'ldo por su ubicacjon (es decir, la cola en la que se encuentra) o en un indicador en el niisrno mensaje. Las colas transaccionadas deben ser utilizadas para garantizar que n i n g h rnensaje queda olvidado si fallara la operacion por cualquier rnotivo. Estas realizan la elimination del rnensaje d e una cola y su alrnacenarniento en otra parte de la transacci6n. Una vez en la cola adecuada, el pedido d e cornpra estaria disponible para un posterior procesarniento, que implicaria ser pasado a otra aplicaci6n, corno la un proveedor externo. Esta solucion tiene un alcance considerable puesto que 10s mensajes pueden potencialmente cruzar fronteras entre organizaciones. El formato flexible del rnensaje proporciona un reducido acoplamiento entre las aplicaciones y la seguridad se incluye con10 parte del sistema de rnensajeria. Una desventaja es que, aunque la rnayoria de 10s desarrolladores J2EE estln familiarizados con el uso de EJB, servlets y RMI, son menos lo que estln familiarizados con JMS por l o que les llevaiia algun tiernpo aprender un nuevo API y paradigma de prograrnaci6n. Los API Java para Mensajeria XML (JAXM) tarnbikn prometen facilitar esta forma de interacci6n entre aplicaciones pasando mensajes de base S O A P , eliminando potencialmente la necesidad de acceder a colas directaniente. Consideraciones de diseiio para aplicaciones J2EE Una carga titil X M L puede tambie'n ser utilizada corno un mensaje de e-mail para proporcionar u n sistema de mensajeria afin a Internet a1 ser utilizado con almacenes de mensajes orientados a la aplicacio'n. En este caso, una aplicacio'n tendria que recuperar el mensaje del almac6n y presentar su contenido a1 gestor, probablemente a la manera del servlet que proporciona una interfaz de base Web. Esto elimina la inmediatez de enviar el mensaje directamente el gestor, pero lo hace mucho ma's pra'ctico. De nuevo, el requisito preciso de la aplicaci6n controlaria las fuerzas en estas decisiones. Puesto que el sistema de pedidos de compra se distribuiriapotencialmente por el planeta, es probable que la soluci6n de mensajeria basada en JMS con mensajes codificados en XML fuera mis eficiente. Esto equilibra la facilidad de procesarniento, las caracteristicas de integraci6n y el alcance potencialrnente rnundial de 10s sitios rernotos de Acme Corporation. Reajustabilidad y disponibilidad a traves de la asincronicidad Corno hernos visto, el rnargen de tiempo entre la presentaci6n del pedido de cornpra y su aprobaci6n o rechazo por parte del gestor puede ser rnuy amplio (cuesti6n de semanas si estin de vacaciones). Aunque esto es potencialmente aceptable para el sistema de pedidos de compra, seria inaceptable para un escaparate de cornercio electr6nico. De hecho, para el tipico sistema transaccional de comercio electr6nic0, un retraso en el pedido de minutos o incluso de decirnas de segundo durante el procesarniento del pedido del usuario puede provocar atrasos y pantallas de "sisterna ocupado". Por este motivo, incluso algunos aspectos que podrian considerarse intuitivarnente corno sincronos pueden ser ejecutados de forrna asincrona. Tornernos el procesarniento de una tarjeta de credito on-line corno ejernplo. Puesto que la tarjeta de credito debe ser cornprobada y aprobada por un procesador de tarjetas de credit0 (norrnalmente una cornpaiiia tercera), esta llarnada de aprobaci6n puede ser encolada para una entrega posterior. Las llarnadas pueden realizarse en lote o cuando el sistema tenga capacidad de sobra. Por el lado positivo, esto puede rnejorar enorrnernente el rendirniento y reajustabilidad del sisterna puesto que implica esperas. El h i c o inconveniente verdadero es para cualquier titular de una tarjeta de credit0 cuya verificaci6n falla. En este caso, deben ser inforrnados posteriormente (habitualrnente via email) de que su transacci6n no ha podido ser procesada. La mensajeria es tarnbikn una herrarnienta titi1 en 10s mornentos en 10s que el servidor de destino no esti disponible, ya sea por accidente (fallo del servidor), diseiio (rnantenirniento) o sobrecarga debida a1 acceso de dernasiados usuarios. El cliente puede entregar rnensajes a la cola y estos quedarin ahi hasta que el servidor regrese. De este rnodo, aporta cierto nivel de solidez a la aplicaci6n dificil de alcanzar al utilizar exclusivarnente rnecanisrno asincronos. Cuestiones relacionadas con sistemas asincronos Corno hernos visto, utilizar sisternas asincronos de operaci6n y de rnensajeria tiene algunas ventajas. Tarnbien tiene, sin embargo, ciertos inconvenientes. Si se necesita salida, ernisor y receptor deben estar de acuerdo en que el resultado sea enviado a una determinada cola. Tarnbien deben estar de acuerdo en un identificador para el rnensaje concreto a1 que responde. Finalrnente, el ernisor del mensaje original debe escuchar la llegada de rnensajes o exarninar la cola para esperar la llegada de su respuesta. Otra cuesti6n es que las transacciones necesitan una gesti6n especial cuando alcanzan las fronteras asincronas. La transacci6n asincrona no puede propagarse con el rnensaje, por lo que se requiere cierta forma de alrnacenamiento de estado de transacci6n. Aunque esto tiene mucho sentido (las transacciones sincronas deben completarse con la mayor rapidez), significa que un fallo en el rnanejo se hace rnis cornplejo y que se requieren otros rnecanisrnos para informar del fallo a1 usuario del sistema. En el caso de la tarjeta de cridito, el pedido debe ser cancelado y se debe enviar un mensaje de e-mail al usuario. Ambas acciones tienen lugar fuera del alcance de la transacci6n asincrona dentro de la cual el usuario solicita sus articulos. Capitulo 21 TambiCn resulta mis dificil obtener un valor de retorno del procesamiento asincrono. Aunque la mayoria de sistemas de mensajeria proporcionan un modo de obtener un acuse de entrega del mensaje, 10s mensajes son en gran medida un mecanismo de una sola trayectoria. Si se requiere un valor de retorno, se requiere tambikn una ruta de vuelta independiente (es decir, otra cola) entre servidor y cliente. Establecer interfaces entre sistemas de mensajeria y EJB ha supuesto tradicionalmente un problema. Sin embargo, en J2EE 1.3 y versiones posteriores, puede utilizarse un EJB controlado por mensaje como recipiente direct0 para una cola o apartado de mensajes. Los mensajes recibidos pueden ser procesados o reenviados a EJB ordinarios de entidad o de sesion con el EJB controlado por mensaje desempefiando la funci6n de un adaptador. Con anterioridad a J2EE 1.3, un objeto adaptador que implementa la interfaz JMS Message Listener tenia que ser registrado como recipiente de 10s mensajes. Este adaptador reenvia entonces 10s mensajes a1 EJB apropiado utilizando las llamadas de interfaz asincrona normales. Aunque no esti tratado aqui, la entrega de mensajes a EJB anteriores a J2EE 1.3, asi como el uso de EJB controlados por mensaje como adaptadores, se analiza con detalle en la documentaci6n original para el patrdn de Activador de Servicio del catilogo de Patrones J2EE de Sun Java Center. Aprobar el pedido Volviendo a nuestro sistema de pedidos de compra,ApprovalWorkf l o w y A p p r o v a l P r o c e s s son anilogas a O r d e r i n g W o r k f l o w y O r d e r P r o c e s s . Estin sujetas a muchas de ]as mismas fuerzas en su diserio y, por ello, serian implementadas por lo general del mismo modo, como A p p r o v a l W o r k f l o w siendo una Fachada de Sesi6n. Una importante diferencia es que s61o hay un tip0 de datos manejados ( O r d e r s ) . Todos 10s datos con 10s que se trabaja serin procesados por esta parte de la aplicaci6n. N o existen datos estiticos como el catilogo de productos. Otra diferencia es que el flujo de trabajo asociado a la aceptaci6n o rechazo de un pedido es lineal. N o hay una fase independiente de iteration como la existente a1 cargar el carro de la compra seguido por la presentacidn del pedido. Debido a estos factores, la funcionalidad d e ~ ~ ~ r o v a l ~ r oincluye c e s sel control de 10s datos utilizados durante la aprobaci6n. Para facilitar esta tarea, cuenta con un mCtodo para enumerar 10s pedidos de compra que esperan la aprobaci6n del gestor. Esto simplifica la forma de esta parte del sistema. La clase A c c o u n t utilizada en el proceso de aprobaci6n comprobaria cualquier solicitud contraria a 10s limites y reglas del departamento para asegurar que el gestor se ajusta, por ejemplo, a su saldo miximo. A c c o u n t seria modelada como un EJB de entidad. Esto es justificable puesto que A c c o u n t contiene 16gica de empresa y datos. El saldo de fondos procedentes de la cuenta del departamento seria acoplados a la aprobaci6n del pedido. En un sistema mis acoplado, el proceso de aprobaci6n tambikn reduciria el nivel de existencias de cada product0 albergado en una base de datos. En ambos casos, A c c o u n t formari parte de una transaction puesto que el cargo s6lo debe tener lugar si el pedido es aprobado (es decir, trasladado a la cola "aprobado"). La necesidad de una transacci6n para el proceso de aprobaci6n podria ser normalmente identificada desde el caso de uso asociado durante el modelado del sistema: 1. El gestor se registra en el sistema de aprobaci6n 2. Se muestra a1 gestor la lista de pedidos de compra en espera de su aprobaci6n 3. El gestor selecciona un pedido de compra y analiza 10s detalles 4. El gestor aprueba el pedido de compra 5. El sistema carga en la cuenta del departamento la cantidad derivada del pedido de compra 6. El sistema reenvia el pedido de compra para su cumplimiento Consideraciones de diseho para aplicaciones J2EE Las alternativas aqui serian que el usuario rechazara el pedido de compra, que fallara el saldo o que fallara el reenvio del pedido de compra. Los pasos 5 y 6 sugieren una relacion transaccional entre ellos por ello, cuando Sean asociados a1 dominio de la solucion: se indicara que requieren una transaccion. En tirminos de clase, el metodo a p r o v e ( ) d e ~ ~ p r o v a l ~ r o cnecesitaria ess ser marcado c o m o transaccional a1 igual . uso de colas de mensaje transaccionales garantizarian que el q u e el mCtodo d e b i t ( ) d e ~ c c o u n t El movimiento del pedido de compra entre las colas "pendiente" y "aprobado" forman una operation atomica con el saldo. La clave para las transacciones es mantenerlas tan cortas como sea posible. N o es necesario que t o d o el procesarniento llevado a cab0 por A p p r o v a l W o r k f l o w o A p p r o v a l P r o c e s s sea transaccional. D e hecho, esto ralentizarian innecesariamente el sistema. El objetivo primordial de las transacciones es mantener la integridad de 10s datos. Esto requiere que 10s cambios Sean aislados entre si y se consigue esencialmente bloqueando algunos de 10s datos subyacentes. C u i n t o s m i s datos e s t i n bloqueados, mas probable s e r i que otras transacciones tengan que esperar a que se libere el bloqueo. Aunque puede jugar mucho con 10s niveles de aislamiento, el limite esti en que cuintas rnis transacciones utilice, rnis competencia tendri para 10s recursos. De esto se desprenden plazos agotados y usuarios frustrados. La linica soluci6n real a esto consiste en mantener las transacciones lo rnis cortas posibles. Por ello, s61o debe utilizar transacciones alli donde sean necesarias y asegurarse de que 10s mitodos transaccionales no realizan demasiado procesamiento innecesario. Las transacciones cortas y el r5pido reciclaje de recursos son 10s dos factores fundamentales en la reajustabilidad de grada media. Merece la pena continuar p o r u n m o m e n t o con el reciclaje de recursos. Se trata de u n concept0 importante en todos 10s niveles. Si cuenta con una cantidad infinita de recursos, entonces n o importa c u i n t o tiempo espera u n componente a una instancia concreta de recurso puesto que otros componentes pueden recuperar una instancia de la reserva infinita. A medida q u e desciende el numero de instancias de recursos, la cantidad de tiempo que u n componente espera a 10s recursos es m i s critica. Esta relacion puede representarse e n el siguiente diagrama: lnfinito 4 A Tan larga como desee 4 Ntjmero de recursos Fraccibn de tiempo v v Uno b 4 Wan corta como sea posible La mayoria de las aplicaciones compiten p o r rnis de un recurso per0 sigue siendo importante reciclar recursos tan ripido c o m o sea posible para contribuir a la reajustabilidad. El modelo J2EE para EJB e s t i disefiado para contribuir a la reajustabilidad, pasivando EJB cuando n o son necesarios y devolviCndolos a O S la reserva de objetos. Puesto que son pasivizados, pueden liberar 10s recursos que albergan y ~ S ~ se ponen a disposition de otras instancias que sirven a otros clientes. Sin embargo, surge la pregunta de c u i n d o se pasivari u n objeto. Considere u n EJB de sesion c o n estado escrito de tal m o d 0 que obtiene y alberga una conexion a una base de datos; Si hay 10 conexiones disponibles bajo la licencia de la base de datos y hay 20 de estos beans de sesi6n con estado en la reserva de objetos, i q u i sucede cuando aparece el 11" cliente concurrente? Puesto que 10s beans de sesi6n sin estado Capitulo 21 son pasivizados despuis de cada rnitodo, n o deben tener ningun problerna con albergar recursos. Sin embargo, si u n desarrollador n o ha llevado a cab0 una prograrnaci6n adecuada y ha obtenido sus recursos en el constructor del obieto, esto podria causar problernas. La raz6n por la que 10s beans de sesidn sin estado n o tienen problernas habitualrnente con la gesti6n de recursos es porque 10s desarrolladores se ajustan a un ciclo de vida conveniente para ese reciclaje. Sin embargo, estas buenas pricticas de reciclaje funcionan en todas las formas de EJB y tambikn e n servlets, piginas JSP y cualquier otra forma de objeto Java. El principio que sostiene un buen reciclaje de recursos (y, por ello, una buena reajustabilidad) consiste en adquirir y liberar recursos cuando 10s necesitarnos a lo largo de nuestro c6digo de cornponentes. Debernos adquirir un recurso justo antes de que lo necesitemos y liberarlo posteriorrnente tan pronto corno sea posible. Muchos desarrolladores tienden a evitar esta politics puesto que consideran cara la creacion y asignacidn de recursos y, por ello, lo hacen s61o una vez en el period0 de inicializacidn. La clave e s t i en utilizar recursos procedentes de reservas de recursos ya que estos estin preconstruidos y pueden ser asignado ripidarnente. Esto significa que n o tenemos que lanzarnos a la caza del recurso cuando necesiternos uno. En el nivel de ernpresa, existe una tendencia a interesarse menos por el reciclaje de recursos puesto que se presupone que el contenedor se encargari de todo. Sin embargo, el principio de liberar 10s recursos tan pronto corno sea posible sigue aplicindose. Mas alla del sistema de pedidos de compra El diseiio siernpre tiene lugar dentro de u n contexto. El contexto que hemos utilizado hasta el rnornento ha sido el sistema electr6nico de pedidos de cornpra para nuestra cornpaiiia ficticia. Sin ernbargo, existen muchos rnecanisrnos y patrones que resultan utiles en el diseiio de sisternas J2EE que no se requieren ni se utilizan en esta situaci6n. E n esta seccion, exarninarernos brevernente algunos de estos rnecanisrnos y patrones y 10s contextos en 10s que se aplican. Diseno de interfaz EJB A1 escribir u n EJB, n o es buena idea que el bean irnplernente su interfaz (de ernpresa) rernota. Esto perrnitiria que una referencia a1 rnismo bean fuera pasada de vuelta a un cliente en lugar de pasar el E J B o b j e c t asociado. Sin embargo, implernentar la interfaz rernota resulta tentador ya que le perrnite recoger cualquier firrna de mktodo incorrecta del bean antes de que lo haga el introspector del contenedor. Podernos conseguir el rnismo proposito definiendo una versidn no rernota de nuestra interfaz de ernpresa que puede ser implementada por el bean. Podemos entonces crear nuestra interfaz remota del bean heredando de la interfaz de empresa n o rernota y del E J B O b j e c t . El siguiente dIagrama muestra la jerarquia de herencia de las interfaces. Observe que 10s mitodos de nuestra interfaz de ernpresa n o remota tendrin que ser declarados para lanzar una excepcidn R e m o t e E x c e p t i o n para que funciones correctamente en la versi6n remota: I-- lnterfaz de empresa A 7- ja~a.ejb.~~~~bj%T_/ - -- A-- - Consideraciones de disefio Dara a~licacionesJ2EE A diferencia del entorno C O M de Microsoft o del entorno de Componentes CORBA, Enterprise JavaBeans s610 tiene una Gnica interfaz. Esto significa que hay cuestiones relacionadas con el diseho de EJB que deben tratarse. Si el diseho del bean sugiere que debe implementar dos interfaces independientes, este requisito puede resolverse utilizando la herencia. La siguiente figura muestra una jerarquia de herencia en potencia para dos interfaces de cuentas, C u r r e n t A c c o u n t y S a v i n g s A c c o u n t . Ambas tienen ciertas operaciones administrativas en comGn per0 se diferenciarin perfectamente en el resto de operaciones. En lugar de insertar simplemente una lista de mktodos administrativos en cada interfaz y arriesgarse a que se desincronicen, cada interfaz puede heredar de otras dos interfaces; la interfaz AccountAdmin que contiene 10s mktodos comunes y una interfaz que contiene 10s mktodos especificos de la cuenta, por ejemplo, C u r r e n t o p e r a t i o n s . Esto permitiria a1 cliente reducir una r e f e r e n c i a ~ u r r e n t ~ c c o uantipoAccountAdmin t o C u r r e n t o p e r a t i o n s . El resto del c6digo cliente podria entonces escribirse como si fueran interfaces independientes y pudiera asegurarse la seguridad de tipo: Observe que esto sdlo puede realizarse para las interfaces remotas de EJB. Las interfaces iniciales necesitara'n devolver diferentes tipos desde sus me'todos y, por ello, no pueden ser utilizadas de este modo. Otra consideraci6n para interfaces EJB es la consecuencia de utilizar el descubrimiento de interfaces basado en roles. La identificaci6n del rol durante el anilisis provocari a menudo el descubrimiento de una interfaz especifica del rol que contenga mktodos especificos de ese rol. U n ejemplo de este tip0 de interfaz es la i n t e r f a z ~ c c o u n t ~ d m i presentada n, en la anterior figura, que debe limitarse a una rol administrativo. Aqui hay dos posibles rutas: a Primero, podria implementar la interfaz en una bean completamente independiente. Sin embargo, esto n o seria deseable si 10s mktodos d e ~ c c o u n t ~ d myi C n u r r e n t o p e r a t i o n s actuaran sobre 10s mismos datos subyacentes. O La segunda ruta consiste en implementar el tip0 de jerarquia de herencia que hemos mostrado anteriormente y usar 10s atributos de seguridad en el descriptor de despliegue para aplicar la seguridad adecuada para esta interfaz virtual. Aunque esta ruta es algo improductiva, es la Gnica alternativa segura a la ausencia de multiples interfaces. EJB 2.0 introdujo en concept0 de interfaces locales para beans de entidad que tienen relaciones dependientes y utilizan persistencia gestionada por contenedor. El EJB dependiente expone una interfaz local al EJB contenedor puesto que esti garantizado que ambas se estin ejecutando en el mismo contenedor. En este caso, se aplican las reglas habituales para interacci6n local Java (pasar por semintica de valor para referencias de objeto) y el diseho de la interfaz no es tan critico. Sin embargo, debe Capitulo 2 1 asegurarse de que nunca seri necesario dividir estos dos EJB en un futuro utilizando persistencia gestionada por bean, antes de que la interfaz sea menos afin a la red. Como hemos analizado anteriormente, una operation eficiente se consigue dividiendo el estado entre las gradas de presentation y de empresa. Un Objeto Valor puede actuar como representante de s61o lectura de 10s datos en el EJB asociado. Algo a tener en cuenta es q u i hacer cuando 10s datos representados cambian. Cuando 10s datos son manipulados localmente (en la misma JVM), el modelo de evento de delegaci6n funciona bien. El modelo puede lanzar cierta forma de evento de carnbio en la vista. La vista implementaria la interfaz escuchante apropiada para ese evento. El API Swing utiliza esta forma de mecanismo de evento como parte de su implementation MVC. Surge una cuesti6n cuando el modelo de datos no es local a la vista. Si la vista esti en la grada Web (o cliente) y el modelo esti en la grada EJB, no hay ningun mecanismo Java de evento distribuido preproporcionado. Sin embargo, existe suficiente estructura para crear el nuestro propio. RMI le permite configurar retrollamadas desde el servidor a1 cliente. Estas pueden ser utilizadas como la base para una version distribuida del modelo de evento de delegation. El servidor puede implementar una interfaz de registro y el cliente (o vista) puede afiadirse a si mismo como escuchante. Cuando sus datos cambian, el servidor puede informar a todos sus escuchantes del carnbio y las vistas pueden actualizarse basindose en estos nuevos datos. Si desea implementar este tipo de estructura, la Especificaci6n de Eventos Distribuidos Jini, disponible en el sitio Web de Sun, proporciona elementos para la reflexion. Otra alternativa para un sistema de eventos distribuidos en utilizar mensajes asincronos. ~ s t o pueden s ser integrados con 16gica de empresa basada en EJB, como ya hemos descrito anteriormente en el capitulo. JMS puede utilizarse para implementar varios patrones basados en mensajes o basados en eventos. La funcionalidad de inter& dependeri mucho de las fuerzas que intervengan en el sub-sistema concreto que esti intentando disefiar. Una cola de mensajes puede utilizarse para pasar mensajes desde un productor a uno o mis consumidores. El uso de mensajes punto-a-punto asegura una relacion uno-a-uno entre productor y consumidor (aunque el comportamiento en el caso que mhltiples consumidores son tan tontos como para registrarse en busca de mensajes procedentes de la misma cola es algo impreciso). Seria adecuado utilizar el sistema punto-a-punto alli donde el productor esti creando elementos de trabajo que deben ser procesados por el consumidor. Alternativamente, al tratar la distribuci6n de informacion, como las omnipresentes cuotas de existencias, puede utilizarse un modelo publicar-y-suscribir. En este caso, multiples clientes recibirin la misma informacion registrindose para recibir mensajes en un apartado especifico. Los mensajes pueden convertirse en persistentes si la aplicacion tuviera problemas si se perdieran 10s mensajes en el trayecto. De un mod0 similar, 10s consumidores pueden solicitar que un servidor reteng? una copia de cualquier mensaje publicar-y-suscribir que haya llegado para ellos cuando esten desconectados. Estos serin entregados cuando el consumidor reaparezca. Todo esto contribuye a la solidez de una aplicaci6n. Diseno para bases de datos Hay muchas cosas inteligentes que pueden hacerse con las bases de datos que van mis alli del alcance de este capitulo. Sin embargo, desde un punto de vista global de disetio, hay uno o dos principios que debe tener en cuenta. En primer lugar, no sea un snob de Java. Los EJB son geniales y hacen un trabajo fantistico proporcionando datos reajustables y flujo de trabajo de empresa. Sin embargo, si el rendimiento es su gran prioridad, tpor qu6 no dejar que la base de datos trabaje tanto como pueda? Es mis eficiente ejecutar Consideraciones de disefio para aplicaciones J2EE cddigo dentro de la base de datos que extraer 10s datos, trabajar con ellos y despuks devolverlos. Aunque integrar un procedimiento almacenado en su base de datos e invocarlo para realizar el trabajo puede n o ser tan flexible, portitil como utilizar un EJB de entidad, quizis descubra que funciona bastante mis deprisa y que puede ser m i s adecuado para las fuerzas de su aplicacion. Si debe codificar todo en Java, intente asegurarse de que tiene un servidor de base de datos que le permite ejecutar su codigo Java en el interior de la base de datos para obtener lo mejor de ambos mundos. Si esti utilizando EJB de entidad, intente evitar pelearse con la base de datos. Si esti consultando muchas tablas para construir su estado de entidad, entonces quizis tenga un serio impediment0 de correspondencia erronea entre su bean y su base de datos. Quizis quiera considerar la desregularizaci6n de su base de datos para facilitar la correspondencia con su entidad. Alternativamente, podria dividir una entidad en un conjunto de entidades dependientes que se comuniquen utilizando interfaces locales (a partir de JZEE 1.3). D e nuevo, aunque no se descubre en este capitulo, hay un buen debate sobre el uso de entidades como objetos dependientes en el patron de Entidad de Composici6n del catilogo de Patrones JZEE de Sun Java Center. En general, merece la pena dedicar bastante tiempo a su disefio de datos. El diseiio de datos tiende a evolucionar m i s despacio que el nivel medio o el nivel cliente. Si lo hace mal, puede requerir una seria reestructuracion de las otras gradas. Lecciones aprendidas Podriamos potencialmente haber seguido la aplicacion de sistema de pedidos de compra a travks de la entrega del pedido a1 sistema proveedor, etc. Sin embargo, esto no supondria ninguna nueva aportacion importante para el diseiio. En este punto, podemos hacer balance de las principales lecciones que hemos aprendido a partir de ejemplo y ampliarlas all: donde resulta apropiado. Separar intereses siempre que sea posible La separacion de intereses desemboca en una mejora de la flexibilidad y de la mantenibilidad de un sistema. Hemos visto varios ejemplos de ello en el sistema de pedidos de compra: O El uso de (pseudo)MCV para dividir el manejo de interfaz de usuario en presentacion (vista), comportamiento (controlador) y datos (modelo) O Utilizar el patron de Ayudante de Vista en piginas JSP divide la codificaci6n Java de la presentacion de datos 0 El cliente puede utilizar la funcionalidad de un EJB sin preocuparse por el ciclo de vida especifico de EJB y las excepciones si esti oculto detris de un Delegado de Empresa 0 Los elementos de funcionalidad de interfaz de usuario pueden ser tratados de forma independiente construyendo una Vista de Composici6n Este principio traspasa 10s patrones y otras decisiones de disefio encontradas en este capitulo. Minimizar el trafico de la red U n exceso de llamadas de red provoca atascos de rendimiento puesto que las redes repletas de datos y componentes pasan mucho tiempo esperando que esas llamadas concluyan. Cualquier reduction en el Capitulo 21 numero de llamadas de red, en la cantidad de datos pasados y en el indice de sobregasto de red por datos pasados es util. De nuevo, este principio puede ver en la prictica en: o El uso de Objetos Valor para evitar la programacidn basada en propiedades en la red. Los Objetos Valor que representan un conjunto parcial de datos pueden tambien reducir 10s niveles de transferencia de datos. 0 Los Manejadores de Listas de Valores que pasan colecciones de Objetos Valor para pasar mis datos en una unica llamada. Los Manejadores de Listas de Valores permiten tambien a1 cliente detener la recuperacidn de datos cuando ya hayan sido suficientes 10s recibidos. 0 El uso de una Fachada de Sesidn reduce el numero de llamadas procedentes del cliente para el nivel de empresa. 0 U n Delegado de Empresa puede almacenar en cache datos y agrupar en lotes llamadas de metodo desde la perspectiva del cliente, reduciendo el trifico en la red. Utilizar abstraccion para contribuir a la flexibilidad Forzar al cliente para que se implique intimamente en una implementaci6n subyacente provoca un acoplamiento excesivo y una falta de flexibilidad en una aplicaci6n. Abstrayendo el servicio que debe ser provisto por el cliente, 10s detalles reales de la interacci6n pueden ocultarse y asi cambiarse siempre que sea necesario. Podemos verlo en: 0 El uso de 10s patrones de Delegado de Empresa y Localizador de Servicio para ocultar detalles subyacentes de interaccidn con EJB remotos. 0 Aplicacidn del patr6n de Objeto de Acceso a Datos para proporcionar una interfaz de cliente c o m h a multiples fuentes de datos. U n uso comedido de la abstracci6n puede hacer que una aplicacion sea mucho mis intuitiva y mis ficil de mantener y ampliar. Usar patrones comunes El conjunto de patrones identificados como especificos de J2EE forman 10s inicios de un lenguaje de patr6n. En un lenguaje asi, 10s patrones se interrelacionan de formas comunes. Comprendiendo ambos patrones y cualquier combinaci6n comun de ellos, un disehador puede hacer mejor uso de 10s patrones disponibles, como vemos en: 3 Los macro patrones Servicio a1 Trabajador y Vista de Lanzador que presentan formas alternativas comunes de utilizar un Controlador Comun con Ayudantes de Vista. 0 Todos 10s patrones especificos de J2EE presentados en este capitulo. Con el simple hecho de saber que hay patrones en estas ireas se puede ahorrar mucho tiempo y conjeturas por parte del disefiador. Los patrones deben formar parte del equipo de herramientas de cualquier disehador o arquitecto de J2EE. Consideraciones de disetio para aplicaciones J2EE Reducir el acoplamiento de mecanismos asincronos En rnuchas aplicaciones, ciertas operaciones tardarin rnucho tiempo en ser cornpletadas. Para que la aplicaci6n avance, la operaci6n debe convertirse en asincrona. Esto puede ayudar a enfrentarse a problernas de reajustabilidad y disponibilidad: El funcionarniento asincrono puede irnplernentarse de diferentes forrnas: 0 Los servicios especificos de rnensajeria integados en software intermediario orientado a1 rnensaje con rndtiples arquitecturas corno punto-a-punto y publicar-y-suscribir 0 Sisternas de rnensaje ad hoc integrados en e-mail u otros sencillos transportes O El uso de un alrnacenarniento persistente para proporcionar un punto de encuentro para el productor y el consurnidor del rnensaje Los intercarnbios asincronos son un buen rnodo de reducir el acoplamiento entre cornponentes. Transacciones de plan Los sisternas s61o deben utilizar transacciones a rnedida que Sean requeridas. Las transacciones pueden ser descubiertas a partir de casos de uso y diseiiadas tal y corno sea apropiado. El tiernpo dedicado alas transacciones debe minirnizarse tanto corno sea posible para evitar la cornpetencia de recursos. N o planear 10s requisitos transaccionales puede llevar a sistemas lentos o defectuosos. Durante rnuchos afios, he estado irnplicado en la evaluaci6n de nuevas tecnologias. A1 principio, mi tendencia era centrarrne en la tecnologia en si misrna y las diversas novedades que aportaban. C o n el paso del tiempo, ernpeck a comprender que el 90% de 10s desarrolladores del rnundo nunca utilizarian todas estas novedades. Lo que quieren es utilizar la tecnologia para resolver sus problernas de ernpresa. C o n ese prop6sit0, necesitan comprender la tecnologia y aplicarla en su propio contexto particular. La clave es asegurar que 10s desarrolladores utilizan las caracteristicas centrales de la tecnologia concreta apropiada a su contexto. La tecnologia rnisrna es de poco uso a rnenos que se aplique correctamente. Espero que haya encontrado cierto contexto familiar en este capitulo y pueda aplicar algunos de 10s principios descritos. En este capitulo, hernos analizado aspectos del diseiio J2EE, concretamente: 0 La relaci6n entre diseiio y arquitectura. 0 Corno el contexto provisto por un tip0 determinado de aplicaci6n puede afectar a la aplicaci6n de base J2EE. n Una variedad de patrones especificos de J2EE que resuelven rnuchas cuestiones cornunes de diseiio surgidas a la hora de diseaar sistemas de ernpresa basados en J2EE. n C6mo las diferentes tecnologias J2EE pueden aplicarse para resolver diferentes problernas de diseiio. En el siguiente capitulo, centraremos nuestra atenci6n en 10s Servicios Web, un terna interesante y en ripida evoluci6n. JZEE y servicios Web Con el uso generalizado de Internet, nuestro mod0 de utilizar 10s ordenadores ha cambiado radicalmente. En sus origenes, 10s ordenadores solian ejecutar aplicaciones monoliticas y el usuario de la aplicacidn tenia que aprender desde cero todo sobre todas y cada una de las aplicaciones que queria utilizar. D e este modo, a medida que la tecnologia seguia cambiando, 10s usuarios se veian obligados a aprender nuevas aplicaciones continuamente. En lugar de que las tecnologias se adaptaran a las necesidades humanas, eramos nosotros 10s que nos veiamos obligados a adaptarnos a la tecnologia en constante cambio. C o n Internet, el foco de atencidn esti cambiando hacia software basado en servicios. Los ordenadores se utilizan para leer el correo electrdnico, obtener las cotizaciones del dia de la bolsa, pagar recibos de utilidades o simplemente para localizar el mejor restaurante chino. El software requerido para dar servicio a estos requisitos no debe ser una aplicacidn monolitica tradicional. Asimismo, el usuario de un servicio de este tipo puede acceder a1 servicio utilizando una ampliar variedad de dispositivos como PDA, tekfonos mdviles, ordenadores portitiles, etc., asi el software tradicional debe convertirse en software basado en servicios a1 que se accede ficilmente a traves de una amplia variedad de dispositivos cliente. Esto ha dado paso a una nueva raza de desarrollo de software orientado a 10s servicios. El desarrollo de software orientado a servicios es posible gracias a la utilizaci6n de tecnicas como C O M , CORBA, RMI, Jini, RPC, etc. Algunas de estas tecnicas son capaces de ofrecer servicios en la Web y otras, no. La mayoria de ellas utilizan protocolos de propiedad para la comunicacidn y sin normalizacidn. Esto dificulta que dos servicios diferentes interoperen entre si. Idealmente, estos servicios no s61o deberian interoperar entre si, sino que tambikn deberian ser capaces de integrarse y componer servicios de micro nivel en un h i c o servicio de mayores dimensiones. Sin embargo, si diferentes programadores de aplicacidn utilizan diferentes tecnologias para crear estos servicios, puede que la integracidn n o siempre sea una tarea ficil. Este concept0 consistente en crear servicios a 10s que se puede acceder a travCs de la Web ha dado lugar a un nuevo termino llamado semicio Web. En este capitulo, analizaremos este nuevo paradigma de software y, en particular, como puede ser aplicado a la plataforma J2EE. Aunque 10s servicios Web no estin especificados como parte de la especificacidn J2EE, gran parte de la tecnologia que necesitamos implementar ya esti ahi. Capitulo 22 M i s concretamente, analizaremos: 0 Tipos de servicios Web 0 Tecnologias de servicio Web 0 Tecnologias Java para el desarrollo de servicios Web 0 Servicios Web inteligentes Pero, antes de seguir adelante, debemos entender con exactitud lo que queremos decir con el tCrmino servicio Web. iQue son 10s servicios Web? U n servicio Web puede definirse corno: I U n componente de aplicaci6n accesible a travks de protocolos Web estindar. I U n servicio Web es como una unidad de lbgica de aplicacibn. Proporciona servicios y datos a clientes remotos y otras aplicaciones. Los clientes y las aplicaciones remotas acceden a servicios Web a travCs de protocolos de Internet omnipresentes. Utilizan XML para el transporte de datos y S O A P (Simple Object Access Protocol) para hacer uso d,e servicios. Debido a1 uso de XML y SOAP, el acceso a1 servicio es independiente de la implementac16n. Asi, un servicio Web es como una arquitectura de componentes para la Web. Igual que sucede con un modelo de desarrollo de componentes, un servicio Web debe tener 1as dos siguientes caracteristicas: 0 Registro con un servicio de b6squeda 0 Una interfaz p6blica para que el cliente invoque el servicio Cada servicio Web debe registrarse en un repositorio central de mod0 que 10s clientes puedan buscar en el registro el servicio deseado. Una vez localizado el servicio, el cliente obtiene una referencia a1 servicio. El cliente utiliza entonces el servicio invocando varios metodos implementados en el servicio con la ayuda de una interfaz pliblica publicada. Asi, cada servicio debe publicar su interfaz para el uso de 10s clientes. Ademis de las anteriores caracteristicas esenciales, un servicio Web debe tambiCn poseer las siguientes caracteristicas: 0 Debe utilizar protocolos Web estindar para comunicaci6n 0 Debe ser accesible desde la Web 0 Debe ajustarse a1 acoplamiento dCbil entre sistemas distribuidos no acoplados de mod0 que 10s sistemas ejecutados en diferentes plataformas y basados en diferentes tecnologias puedan cooperar entre si para formar un sistema distribuido Los servicios Web reciben informacibn procedente de clientes como mensajes, que contienen instrucciones sobre lo que desea el cliente, similares a las llamadas de mCtodos con parimetros. Estos mensajes, que tambikn son entregados por un servicio Web a1 cliente cuando concluye el servicio, son codificados utilizando XML y las interfaces pliblicas tambien son descritas en XML. XML proporciona transporte de datos neutral con referencia a la plataforma. De este modo, 10s servicios Web capacitados para XML pueden, tebricamente, interoperar con otros servicios Web capacitados para XML siempre que J2EE y servicios Web dos servicios estkn de acuerdo en un protocolo cornfin para la cornunicacibn. Los protocolos utilizados por servicios Web para la cornunicaci6n estin siendo norrnalizados y 10s analizarernos en las siguientes secciones. Servicios inteligentes En estos dias, la rnera introducci6n de servicios Web n o es suficiente. Los usuarios de un servicio Web quieren que el servicio sea lo suficienternente inteligente para cornprender el contexto en el que se invoca y actuar consecuenternente. Por ejernplo, si esti utilizando un servicio Web para buscar un restaurante, el servicio debe ser lo suficienternente inteligente para buscar sus preferencias personales, su historial de 10s ultirnos dias con relaci6n a 10s lugares donde ha cornido y ofrecer sugerencias apropiadas. Alternativarnente, suponga que esti utilizando un servicio Web para hace una reserva de viaje. La politica de su ernpresa quizis le perrnita viajar en clase preferente, aunque quizis viajaria en a u t o b k en sus viajes personales. El servicio deberia detectar autorniticarnente el contexto y ofrecer consecuenternente las sugerencias para sus reservas de viajes. Estos servicios se llarnan servicios inteligentes y pueden proporcionar contenidos utilizando tecnicas de personalizaci6n. Los servicios inteligentes serin tratados con rnis detenirniento rnis adelante, en este rnisrno capitulo. Despuks de haber visto en que consisten 10s servicios Web, analizarernos ahora las tecnologias requeridas para el desarrollo de estos servicios Web. Tecnologias de servicios Web Hay una aplica variedad de tecnologias que apoyan 10s servicios Web. Las siguientes tecnologias estin disponibles para la creaci6n de servicios Web. Son tecnologias neutrales en su relaci6n con el vendedor. Exarninarernos brevernente estas tecnologias antes de continuar con 10s que Java nos ofrece en el carnpo de 10s servicios Web: 0 SOAP 0 Mensajes SOAP con anexos 0 WSDL 0 UDDI 0 ebXML S O A P (Simple Object Access Protocol, vkase http : / /www. w3 .org/TR/SOAP/ para rnis detalles) es un protocolo de base XML ligero y sencillo. SOAP perrnite el intercarnbio de inforrnaci6n estructurada y tecleada sobre la Web, describiendo un forrnato de rnensaje para la cornunicaci6n equipo-a-equipo. SOAP perrnite la creacidn de servicios Web basados en una infraestructura abierta. SOAP consiste en tres partes: 0 Sobre S O A P Define el contenido de un rnensaje, quikn es el receptor del rnensaje y si el rnensaje es opcional u obligatorio. Capitulo 22 0 Reglas de codificaci6n S O A P Define un conjunto de reglas para intercarnbiar instancias de tipos de datos definidos por la aplicaci6n. O Representaci6n R P C S O A P Define una convencidn para representar llarnadas de procedimiento rernoto y respuestas. SOAP puede utilizarse en cornbinaci6n con una variedad de protocolos y forrnatos de Internet existentes incluido HTTP, SMTP y MIME, y puede ajustarse a una arnplia garna de aplicaciones desde sisternas de rnensajeria a W C . Sin embargo, en el rnornento de la publicaci6n de este libro, s610 se ajusta a la asociaci6n HTTP. ~ s t es e un tipico rnensaje SOAP: Corno podernos ver en este ejernplo, un rnensaje SOAP esti codificado utilizando XML. SOAP define dos espacios de nornbre estindar, uno para el sobre (http://schemas.xmlsoap.org/soap/enevelope/) y el otro para las reglas de codificaci6n (http://schemas.xmlsoap.org/soap/encoding/). U n rnensaje SOAP no debe contener D T D (Definicibn de Tipo de Docurnento) y no debe contener ninguna instrucci6n de procesarniento. El anterior rnensaje SOAP define un metodo llamado GetLastTradePrice que torna un sirnbolo bursitil corno parirnetro. El consurnidor del servicio Web crea un rnensaje SOAP corno el anterior, lo integra en una solicitud POST H T T P y la envia para que sea procesada por el servicio Web: POST /StockQuote HTTP/1.1 Host: www.stockquoteserver.com Content-Type: text/xml; charset="utf-8" Content-Length: nnnn SOAPAction: "Sorne-URI" ... SOAP Message El servicio Web procesa el rnensaje, ejecuta la operaci6n solicitada y devuelve el resultado a1 cliente en forrna de otro rnensaje SOAP. El rnensaje contiene ahora el i n d i ~ ebursitil solicitado. U n tipico rnensaje SOAP de retorno puede ser ask El rnensaje puede ser devuelto a1 cliente corno una respuesta HTTP y contendri la cabecera HTTP adecuada en la parte superior del rnensaje. Corno veri, en este rnensaje estarnos diciendo a1 cliente que la J2EE v servicios Web respuesta a su l l a r n a d a ~ e t ~ a s t ~ r a d e ~esr i3 c4 e. 5 ; si el cliente hubiera realizado solicitudes a rnis rnktodos, la respuesta contendria rnis valores de retorno. lnteroperabilidad El orincioal obietivo en el diserio de SOAP fue oerrnitir una ficil creaci6n de servicios Web distribuidos interoperables (proporcionando ficil acceso a objetos). Puesto que 10s servicios pueden ser descritos en XML, es rnucho rnis ficil describir servicios en arquitecturas RMI, CORBA o EJB. Algunos detalles de especificaciones SOAP estin abiertos a la interpretaci6n; sin embargo, la irnplernentaci6n difiere entre vendedores. Asi, 10s rnensaies creados Dor diferentes aolicaciones difieren en su nivel de adaptaci6n teniendo corno resultado aplicaciones no interoperables. Observe que un docurnento XML vilido puede no ser necesariarnente un rnensaje SOAP vilido y, sirnilarrnente, un rnensaje SOAP vilido puede no ser un rnensaje SOAP vilido. Lo que esto significa es que un rnensaje SOAP, aunque es un rnensaje XML vilido, puede que no siga estrictarnente la especificaci6n SOAP. Para probar el grado de conformidad, pueden utilizarse herrarnientas terceras. Una herramienta de este tip0 llarnada SOAP Message Validator esti desarrollador por Microsoft y esti disponibleenhttp: //www. s o a p t o o l k i t .com/soapvalidator/.Utilizandolaherrarnientade convalidaci6n, puede cornprobar si cualquier c6digo SOAP se corresponde con la especificaci6n SOAP 1.1 lmplementaciones La tecnologia SOAP ha sido desarrollada por DevelopMentor, IBM, Lotus, Microsoft y Userland. Mis de 50 vendedores han irnplernentado SOAP hoy en dia. Las irnplernentaciones rnis populares son la de Apache, que es una irnplernentaci6n de base Java de fuente abierta, y la de Microsoft, dentro de su plataforrna .NET. Las dos irnplernentaciones tienen algunas discrepancias que hacen que las aplicaciones desarrolladas utilizando las dos tecnologias no Sean interoperables. La especificacidn SOAP ha sido presentada a W3C (World Wide Web Consortium), que esti trabajando en estos rnornentos en nuevas especificaciones llarnadas XMLP (Protocolo XML) que esti basado en la versi6n 1.1 de SOAP. Mensajes SOAP con anexos (SwA) Quizis necesite enviar un rnensaje SOAP con un anexo consistente en otro docurnento o en una irnagen, etc. En Internet, 10s forrnatos de datos G I F v, TPGE son tratados corno estindares de facto para " trasrnisi6n de irnigenes. En general, 10s anexos pueden estar en forrnato de texto o binario. La segunda iteraci6n de la especificaci6n SOAP (SOAP 1.1) perrnitia que 10s anexos fueran cornbinados con un rnensaje SOAP utilizando una estructura MIME rnultiparte. Esta estructura rnultiparte se denornina Paquete de Mensajes SOAP. Esta nueva especificaci6n ha sido desarrollada por H P y Microsoft y ha sido presentada a1 W3C. Esta es una rnuestra de un rnensaje SOAP que contiene un anexo (myimmage .t i f f ) : MIME-Version: 1 . 0 C o n t e n t - T y p e : M u l t i p a r t / R e l a t e d ; boundary=MIME b o u n d a r y ; s t a r t = " < m y i m a g e d o c . x m l @ m y s i t ecorn>" . type=text/xml; Content-Description: This i's the optional message description. -MIME boundary Content-Type: text/xml; charset=UTF-8 Content-Transfer-Encoding: 8bit Content-ID: < r n y i m a g e d o c . x m l @ r n y s i t e . c o r n > Capitulo 22 -MIME boundary Content-Type: image/tiff Content-Transfer-Encoding: binary Content-ID: . . .binary TIFF image.. -MIME-boundary- . El Lenguaje de Descripci6n de Servicios Web (WSDL) es un formato XML para describir una interfaz de servicio Web. Un archivo WSDL define el conjunto de operaciones permitidas en el servidor y el formato que el cliente debe seguir al solicitar el servicio. El archivo WSDL actGa como un contrato entre el cliente y el servicio para una comunicaci6n efectiva entre las dos partes. El cliente tiene que solicitar el servicio enviando una solicitud bien estructurada y que se ajuste a SOAP. Como ejemplo, si estuviCramos creando un servicio Web que ofreciera las Gltimas cotizaciones de la bolsa, seria necesario que creiramos un archivo WSDL en el servidor que describiera el servicio. El cliente obtendria primer0 una copia de este archivo, comprenderia el contrato, crearia una solicitud Web basada en el contrato y lanzaria la solicitud a1 servidor utilizando un Puesto HTTP. El servidor valida la solicitud y, si es vdida, la ejecuta. El resultado, que es el Gltimo indice bursitil para el simbolo requerido, es devuelto entonces a1 cliente como una respuesta SOAP. Documento WSDL Un documento WSDL es un documento XML que consiste en un conjunto de definiciones. Primero, declaramos 10s espacios de nombre requeridos por la definici6n del esquema: El elemento raiz es d e f i n i t i o n s , como mostramos aqui: El atributo name es opcional y puede servir como una forma 1igera de documentaci6n. nmtoken representa testigos de nombre que son cadenas cualificadas similares a CDATA, per0 el uso de caracteres esti limitado a letras, digitos, subrayado, dos puntos, punto y barras. Opcionalmente, un t a r g e t N a m e s p a c e puede especificarse proporcionando u n u r i . La etiquetaimport puede utilizarse para asociar un espacio de nombre con una localizacion del documento. Asi, 1as definiciones pueden contener el espacio de nombre de destino, que se asocia entonces a la localizacidn del documento en una J2EE y servicios Web instrucci6n i m p o r t posterior. El siguiente segrnento de c6digo muestra cdrno el espacio de nombre declarado se asocia mis tarde a la localizaci6n del docurnento especificada en la instrucci6n i m p o r t : Finalrnente, el elemento opcionalwsdl : d o c u m e n t a t i o n es utilizado para declarar docurnentaci6n legible. El elernento puede contener cualquier texto arbitrario. Dentro de las definiciones, aiiadiri otros elernentos. Existen seis elementos principales en la estructura del docurnento que describen el servicio. Son 10s que enurnerarnos a continuaci6n: 0 types 0 message 0 binding 0 port 0 service Elelemento types El elernento t y p e s proporciona definiciones para tipos de datos utilizados para describir c6rno 10s rnensajes intercarnbiarin datos. La sintaxis para el elernento t y p e s es la siguiente: ? ? * La etiquetawsdl : d o c u m e n t a t i o n es opcional como en el caso d e d e f i n i t i o n s . El sisterna de tipo x s d puede utilizarse para definir tipos en un rnensaje. Como quizis n o sea posible tener una gramitica de sisterna de un h i c o tip0 para describir todos 10s tipos abstractos, WSDL permite que 10s sisternas tip0 Sean aiiadidos a travks del elernento de extensibilidad. U n tipico ejernplo de una secci6n < t y p e s > se muestra a continuaci6n. Aqui se define un elernento llarnado S t o c k Q u o t e S e r v i c e . El semicio requeriri un parirnetro de entrada de tipo string, con el nombreticker~yrnbol: Capitulo 22 U n elernento m e s s a g e representa una definici6n abstracta de 10s datos transrnitidos. La sintaxis para el elernento m e s s a g e es la siguiente: El atributo mes s a g e name se utiliza para definir un nornbre 6nico para el rnensaje dentro del alcance el docurnento. Corno en casos anteriores, w s d l : d o c u m e n t a t i o n es opcional y puede utilizarse para declarar docurnentaci6n legible. El rnensaje consiste en una o rnis partes 16gicas. p a r t describe el contenido abstracto 16gico de un rnensaje. Cada p a r t e consiste en un nornbre y en atributos opcionales e l e m e n t y t y p e . El elernento y su tipo pueden ser declarados con anterioridad en la secci6n t y p e s . A continuaci6n se rnuestra un t i p i c o m e s s a g e . El nombre del rnensaje es s t o c k Q u o t e S e r v i c e . S t o c k Q u o t e s debe definirse en el espacio de nornbre en la secci6ndef i n i t i o n s : El elernento p o r t T y p e define el conjunto de operaciones abstractas. Una operaci6n consiste en mensajes de entrada y de salida. Corno se rnuestra en la siguiente sintaxis, la etiqueta o p e r a t i o n define el nornbre de la operacibn, input define la entrada para la operaci6n y output define el forrnato de salida para el resultado. El elernento f a u l t se utiliza para describir 10s contenidos del elernento de 10s detalles de fallos SOAP. El elernento de detalles de fallos especifica el forrnato abstracto del rnensaje para 10s rnensajes de error que pueden producirse como resultado de la operaci6n: ? ? oolean r e s u l t = f a l s e ; S t r i n g u r l = "jdtic: c l o u d s c a p e : c : / j2 s d k l . 3 / c l o u d s c a c a p e D B " ; String price=""; try i con = D r i T ~ t r M a n a g e rg.e t C o r ~ r ~ e c t i o(rui r l ); // Recuperar d a t o s de l a base d e datos Staten1er.t s t m t = con.createStaterr1er1t ( ) ; S t r i n g s q l = "SELECT FROM s t o c k d e t a l l s symbol t " ' ) " ; R e s u l t s e t r s = s t m t . e x e c u t e Q u e r y ( s q l ); + / / Mostrar e l conjuntc de resultados while ( r s . n e x t ( ) ) [ price = rs.getString(2); result= true; break; WHERE (stocksymbol="' t Capitulo 22 1 rs. close ( ) ; stmt .close ( 1 ; catch(Exception e ) [ e.printStackTrace0; if ( r e s u l t ) [ return price; 1 else { return "Enter a valid Stock Symbol"; 1 1 Antes de ejecutar este cbdigo, necesitari crear una tabla llamada s t o c k d e t a i l s en su base de datos y afiadir a ella algunos registros. Este es el SQL para crear la tabla: CREATE TABLE ( s t o c k s y m b o l V A R C H A R ( 1 0 ) NOT N U L L , stockprice V A R C H A R ( 1 0 ) ) stockdetails Crear el JAR El siguiente paso en el desarrollo es compilar y convertir en JAR el archivo de clase creado. Utilice el siguiente comando para crear un archivo JAR llamado s t o c k . j a r : jar cvf stock. jar StockQuote. class Generar archivos WSDL A continuaci6n, generaremos el archivo WSDL que expone el metodo g e t s t o c k p r i c e ( ) de nuestra clase Java como semicio Web. Esto podria significar escribir todo el cbdigo XML. Afortunadamente, el juego de herramientas de IBM proporciona una herramienta para generar el archivo WSDL. Inicie la herramienta ejecutando el archivo w s d l g e n .b a t provisto en la carpeta \bin del juego de herramientas de semicios Web de IBM. Asi, se abre la ventana que mostramos a continuacibn: WSDL Generation TOOI Please select the service creation type: . ... .................. " ..2ava..G!as4 .. I r r EJB Jar File COM Dispatch Interface I J2EE v servicios Web La herramienta le permite crear una descripci6n de servicio Web desde cualquiera de las interfaces niostradas. Utilizaremos la opci6n Java Class para generar la descripci6n para nuestro servicio Web. Haga clic en Next (Siguiente) para pasar a la siguiente pantalla del asistente: Java Class WSDL Ctnrration Class Name I~tntit~uote Classpath F Yfi/ro~IProJa\raSeruenCh227slockjar Output Filename P I Properly Name r I n Value I' En el canipo Class Name (Nombre de la clase) introduzca StockQuote y e n Classpath, facilite la ruta completa del archivo stock . j a r . Acepte el nombre del archivo de salida por defecto, per0 aseglirese de que sale en el mismo directorio en que ha creado el archivo de clase. Las propiedades del servicio se presentan en la tabla como se muestra en la captura de pantalla. Haga clic en Next para pasar a la siguiente pantalla. En esta pantalla, veri In lista d e metodos descubiertos por la herramienta: Capitulo 22 ,void watl(long,mt) vo~dka~t(lo~g! Class getclass0 -- -I - Back I1 7 1 Desplace hacia abajo la lista de rnitodos hasta encontrar el mktodo getstockprice ( ) . Seleccione este metodo y haga clic en Next. La siguiente pantalla le da la oportunidad de confirmar sus opciones antes de que la herramienta genere el archivo WSDL: Confirm vour chblces - - ;Urappering source: ScockOuocc ,TDUSDL docment: c:\Uron\ProJavaServer~Ch22\Swck(luocc~Setvi I Haga clic en Finish (Finalizar) para generar el archivo WSDL. DespuCs de la creaci6n efectiva del archivo, emerge un mensaje en la pantalla para indicar que la operaci6n ha sido realizada con kxito: 1176 J2EE y servicios Web Corno parte del proceso de generaci6n de WSDL, se crearin 10s siguiente archivos en la presente carpeta: - El archivo StockQuote Service.wsdl El archivo generado S t o c k Q u o t e - S e r v i c e . w s d l es el que rnostrarnos a continuaci6n: coperat ion narne="getStockPrice"> La configuraci6n de un sencillo descriptor de implementaci6n a p p l i c a t i o n . xml s610 conlleva 10s siguientes pasos: 1. La e t i q u e t a < a p p l i c a ti o n > se utiliza para declarar una aplicaci6n de empresa. La etiqueta < a p p l i c a t i o n >puede contener,< d i s p l a y - n a m e > y < d e s c r i p t i o n > p a r a s e r utilizados por una herramienta de implementaci6n y proporcionar informaci6n sobre la aplicaci6n. El contenido de estas etiquetas es el mismo que el de 10s mismos etiquetas de 10s descriptores de implementacidn de un EJB, una aplicaci6n Web y un adaptador de recursos. 2. Cada m6dulo J2EE incluido en la aplicaci6n de empresa debe tener una etiqueta equivalente que describa el m6dulo. Los EJB son descritos utilizando la etiqueta < e j b>, las a~licacionesWeb son descritas utilizando la etiaueta . 10s adamadores de recursos son descritos utilizando la etiqueta < c o n n e c t o r > y 10s programas cliente de aplicaci6n son descritos utilizando la etiqueta< j ava>. A excepci6n de la e t i q u e t a < ~ e b >el, contenido de las otras etiquetas es un URI relativo que nombra el archivo que contiene el m6dulo J2EE dentro del archivo EAR. El URI debe ser relativo a la raiz del archivo EAR. 3. Si su aplicaci6n de empresa contiene un m6dulo JZEE de aplicaci6n Web, necesita facilitar un y u n < c o n t e x t - r o o t > . L a e t i q u e t a < ~ e b - u r i >es unURI relativo que nombrael archivo que contiene el m6dulo J2EE en el archivo EAR. Se trata del mismo tipo de URI que se especificaparalasetiquetas , < c o n n e c t o r > y < j ava>.Laetiqueta Empaquetado e implernentacion J2EE especifica el nombre del contexto bajo el que se ejecutari la aplicaci6n Web. Posteriormente, todas las solicitudes de piginas JSP y servlets para esa aplicaci6n Web deben estar precedidas por este contexto de Web. Por ejemplo, si despliega una aplicaci6n Web con: todas las solicitudes p y a piginas JSP y servlets siempre estarin precedidas de: Cada aplicaci6n Web empaquetada en un archivo EAR debe tener un valor exclusive. Dos aplicaciones Web empaquetadas en el mismo archivo EAR no pueden tener valores idhticos. Si s610 hay una aplicaci6n Web en el archivo EAR, el valor de puede serunacadenavacia. El uso mis comb de archivos EAR se daria en una situaci6n en la que una aplicaci6n de empresa tenga un Gnico m6dulo EJB y un Gnico m6dulo de aplicacion Web que haga uso de 10s componentes EJB implementados en el m6dulo EJB. En este ejemplo, 10s EJB y las aplicaciones Web no dependen de ninguna biblioteca de dependencia. Esta secci6n describe 10s pasos necesarios para la construcci6n de este ejemplo. Empaquetar 10% componentes Este ejemplo tiene un servlet que invoca un mktodo invoke ( ) en la interfazremota de un EJB de sesi6n sin estado. El servlet y el EJB imprimen instrucciones a la consola para que indique que estin siendo ejecutados con Cxito. Si la consola recibe una excepci6n, probablemente el empaquetado de 10s componentes no se ha realizado correctamente. Todos 10s archivos fuente EJB de este ejemplo se encuentran en el paquete wrox. El servlet se encuentra en el paquete sin nombre. Los archivos Java utilizados para implementar este ejemplo incluyen: EnterpriseServ1et.java La clase de implementacion del servlet que invoca el EJB Enterprise-java La interfaz remota del EJB EnterpriseHome.java La interfaz inicial del EJB EnterpriseBean. java La clase de implementaci6n del EJB Para saber c6mo componer servlets y EJB, remitase a 10s capitulos correspondientes de este libro. Esta seccidn s61o mostrari 10s fragmentos relevantes de codigo que permitan a1 lector seguir el ejemplo. La composici6n de EJB y de 10s descriptores de la aplicaci6n Web, la creaci6n de 10s archivos JAR y de archivos WAR no estin demostrados en este capitulo. El codigo fuente para la clase de i m p l e m e n t a c i 6 n ~ n t e r p r i s e ~ e a jnava . es el siguiente: package wrox; import javax.ejb.*; public class EnterpriseBean implements SessionBean I Capitulo 24 private InitialContext ctx; public public public public public void e j b C r e a t e 0 {} void ejbRemove() {} void ejbActivate ( ) { I void ejbpassivate ( ) { I void setSessionContext (SessionContext c ) { 1 public void invoke() [ Systern.out .prir7tlr1("Executing in EJB."); El codigo fuente para la clase del servlet Enterprises ervlet . j ava es el siguiente: import import import import javax.servlet.*; javax.servlet.http.*; j ava. io.*; j avax. naming. * ; public class Er~terpriseServlet extends HttpServlet [ public void service(HttpServ1etRequest req, HttpServletResponse throws IOExceptionl ; res .setContentType ("text/htmll') Printwriter out = res.getWriter ( ) ; res) try i System.out.println("Serv1et Executing in Server"); InitialContext ctx = new InitialContext ( ) ; wrox. EnterpriseHome eHome wrox.Enterprise e. invoke(); e = (wrox.EnterpriseHome) ctx.lookup("EnterpriseEJB"); eHome.create0; = 1 catch(Exception e) { out .println ("Exception: " t e ); System. out. println ("Exceptior~: " t e ) ; 1 out .println ("Title") ; out .println ("") ; out .println ("See console to ensure EJB was invoked. ") ; out .println (""); 1 1 Despu.6~de desarrollar el codigo EJB 10s descriptores de irnplernentaci6n relevantes (que no incluirnos aqui), el EJB debe ser ernpaquetado en un archivo llamado EnterpriseBean. jar. El EJB es configurado para asociarse a EnterpriseEJB en el espacio de nornbre JNDI. DespuCs del desarrollo del cddigo de servlet y de 10s descriptores de despliegue relevantes (tarnpoco incluidos aqui), el servlet debe ser ernpaquetado en un archivo llarnado ~ e b ~ p war. p . La clase de servlet es registrada para ejecutarse con la asociaci6n /enterpriseservlet /. EnsamblJe de la aplicacion Despuks de cornpletar el proceso de construcci6n del cornponente, tarnbikn debe desarrollarse el descriptor de implernentaci61-1de la aplicacion de ernpresa. Necesitarnos registrar el EJB y la aplicaci6n Empaquetado e implementacion J2EE Web como modulos de la aplicaci6n de empresa. Tambikn queremos que 10s componentes de la aplicaci6n Web se ejecuten bajo la raiz del contexto /Web/. El archivo a p p l i c a t i o n . xml para este ejemplo se convierte en: c ! DOCTYPE a p p l i c a t i o n P U B L I C ' - / / S u n M i c r o s y s t e m s , I n c . //DTD J2EE A p p l i c a t i o n 1.3//EN1 'http://java.sur~.com/dtd/applicaticr~1 3 . d t i l 1 > Despuks de crear el descriptor de implementacion a p p l i c a t i o n . xml,el directorio de construcci6n de la aplicacidn de empresa debe parecerse a este: . Para crear un archivo EAR l l a m a d o ~ n t e r p r i s ee a r utilizando la utilidad j a r , debe introducir en la consola el siguiente comando: j a r cvf E r ~ t e r p r i s e e. a r E r ~ t e r p r i s e B e a r r . ja r WehA&'p.war META-INF Lo interesante sobre la herramienta de implementacidn provista por la Inplement a ci o n de Referencia J2EE es que nunca se supone que 10s desarrolladores deban componer 10s descriptores de implementaci6n ej b- j a r .x m l o appl i ca ti on. xml. Estos archivos siempre son generados automaticamente por el us~ario.En el caso de esta aplicacidn de empresa, el archivo a p p l i ca ti on. xnd que se sitria en el archivo EAR es generado automkticamente para el desarrollador. lmplementacidn de la aplicacion Despuks de que el archivo EAR haya sido construido, necesita implementarse. Recuerde que el proceso de implementacibn es especifico del vendedor y que cada vendedor proporciona herramientas personalizadas para ello. La utilidad d e p l o y t o o l J2EE tiene una opci6n para implementar una aplicaci6n para la Implementaci6n de Referencia. qecutar la aplicacion Despues de que la aplicaci6n de empresa haya sido implementada con exito, la ejecuci6n del cliente conlleva invocar el servlet que ha sido desplegado en la aplicaci6n Web. Puesto que la raiz de contexto de la aplicaci6n de empresa es /Web, el servlet es invocado como parte de la misma. Por ejemplo, para invocar el servlet, debe introducir lo siguiente en la ventana del navegador: Deberi ver la siguiente pantalla en el navegador despuks de que se ejecute el servlet: Capitulo 24 Etiquetas opcionales\ de la etlqueta de Implementation Pueden utilizarse dos etiquetas opcionales de descriptor de implementacidn en ciertas situaciones. Son y. < a l t - a d d > es una sub-etiqueta de . El valor de esta etiqueta es un URI que apuntaria hacia otro archivo de descriptor de implementacidn para el mddulo referenciado desde la raiz del archivo EAR. El archivo no tiene por quC tener el mismo nombre que tiene dentro del mddulo J2EE. Por ejemplo, todos 10s descriptores de implementacidn del mddulo EJB deben llamarse e j b- j a r .xml. El valor de esta etiqueta puede ser un archivo con un nombre distinto a e j b- j a r .xml si esti referenciando a un descriptor de implementacidn alternativo para un mddulo EJB. El archivo del descriptor de implementacidn ignoraria a1 contenido en el mddulo J2EE. ~ s t es e un tipo de descriptor de implementacidn posterior a1 ensamblaje. Esta etiqueta puede utilizarse para referenciar una versidn externa del descriptor que debe utilizarse si un implementador quiere utilizar un descriptor de implementacidn diferente del contenido en un EJB, una aplicacidn Web, un adaptador de recursos o un mddulo de cliente de aplicacidn. Si este valor no se especifica, entonces la herramienta de implementaci6n debe utilizar 10s valores especificados en 10s archivos JAR, WAR o RAR provistos en el archivo EAR. Por ejemplo, para especificar una aplicacidn Web con un descriptor de implementacidn externo, alternativo, que estC localizado en la raiz del archivo EAR, debe escribir lo siguiente: < s e c u r i t y - r o l e > permite a1 implementador especificar loirales de seguridad de nivel de aplicaci6n que deben utilizarse para todos 10s mddulos contenidos en el archivo EAR. Si un archivo EAR contiene m6ltiples mddulos EJB y/o m6ltiples mddulos de aplicacidn Web, cada hno de esos mddulos puede tener sus propios roles de seguridad definidos en si mismos. Una de las responsabilidades del implementador consiste en asegurarse de que 10s nombres de todos 10s roles de seguridad contenidos en todos 10s mddulos J2EE son exclusives y tienen significado para la aplicacidn completa. Los roles de seguridad pueden ser "extraidos" del nivel de mddulo J2EE y llevados a1 nivel de aplicacidn de empresa e incluidos en esta etiqueta. Si existe un valor de rol de seguridad duplicado en uno de 10s mddulos JZEE, ese valor puede ser eliminado si el valor es proporcionado en el nivel de aplicacidn de empresa. Esta etiqueta requiere una sub-etiqueta < r o l e - n a m e > para proporcionar realmente el nombre simbdlico del rol de seguridad. U n ejemplo de configuracidn de una etiqueta es el siguiente: Empaquetado e implementation J2EE This is administrator's security role Administrator Cuestiones relacionadas con el orden de 10s modulos La especificaci6n JZEE no establece ninguna especificaci6n sobre c6mo deben implementarse 10s m6dulos JZEE contenidos en un archivo EAR. En concreto, el orden en el que 10s m6dulos deben ser implementados n o se describe explicitamente en la especificaci6n. Puede ser un problema si un componente de un m6dulo necesita usar otro componente en otro m6dulo todavia por implementar. La mayoria de 10s senidores de aplicaci6n implementarin 10s archivos EAR utilizando el mismo procedimiento: 1. Todos 10s adaptadores de recursos contenidos en el archivo EAR serin implementados en la infraestructura de conectores. Si se configuran mdtiples adaptadores de recursos, se implementarin en el orden en que aparecen en el descriptor application. xml. 2. Se implementarin todos 10s m6dulos EJB. Los EJB se implementan despuks de 10s adaptadores de recursos puesto que 10s EJB pueden hacer uso de un determinado adaptador de recursos durante su etapa de inicializaci6n. Si se configuran m~ltiplesm6dulos EJB, se implementarin el orden en que aparezcan listados en el descriptor de implementaci6n applicat ion. xml. 3. Se implementarin todos 10s m6dulos de aplicaci6n Web. Las aplicaciones Web se implementan despuks de 10s EJB y de 10s adaptadores de recursos puesto que las aplicaciones Web hacen uso de estos recursos durante su fase de inicializaci6n. Si se configuran mdtiples m6dulos de aplicaci6n Web, se implementarin en el orden en que aparezcan listados en el descriptor de implementaci6n application.xm1. Cuestiones relacionadas con paquetes de dependencia La cuesti6n mis frecuente relacionada con el empaquetado J2EE hace referencia a las clases de utilidad y de compatibilidad. A la hora de empaquetar una aplicaci6n Web o una aplicaci6n EJB, id6nde deben situarse estas bibliotecas? Si ubica estas clases en la ruta estindar de su senidor de aplicaci6n, probablemente perderin cualquier capacidad de descarga que tienen dichas aplicaciones Web y EJB que son controladas por 10s cargadores de clases utilizados para cargarlas en la implementaci6n. Si sus aplicaciones Web/EJB necesitan cambiar la versi6n de las bibliotecas que utilizan, entonces sera necesario volver a implementar la biblioteca dependiente cuando se vuelva a implementar la aplicaci6n Web/EJB. En esta situaci611, almacenar clases dewtilidad en la ruta de clase estindar n o es una opci6n viable puesto que el senidor de aplicaci6n completo tendria que ser reiniciado para cada implementaci6n de una aplicaci6n Web/EJB, lo que claramente no resulta ideal. Teniendo en cuenta la definici6n estindar de JZEE, id6nde se supone que deben situarse las bibliotecas de dependencia de mod0 que puedan volver a implementarse con una aplicaci6n en el period0 de ejecuci6n? Existen dos soluciones creativas, aunque indeseables en 6ltima instancia: Capitulo 24 Las bibliotecas de dependencia ernpaquetadas corno archivos JAR pueden situarse en el directorio WEB- I N F \ l i b de una aplicacion Web. Por lo general, el d i r e c t o r i o ~ E ~ I N- F \ l i b debe utilizarse principalrnente para el almacenamiento de clases de servlet, pero 10s servlets y las piginas JSP buscarin clases en este directorio a la hora de cargar clases nuevas. Si la biblioteca de utilidad que esti utilizando so10 la necesitan sus servlets y piginas JSP, esta soluci6n sera entonces suficiente. Sin embargo, si las misrnas bibliotecas tarnbien son necesitadas por EJB, consurnidores JMS o clases de arranque y cierre, entonces esta opci6n no funcionari puesto que el directorio WEBI N F \ l i b no es visible para estos elernentos. 0 Una copia completa de todas las bibliotecas de utilidad se situa en cada archivo JAR EJB adernis de en el archivo WEB- INF\lib. Cuando se irnplementa un EJB, un cargador de clases EJB so10 buscara cualquier clase de utilidad referenciada dentro de su propio archivo JAR. N o buscari en 10s archivos JAR de otras aplicaciones EJB que hayan sido irnplementadas ni en el directorio WEBINF\lib. Si todas sus aplicaciones EJB requieren el uso de la misrna biblioteca, entonces ubicar una copia de las clases de esa biblioteca en cada archivo JAR cubriri sus necesidades. Las clases de utilidad podrin volver a irnplementarse junto con el EJB. Aunque la segunda situacibn alcanza la capacidad de reimplementaci6n de las bibliotecas de dependencia, es increiblemente ineficiente. El propdsito de tener multiples archivos JAR para ernpaquetar es fornentar la rnodularidad de aplicaciones y situar la rnisrna clase en multiples archivos JAR destruye esta posibilidad. Adernis, tener multiples copias de las rnisrnas clases sobrecarga innecesariamente sus aplicaciones. Finalrnente, existe un paso afiadido para el proceso de construccion, puesto que cada archivo JAR tendri que ser reconstruido si desea cambiar incluso una unica biblioteca. Soluciones Una de las posibles soluciones a este problerna consiste en elirninar la necesidad de que haya multiples JAR en aplicaciones J2EE haciendo convergir todos 10s EJB y sus clases de utilidades en un paquete unificado. La especificaci6n EJB 2.0 esta dirigiendo algunos proyectos para conseguirlo. Esta version de la especificacion establece que 10s EJB de entidad que participen en una relacion lo hagan utilizando interfaces locales y ello requiere que ambos EJB que intervienen en la relacion Sean ernpaquetados en el rnisrno archivo JAR. Anteriores borrado~esde EJB 2.0 perrnitian a EJB de diferentes archivos JAR participar en relaciones, fornentando una mayor rnodularidad del sisterna pero, finalrnente, lirnitaba las optirnizaciones de persistencia disponibles para beans de entidad CMP en una relacion. El Borrador 2 Publico Final elirnin6 las relaciones rernotas; por ello, rnuchos vendedores estin pensando en facilitar herrarnientas que llevan a cab0 la convergencia JAR EJB. Estas herrarnientas tornarin corno entrada dos archivos JAR EJB validos y fusionarin sus clases y descriptores de irnplernentacion en un unico paquete unificado. Podria potencialmente utilizar una de estas herrarnientas de convergencia para volver a ernpaquetar sus aplicaciones JAR existentes para reducir la redundancia de las bibliotecas de dependencia entre archivos JAR EJB. En el rnornento de escribir este libro, estas utilidades de convergencia todavia estin siendo desarrolladas. Cornpruebe con su proveedor de servidor de aplicaci6n si hay alguna utilidad de convergencia disponible para su uso. Recuerde que, incluso si todos 10s EJB convergen en una unica aplicacih JAR, tendri que elirninar copias de su biblioteca de dependencia entre 10s EJB, per0 todavia seri necesario que exista una copia en una b i b 1 i o t e c a w ~ ~I-N F \ l i b si una aplicacion Web depende de ella. Adicionalrnente, la necesidad de rnodularidad de aplicaciones JEB sigue existiendo puesto que rnuchas cornpaiiias desean volver a implementar EJB de forma individual. Puesto que cada EJB de un JAR se volveri a irnplementar cuando vuelva a implernentarse ese archivo JAR, podria llevarse a cab0 una innecesaria cantidad de procesarniento si su unico deseo es volver a implernentar un unico EJB. Empaquetado e implernentacion J2EE Una solucion mejor C o n el lanzamiento de JDK 1.3, Sun Microsysterns redefini6 el "rnecanismo de extensi6n1'que es la funcionalidad necesaria para apoyar paquetes opcionales. El rnecanisrno de extensi6n esti disefiado para ser compatible con dos realidades: 0 Q u e 10s archivos JAR puedan declarar su dependencia de otros archivos JAR perrnitiendo 4ue una aplicaci6n estk formada por mdtiples m6dulos CI Q u e 10s cargadores de clases sean rnodificadas para buscar paquetes opcionales y rutas de aplicacion para clases Adicionalrnente, la especificacion J2EE 1.3 establece que 10s servidores de aplicacion deben ser compatibles con el rnecanismo de extensi6n tal y corno se define para archivos JAR. Esto requiere cualquier herrarnienta de implementaci6n que referencie un archivo JAR que sea capaz de cargar cualquier biblioteca optional definida a travks del mecanisrno de extension. Tambikn irnplica que si un servidor de aplicaci6n o una herrarnienta de irnplernentacidn sea compatible con las operaciones de desimplementaci6n y reimplementaci6n de aplicaciones EJB que utilicen bibliotecas a travks del mecanisrno de extensibn, por lo que esa herramienta o servidor de aplicaci6n debe tambikn ser compatible con la desimplementacidn y reimplementacidn de cualquier biblioteca dependiente. El apoyo para el rnecanismo de extensi6n no existe para EAR o aplicaciones de adaptadores de recursos tal y corno define la especificacion JZEE, puesto que estas aplicaciones no son cargadas directamente por una instancia de C l a s s l o a d e r . Las aplicaciones Web tienen la libertad de utilizar el mecanisrno de extensi6n o el directorio~EB-I N F \ l i b a1 especificar una biblioteca de dependencia. Corno hemos analizado anteriorrnente, el mod0 en que es cargada una biblioteca de dependencia variari dependiendo de si la biblioteca es especificada utilizando el rnecanismo de extensidn o el directoriowEB- I N F \ l i b . Las aplicaciones de ernpresa necesitan volver a ernpaquetar cualquier biblioteca que necesite la aplicacion Web o la aplicacion EJB corno parte del archivo EAR. Una vez ernpaquetada, el mecanismo de extensi6n proporciona un rnodo estindar para que 10s archivos WAR de aplicaci6n Web y 10s archivos JAR de aplicacion EJB especifiquen quk bibliotecas de dependencia existentes en el archivo EAR de la aplicacidn de empresa son necesarias. Comprender la ruta de clase manifiesta |