4. Tabla de contenidos
1. Presentación de openFWPA .............................................................................................. 1
Introducción .............................................................................................................. 1
Visión General de openFWPA ...................................................................................... 2
Empaquetamiento de openFWPA .......................................................................... 4
Requerimientos técnicos y de sistema ..................................................................... 5
Lista completa de funcionalidades ......................................................................... 5
Lista de componentes de terceras partes .................................................................. 6
Arquitectura de referencia ............................................................................................ 8
Desarrollo de aplicaciones .......................................................................................... 10
Estructura de directorios ..................................................................................... 10
Compilación y despliegue del sistema ................................................................... 11
Pruebas unitarias ............................................................................................... 11
Instalación de la aplicación de ejemplo (Sample App) .............................................. 11
2. Arquitectura Modelo -Vista- Controlador con openFWPA ..................................................... 13
MVC ...................................................................................................................... 13
Desarrollo de la Vista ................................................................................................ 14
Aspecto corporativo de las aplicaciones del Principado de Asturias ............................. 14
Cascading Style Sheets (CSS) ............................................................................. 14
Desarrollo del Controlador ......................................................................................... 16
Declaración de Actions ...................................................................................... 16
Jerarquía de Actions .......................................................................................... 17
Action Forms ............................................................................................. 29
Desarrollo de lógica de negocio .................................................................................. 31
Service Locator ................................................................................................ 31
Session EJBs .................................................................................................... 31
Value Objects .................................................................................................. 31
Excepciones ..................................................................................................... 32
Utilidades ........................................................................................................ 33
Otras clases de utilidad .............................................................................................. 33
PrincastMessageFmtter ............................................................................ 33
PrincastUtils ............................................................................................ 33
ParameterCaster ........................................................................................ 33
ServletPathUtils ...................................................................................... 33
DateDecorator ............................................................................................ 34
PrincastPathResolver .............................................................................. 34
PrincastOSCacheInterceptor .................................................................. 35
Providers ......................................................................................................... 35
3. Implementación de la Arquitectura de Referencia con openFWPA .......................................... 37
Inversión de Control en la Arquitectura de Referencia ..................................................... 37
Introducción al manejo de la Arquitectura con Spring ...................................................... 37
Estableciendo el Datasource ........................................................................................ 38
Enlazando con los DAOs ........................................................................................... 39
Enlazando con los Managers ....................................................................................... 40
Gestión de transacciones ............................................................................................ 41
Enlazado con los Delegates ........................................................................................ 42
Enlazado con las Actions ........................................................................................... 42
Acceso directo al ApplicationContext ................................................................. 43
BeanDoc para obtener la gráfica de arquitectura ............................................................. 43
Plugin SpringIDE para Eclipse .................................................................................... 43
4. Componentes para acceso a datos ..................................................................................... 45
Acceso a Bases de Datos Relacionales .......................................................................... 45
iv
5. Manual de Desarrollo
de Aplicaciones J2EE
El patrón DAO ................................................................................................. 45
Loggeo de las Excepciones en los DAO ................................................................ 47
Listas clave/valor .............................................................................................. 47
LookupPropertyBean .................................................................................. 49
Providers ......................................................................................................... 49
Generadores de Secuencia .................................................................................. 49
Pools de conexiones .......................................................................................... 50
5. Construccion de informes con openFWPA ......................................................................... 51
Generación de Informes ............................................................................................. 51
Creación de los diseños XML. ............................................................................ 51
Clases en el openFWPA para la renderización de informes. ...................................... 57
6. Operaciones ................................................................................................................. 61
Sistema de Inicialización y Arranque ............................................................................ 61
Declaración de objetos inicializables .................................................................... 61
Desarrollo de objetos inicializables ...................................................................... 62
Arranque de aplicaciones web ............................................................................. 63
Arranque manual .............................................................................................. 63
Sistema de Configuración de Aplicaciones .................................................................... 63
Implementación de objetos configurables .............................................................. 64
Plugins de Configuración ................................................................................... 66
Logging .................................................................................................................. 72
Log4J. Componentes ......................................................................................... 72
Configuración ................................................................................................... 74
Componentes del openFWPA para Logging. .......................................................... 75
Pista de auditoría .............................................................................................. 76
Pista de Rendimiento ......................................................................................... 77
Ficheros de Configuración .......................................................................................... 77
web.xml ........................................................................................................ 77
struts-config.xml .................................................................................... 79
Filtros web .............................................................................................................. 83
Filtros del openFWPA. PrincastFilter. ......................................................... 83
Configuración del filtro GZIPFilter ................................................................. 85
Configuración del filtro SecurityFilter ......................................................... 85
Filtro de navegación .......................................................................................... 85
Filtro de activación ........................................................................................... 86
Filtros de Activación ......................................................................................... 87
Consola de gestión .................................................................................................... 88
7. Seguridad en aplicaciones con openFWPA ......................................................................... 90
Seguridad ................................................................................................................ 90
Autentificación básica ........................................................................................ 90
Autentificación basada en formulario .................................................................... 90
Autentificación basada en el Filtro de Seguridad del openFWPA ............................... 90
Single Sign On ............................................................................................... 103
8. Integración de Sistemas ................................................................................................ 104
Tecnologías de Integración ....................................................................................... 104
XML Genérico: Configuración .......................................................................... 104
9. Pruebas ...................................................................................................................... 106
Pruebas unitarias ..................................................................................................... 106
Jerarquía de clases para las pruebas unitarias ........................................................ 106
Convenciones a seguir ..................................................................................... 107
Ejecución de las pruebas unitarias ...................................................................... 107
Consultando los resultados de los tests ................................................................ 107
Pruebas unitarias de objetos que acceden a bases de datos. ...................................... 108
Pruebas unitarias de Spring Beans ...................................................................... 112
v
6. Manual de Desarrollo
de Aplicaciones J2EE
Pruebas unitarias de objetos Configurables .................................................... 112
Pruebas unitarias en contenedor ......................................................................... 113
Pruebas unitarias de informes ............................................................................ 114
Más información sobre la implementación de pruebas unitarias ................................ 115
Pruebas de Rendimiento ........................................................................................... 116
Modo de Prueba de Rendimiento ....................................................................... 116
vi
7. Lista de figuras
1.1. Estructura de openFWPA ............................................................................................... 2
1.2. Arquitectura de Referencia ............................................................................................. 8
1.3. Estructura de directorios del proyecto Sample App. ........................................................... 10
2.1. Modelo Vista Controlador ............................................................................................ 13
2.2. Ciclo petición-acción-jsp de Struts ................................................................................. 13
2.3. Estructura de capas de las aplicaciones web con openFWPA ............................................... 14
2.4. Aspecto corporativo del portal princast.es ................................................................ 14
2.5. Aspecto de la aplicación de ejemplo (Sample App) ........................................................... 14
2.6. Jerarquía de Actions .................................................................................................... 17
2.7. Maquinaria de Estados de PrincastAction ................................................................ 18
2.8. Almacenamiento de la Action .................................................................................... 21
2.9. Esquema de la PrincastDispatchAction del ejemplo ............................................... 25
2.10. Esquema de las Actions para listados ............................................................................ 28
2.11. Estructura de la capa Modelo ...................................................................................... 31
2.12. Diagrama de Value Objects ........................................................................................ 32
2.13. Jerarquía de Excepciones ............................................................................................ 32
3.1. Ficheros de configuración de Beans ............................................................................... 37
3.2. Ejemplo de gráfica generada con BeanDoc ...................................................................... 43
3.3. Spring IDE para visualizar ficheros de Spring .................................................................. 44
4.1. Ejemplo de necesidad de lookup .................................................................................... 49
4.2. Navegación de una relación en BD con un LookupPropertyBean ......................................... 49
5.1. Proceso de generación de informes ................................................................................ 51
6.1. Estructura del sistema de configuración .......................................................................... 64
6.2. Jerarquía de Plugins .................................................................................................... 68
6.3. Estados del Sistema de Logging .................................................................................... 74
7.1. Esquema del sistema de autenticación ............................................................................ 91
9.1. Set de pruebas unitarias disponibles .............................................................................. 106
9.2. Autowiring de DAOs y DataSources ............................................................................ 110
vii
8. Lista de tablas
1.1. Componentes necesarios para la ejecución del openFWPA ................................................... 7
1.2. Capas de la Arquitectura de Referencia de openFWPA ........................................................ 9
viii
9. Capítulo 1. Presentación de openFWPA
Introducción
openFWPA es el framework de desarrollo libre para sistemas de administración electrónica y gobierno
electrónico desarrollado por el Gobierno del Principado de Asturias. Está basado en la tecnología J2EE y
su objetivo es facilitar el diseño, implementación, implantación y mantenimiento de las aplicaciones.
openFWPA es Software Libre / Open Source y está publicado bajo una doble licencia: LGPL 3.0 (o
superior) y EUPL 1.0 (o superior). La Licencia Pública General Menor del proyecto GNU (LGPL) es
una de las licencias desarrolladas y promovidas por la Free Software Foundation (FSF), y da permisos de
reproducción, distribución, modificación y redistribución con copyleft, aunque no se impide la utilización
de componentes privativos dentro del sistema. La Licencia Pública de la Unión Europea (EUPL) es una
licencia de software libre con copyleft creada y apoyada por la Unión Europea para el impulso del Software
Libre en las administraciones públicas.
Los dos grandes objetivos del framework son:
• Simplificación y homogeneización del proceso de desarrollo de aplicaciones. Para ello openFWPA
proporciona una arquitectura reutilizable y un conjunto de herramientas y librerías que implementan
algunos de los componentes más habituales, y de escritura más tediosa, en aplicaciones web. Todo ello
debiera redundar en un menor coste total de propiedad (TCO) de las soluciones desarrolladas sobre
openFWPA.
• Definición de estándares de desarrollo, calidad y aceptación. Se trata de un conjunto de directrices, de
obligado cumplimiento, para exigir y garantizar unos niveles mínimos de calidad en las aplicaciones
J2EE [1]. Estos estándares son internos al Principado de Asturias, y son por tanto aplicables solamente
dentro de aquellos proyectos desarrollados dentro del Principado de Asturias.
El openFWPA posee las siguientes características:
• Uso de software libre. Hay una serie de proyectos del mundo del software libre que poseen una excelente
calidad, lo que los habilita para participar en aplicaciones de misión crítica.
• Uso de patrones de diseño. El openFWPA promueve el uso de patrones de diseño, en dos sentidos
importantes. En primer lugar, el framework está diseñado y construido sobre patrones. Por otro lado,
las aplicaciones que se desarrollan sobre el framework hacen uso asimismo de patrones. Entre otros,
las aplicaciones desarrolladas sobre openFWPA siguen una arquitectura Modelo2 , el estándar en
aplicaciones web (se trata de una adaptación del famoso MVC).
• Uso de estándares. En el diseño del openFWPA se ha promovido la utilización e incorporación de
estándares (por ejemplo, XHTML [4] + CSS [14], etc.). El uso tanto de patrones de diseño como
de estándares proporciona importantes ventajas en cuanto a la adaptabilidad y longevidad de las
aplicaciones que los utilizan, al ser más fácilmente mantenidas, extendidas o reutilizadas.
• Aspecto corporativo. Otra característica importante es que las aplicaciones deben integrarse con el resto
de aplicaciones del Principado de Asturias, tanto a nivel funcional como de aspecto (look & feel). El
openFWPA incluye un conjunto de plantillas y componentes para construir la capa de presentación de
acuerdo a las guías de estilo corporativo del Principado de Asturias. En la versión publicada en portal,
estas plantillas pueden modificarse de acuerdo a las necesidades de cada proyecto. Sin embargo, los
proyectos internos han de seguir las directrices de estilo corporativo.
• Integración de aplicaciones. La nueva funcionalidad, añadida al openFWPA en las últimas versiones,
facilita la integración de las aplicaciones con otros sistemas del Principado de Asturias (sistema de
seguridad, comunicaciones, bases de datos corporativas, sistemas de seguridad, sistemas de CRM, etc.).
1
10. Presentación de openFWPA
Esta funcionalidad solo está disponible para los proyectos internos, al carecer de interés en aplicaciones
desarrolladas fuera de la organización.
• Ciclo de vida. Las aplicaciones poseen un ciclo de vida más allá de su desarrollo y puesta en producción.
Éstas han de ser configuradas, migradas y operadas en los diversos entornos. Por ejemplo, el framework
proporciona piezas con una funcionalidad importante que facilita el soporte a la operación. Los
componentes del framework están preparados para ser gestionados “en caliente” desde una consola
de operaciones, y ofrece componentes para aspectos críticos de operación (como gestión adecuada de
logging, pistas de auditoría, estadísticas de rendimiento y uso). En general, estos aspectos se incorporan
al framework de manera transparente a las aplicaciones. Asimismo, se ofrece (opcionalmente) una serie
de APIs avanzadas que permiten a las aplicaciones publicar funcionalidad en la consola de operaciones.
Visión General de openFWPA
El framework de desarrollo J2EE del Principado de Asturias posee la siguiente estructura. Dentro de cada
elemento se muestran los artefactos más relevantes:
Figura 1.1. Estructura de openFWPA
A continuación, se muestran en más detalle los diversos elementos que lo componen.
Aceptación Las aplicaciones desarrolladas con el framework para uso interno
del Principado de Asturias deben pasar por una serie de controles
de calidad. A tal efecto, se han desarrollado una serie de guías que
deben seguirse para el desarrollo de estas aplicaciones. Dentro de
esta guía de aceptación se define una arquitectura reutilizable que
debieran seguir las aplicaciones.
Entorno de desarrollo El framework de desarrollo es agnóstico en cuanto al entorno de
desarrollo. Éste debiera poseer los siguientes elementos:
• Entorno Integrado de desarrollo. Ofrece un entorno donde los
desarrolladores pueden desarrollar, compilar, depurar y probar el
software en construcción.
• Herramientas de despliegue. Permite el despliegue de las
aplicaciones en los distintos entornos (máquina local, máquinas
del entorno de desarrollo, etc.).
• Diseño de informes. Permite la construcción de informes en
distintos formatos.
• Gestión de la configuración. Permite la gestión del cambio de
los distintos elementos del sistema (código fuente, scripts de
construcción, pruebas, etc.). Se trata de un sistema de control de
versiones.
• Entorno de integración (semi) continua. El entorno de desarrollo
debiera ofrecer funcionalidad avanzada de integración continua
o semi-continua.
Los proyectos arrancados dentro del Principado de Asturias deben
poseer las herramientas definidas en el puesto estándar. Estas
2
11. Presentación de openFWPA
herramientas deben instalarse y configurarse de manera estándar
(igual para todas las estaciones de trabajo).
Software Libre Tras la definición de los requisitos del framework en términos de
herramientas necesarias para el entorno de desarrollo, directrices
de aceptación y diseño del runtime del framework, se realizó la
selección de distintos componentes del mundo del código abierto
o gratuito para su inclusión. Por ejemplo, se seleccionó Eclipse
como Entorno Integrado de Desarrollo, o CVS para el Control
de Versiones. Como elementos más relevantes, destaca el uso de
Eclipse, Spring o Struts.
Sistema de tiempo de ejecución El sistema de tiempo de ejecución es un conjunto de ficheros .jar
que se despliegan con cada una de las aplicaciones del framework.
Este sistema sigue las directrices de construcción de aplicaciones,
y ofrece componentes reutilizables y una base extensible para
el desarrollo basado fuertemente en patrones de diseño. De esta
manera, las aplicaciones se reducen en tamaño y complejidad,
teniendo todas la misma estructura interna (basada en una
adaptación del patrón MVC llamada Modelo2).
El sistema de tiempo de ejecución emplea diversos componentes
del mundo de código abierto, usando lo mejor de cada uno de
ellos e integrándolos. Esta aproximación ha facilitado enormemente
el desarrollo, y emplea internamente dos frameworks – Struts y
Spring.
Módulos de integración Los sistemas a construir dentro del ámbito de la Administración
del Principado de Asturias presentan una fuerte componente de
integración con otros sistemas. Se han escrito adaptadores para los
distintos sistemas corporativos existentes dentro de la organización,
de manera que se simplifica y homogeneíza enormemente las tareas
de integración siguiendo un patrón proxy. Estos módulos solo están
disponibles para aquellos proyectos realizados para el Principado
de Asturias.
Seguridad Es crucial que las aplicaciones desarrolladas posean un nivel
de seguridad suficiente, y que esta seguridad pueda gestionarse
centralmente desde los sistemas corporativos de seguridad. A este
fin, se ha desarrollado toda una infraestructura de seguridad sobre
estándares (X509, Java Authentication and Authorization Service,
Web Services, etc.). Desde el punto de vista de la aplicación, se
trata de realizar una parametrización. Toda esta infraestructura es
extensible. Dado que determinados proyectos se desarrollan por
equipos externos sin acceso a la infraestructura del Principado
de Asturias, se incluye un simulador de autenticación, de manera
que determinados escenarios pueden ejecutarse empleando un
documento XML en local como repositorio de credenciales.
Asimismo, esta infraestructura es extensible, de manera que pueden
desarrollarse adaptadores a otros repositorios (LDAP, etc) en
proyectos ajenos al Principado de Asturias.
Operación Las aplicaciones han de ser operadas en los distintos entornos,
de manera que el personal de operaciones pueda mantener la
3
12. Presentación de openFWPA
aplicación en funcionamiento. El framework posee una serie de
herramientas que facilitan esta operación, como pueden ser:
• Filtro de compresión. El framework proporciona un filtro de
compresión de las comunicaciones, de manera que se minimice
la comunicación entre el servidor y el cliente.
• Manual de Operaciones. En este documento se describen
las operaciones que pueden realizarse sobre la aplicación
desplegada.
• Configuración. El framework posee un subsistema flexible de
configuración, de manera que las aplicaciones se aislan de los
repositorios de configuración.
• Auditoría. Se proporciona funcionalidad para la generación de
pistas de auditoría.
• Gestión de logs. El framework proporciona un potente sistema
de logs, de manera que (por configuración) puede enviarse los
mensajes a una BD, a ficheros de texto, XML, HTML, etc. Esta
configuración puede cambiarse en caliente.
• Consola de Administración. Las aplicaciones desarrolladas con
el framework poseen una consola de administración web para la
modificación de los distintos componentes.
• Métricas de uso. Pueden habilitarse diversas métricas de uso de
la aplicación, de manera transparente para las aplicaciones.
Documentación Con el framework se entrega toda la documentación necesaria
para el desarrollo y operación de aplicaciones. Se entregan
una aplicación de ejemplo (con sus pruebas de rendimiento
correspondientes) y una aplicación en blanco, con la estructura de
directorios creada.
Soporte Existe un sitio de soporte para la resolución de dudas, incidencias,
etc. Este sitio web de soporte permite comunicar al equipo de
mantenimiento del framework bugs detectados, etc. de manera
que se pueda liberar una nueva entrega (release) con los defectos
corregidos. A tal efecto, se crea un usuario para cada equipo
de desarrollo que demande soporte, para que puedan realizar un
seguimiento consistente de las incidencias que puedan surgir.
Empaquetamiento de openFWPA
El conjunto completo de entregables que puede acompaña al openFWPA es el que sigue. En algunas
distribuciones, pueden no estar disponibles determinados elementos:
• Manual del desarrollador. (Este documento).
• Manual de operaciones.
• Manual de configuración de la seguridad.
• Directrices de aceptación de aplicaciones J2EE del Principado de Asturias.
4
13. Presentación de openFWPA
• Herramientas del desarrollador.
• Guía de estilo del lenguaje Java
• Guía de estilo del lenguaje JSP.
• openFWPA. (binarios)
• Aplicación de ejemplo: SampleApp (binarios y fuentes)
• Aplicación en blanco: App Blank (binarios y fuentes)
Requerimientos técnicos y de sistema
Para la correcta ejecución de las aplicaciones que utilizan el openFWPA es necesario disponer de los
siguientes elementos:
• Librerías de soporte (Ver “Lista de componentes de terceras partes”)
• Servidor de aplicaciones Oracle10G OC4J (versión 10.1.2) con Java JRE 1.4.2
Determinadas partes de la aplicación requieren además, los siguientes componentes:
a. Seguridad:
• Certificado Raíz de la Fabrica Nacional de Moneda y Timbre (FNMT)
• Fichero de certificados (cacerts) en la máquina virtual
Lista completa de funcionalidades
Las funcionalidades soportadas por el openFWPA son las siguientes:
• Extensión del framework Struts [8] con una colección propia de clases Action.
• Acceso a datos a través de objetos DAO.
• Automatización de la carga de consultas SQL desde ficheros de propiedades.
• Plantillas (Tiles) para la creación rápida de páginas JSP.
• Hojas de estilos con el look & feel del Principado de Asturias.
• Facilidades para la generación de informes en formato PDF.
• Etiquetas JSP para la inclusión de listas, barras de navegación, fechas y calendarios en las páginas web.
• Integración de formularios (ActionForm) con entidades (ValueObject) de la aplicación.
• Utilidades para la gestión de tablas de datos en formato {atributo, valor}.
• Facilidades para la obtención de listas paginadas como resultado de consultas.
• Herramienta para la generación automática de menús.
5
14. Presentación de openFWPA
• Infraestructura para pruebas unitarias.
• Infraestructura para pruebas unitarias en contenedor.
• Integración de una consola de monitorización y gestión basada en el estándar JMX [19].
• Jerarquía propia de excepciones.
• Monitorización y control integrado de errores
• Sistema de configuración centralizado.
• Sistema de inicialización y arranque configurable.
• Componentes para el acceso a pools de conexiones.
• Sistema de logging con varios niveles.
• Gestión de logging desde la consola de administración.
• Monitor de rendimiento.
• Sistema de monitorización para las clases Action.
• Generación de estadísticas de acceso a las aplicaciones.
• Generación de estadísticas de excepciones no controladas en las aplicaciones.
• Componente para monitorizar el estado del sistema sobre el que corre la aplicación.
• Infraestructura para filtros gestionados “en caliente”.
• Filtro para compresión GZIP.
• Inicialización de componentes configurables.
• Filtro de seguridad para integración con el Módulo de Autenticación del SAC del Principado de Asturias.
• Conexión con backends del Principado de Asturias (Claves, Terceros, Siebel, Módulo Común de SMS).
Lista de componentes de terceras partes
El framework de desarrollo del Principado de Asturias incorpora componentes de terceras partes. Las
aplicaciones que se construyan sobre el framework han de utilizar las versiones enumeradas en
6
15. Fundación Apache.
Struts Menu sourceforge.net struts-menu.jar 2.2 Librería para
struts-menu.tld facilitar el
struts-menu-el.tld
Presentación de openFWPA desarrollo de menús
en aplicaciones
web.
Tabla 1.1. Componentes necesarios para la ejecución del openFWPA
Apache Ant ASF 1.6.1 Herramienta para
la automatización
de las operaciones
de compilación,
construcción y
despliegue de
proyectos.
Java SDK Sun Microsystems 1.3.1_11 - 1.4.x Conjunto de
herramientas y
librerías Java.
Oracle AS9i Oracle oc4.jar admin.jar 9.0.3.0.0 - 10.1.2 Servidor de
aplicaciones de
Oracle.
JMX Reference Sun Microsystems jmxri.jar 1.0 Librería para la
Implementation jmxgrinder.jar gestión dinámica de
jmxtools.jar aplicaciones Java
(sólo es necesaria
con OC4J 9.0.3).
Base de Datos Oracle 8.1.7.3 Sistema de Gestión
Oraclae de Bases de Datos.
Jasper Reports sourceforge.net jasperreports.jar 0.6.0 Herramienta para
la generación de
informes en
diferentes formatos:
PDF, HTML, XLS,
CSV y XML.
JSSE Sun Microsystems jsse.jar 1.0.3_03 Proporciona
soporte para la
conexión bajo
protocolo SSL.
JAAS Sun Microsystems jaas.jar 1.0 Proporciona
soporte para
autentificación y
autorización.
JCE Sun Microsystems jce.jar 1.2.2 Proporciona
local_policy.jar soporte para uso
sunjce_provider.jar de protocolos de
US_export_policy.jar encriptación.
JDBC Sun Microsystems jdbc2_0-stdext.jar 2.0 Extensiones JDBC
para la compilación
con versión
1.3.1_11 de la JDK.
Spring Spring Framework spring.jar 1.2.6 Framework IoC.
Java Monitor API JAMon API JAMon.jar 1.1.2 Librería de
monitorización y
medición de
tiempos
Direct Web Get Ahead dwr.jar 1.0 Librería de AJAX
Remoting (DWR)
7
16. Presentación de openFWPA
Arquitectura de referencia
El framework de desarrollo del Principado de Asturias hace un uso intensivo de Patrones de Diseño. A fin
de lograr una homogeneidad efectiva en las aplicaciones realizadas en el marco del Principado de Asturias,
se propone una Arquitectura de Referencia que describe la arquitectura de las aplicaciones desarrolladas
con el openFWPA. El uso de esta arquitectura de referencia es obligatorio, al ser parte de las Directrices
de Aceptación de aplicaciones.
Una arquitectura de referencia es una descripción de los elementos de los que se compone una aplicación, y
de las relaciones entre estos elementos. Manejar arquitecturas de referencia es tremendamente beneficioso,
ya que permite: Homogeneizar las aplicaciones. Al usar la arquitectura de referencia, las aplicaciones
son estructuralmente iguales, cambiando sólo los elementos en concreto, pero no la forma que tienen de
relacionarse. Esto tiene un impacto directo en el esfuerzo en desarrollo y mantenimiento.
Extender las mejores prácticas y tecnologías. La arquitectura de referencia ha de mantenerse, de manera
que se vayan introduciendo cambios basados en cambios tecnológicos o en el establecimiento de mejores
prácticas.
La arquitectura de referencia J2EE propuesta se basa en el patrón Modelo2 sobre una disposición en capas,
y puede verse en el siguiente diagrama:
Figura 1.2. Arquitectura de Referencia
El concepto de separación en capas está claramente definido en esta arquitectura de referencia:
La comunicación entre capas sólo puede existir a través de a) interfaces, b) Objetos de Datos (Value
Objects). Los elementos de la arquitectura de referencia pueden verse en la siguiente tabla:
8
17. Presentación de openFWPA
Tabla 1.2. Capas de la Arquitectura de Referencia de openFWPA
Elemento Descripción Patrones relevantes
Capa de Acceso a Datos Encapsula toda la lógica de acceso Data Access Object Proxy Value
a datos. Asimismo, encapsula los Object Absctract Factory
accesos a sistemas remotos.
Capa de Objetos de Datos Representa las entidades del Value Object
modelo, como objetos JavaBean y
sin lógica de negocio.
Capa de Negocio Implementa toda la lógica de Business Delegate Façade
negocio, implementada como
procesos sobre la capa de Acceso
a Datos. Oculta toda la comlejidad
a la capa superior.
Capa de Controlador Transforma eventos en la vista a MVC Command
eventos en el modelo, y viceversa.
Capa de Vista Presenta el modelo al usuario, MVC
y comunica sus acciones al
controlador
Filtro web Permiten filtrar las peticiones de Chain Of Responsibility
los clientes, a fin de propor-cionar
autenticación, asertos a toda la
aplicación, compresión de datos,
etc.
Datasource Gestiona pools de conexiones, a
fin de no crear una conexión por
cliente a Base de Datos u otros
repositorios.
Gestión de sesión Gestiona la sesión de los clientes,
de manera que desconecta a los
inactivos.
Sistema externo Representa cualquier sistema a
integrar a través de un interfaz
bien definido.
Dado el número de librerías que implementan el patrón MVC, tiene todo el sentido usar alguna de ellas
en vez de implementarlo para un proyecto. El openFWPA da soporte para este patrón. Caso de ser una
aplicación J2EE no construida sobre el openFWPA, debiera hacer uso del framework Struts.
Una vez fijada la arquitectura de referencia, se ha acudido al mundo del software libre buscando
implementaciones de los elementos reseñados en ella. Por ejemplo, para la capa del controlador se ha
optado por usar una implementación de un proyecto del software libre en vez de proceder a realizar una
implementación propia. Asimismo, el openFWPA ofrece soporte en la implementación de todas las capas,
desde acceso a datos hasta presentación.
En general, prácticamente todas las librerías utilizadas por el openFWPA provienen de la Apache Software
Foundation (ASF) [5] y también pueden ser consideradas como estándares “de facto” en sus respectivas
áreas. Las librerías proporcionadas por la ASF, son de código libre y abierto, están mantenidas por un
nutrido grupo de desarrolladores de todo el mundo y son muy habituales en proyectos de desarrollo
(principalmente Java) de cualquier índole.
9
18. Presentación de openFWPA
Desarrollo de aplicaciones
Antes de comenzar el desarrollo de una aplicación web con el openFWPA, es importante tener en cuenta
las directrices y recomendaciones que se indican en este apartado.
Estructura de directorios
Las aplicaciones definirán una estructura de directorios siguiendo la plantilla:
• build, target: Contendrá los .class generados para el proyecto.
• db: Contendrá los scripts de creación de la base de datos o la propia base de datos. En caso de darse
soporte a más de una base de datos o más de una versión, ha de crearse un directorio para cada una
de las BD.
• config: Contendrá los ficheros necesarios para la creación del fichero EAR necesario para desplegar
la aplicación en el contenedor J2EE (como por ejemplo application.xml), así como los ficheros
con la información necesaria para la configuración de recursos que necesitará la aplicación (por ejemplo
DataSources. En este caso podría incluirse un fichero data-sources.xml con la información a
añadir al fichero data-soruces.xml del contenedor J2EE para la definición de los mismos).
• src: Este directorio contendrá dos subdirectorios:
• java: Contendrá los ficheros de código fuente Java y de recursos de la aplicación, y el fichero
build.xml.
• webapp:
• pages: Contendrá el resto de ficheros de la aplicación: páginas HTML, JSP, imágenes, hojas de
estilo CSS, etc.
• WEB-INF: Contendrá los ficheros de configuración XML (web.xml, struts-config.xml,
validation.xml, etc.), DTDs y TLDs.
• lib: Contendrá las librerías que será necesario distribuir con la aplicación, puesto que no estarán
incluidas en el contenedor J2EE.
• ejbApp:
• META-INF: Contendrá el fichero de MANIFEST.MF, así como los ficheros necesarios para el
despliegue de EJBs en caso de que sean utilizados en la aplicación. Estos ficheros sería ejb-
jar.xml, orion-ejb-jar.xml, … y cualquier otro fichero que fuera necesario.
• dist: Se trata de un directorio temporal empleado para la generación de los jars, ears,… necesarios
para el proyecto.
• javadoc: Contiene el javadoc generado con el target de Ant incluido al efecto.
Como ejemplo se muestra la estructura de la aplicación de ejemplo (Sample App):
Figura 1.3. Estructura de directorios del proyecto Sample App.
10
19. Presentación de openFWPA
Compilación y despliegue del sistema
Para la compilación y el despliegue de aplicaciones se utilizará la herramienta Ant [10] (http://
ant.apache.org). Ant es una herramienta de construcción basada en Java similar al clásico Make.
Los ficheros de configuración de Ant están escritos en XML y tienen por nombre build.xml. Cada uno
de ellos contiene un project y al menos un target (el default, que será el que se ejecutará si no se especifica
ningún otro en la llamada a Ant). Cada uno de ellos será el encargado de la compilación, empaquetado,
despliegue en el contenedor J2EE, etc. de la aplicación.
Con las aplicaciones en blanco (Blank App) de ejemplo (Sample App) de distribuye un fichero
build.xml. Los targets más relevantes son los siguientes:
• all (default): Realiza lo mismo que make-ear.
• compile: Compila los ficheros fuente Java de la aplicación.
• javadoc: Genera la documentación Javadoc.
• test.unit: Lanza las pruebas unitarias utilizando JUnit [11]. Busca en los paquetes de código fuente las
clases cuyo nombre termine en Test (según el convenio de nombrado de JUnit), ejecuta las pruebas y
genera informes con los resultados de las mismas en formato HTML.
• make-war: Genera un fichero WAR (Web Application Archive) con la aplicación, necesario para la
posterior generación del fichero EAR.
• make-ear: Genera un fichero EAR (Enterprise Application Archive) con la aplicación, que podrá ser
desplegado en un contenedor J2EE.
• deploy.localhost: Despliega la aplicación en el contenedor J2EE instalado en la máquina local.
• undeploy.localhost: Desinstala la aplicación del contenedor J2EE instalado en la máquina local.
• deploy.desa: Despliega la aplicación en el contenedor J2EE instalado en la máquina cuya IP está
contenida en la variable desa.test.host.
• undeploy.desa: Desinstala la aplicación del contenedor J2EE instalado en la máquina cuya IP está
contenida en la variable desa.test.host.
• new: Crea un nuevo proyecto a partir del proyecto actual, para ello es necesario pasarle el nombre del
proyecto nuevo mediante el parámetro -Dapp.name=proyectoNuevo. Esto copiará el proyecto
actual, al mismo nivel de directorio y sustituye el nombre del proyecto en los ficheros de configuración
que sea posible.
Pruebas unitarias
Es muy recomendable la implementación de pruebas unitarias, al menos para todos los componentes
críticos de la aplicación. Es también recomendable, en aplicaciones web, implementar pruebas unitarias
para todos los objetos de acceso a datos (DAO). Para facilitar esta tarea se puede utilizar la librería dbUnit
y la clase PrincastDatabaseTestCase, suministrada en el openFWPA.
Instalación de la aplicación de ejemplo (Sample App)
Para instalar la aplicación de ejemplo (Carrito) se deben seguir los pasos descritos en los siguientes
apartados.
11
20. Presentación de openFWPA
Configuración de la seguridad
Para habilitar la seguridad en la aplicación de ejemplo deben seguirse los pasos especificados en el
documento [Manual de Operaciones].
Configuración de la base de datos
Esta aplicación utiliza una base de datos MySQL. Se ha de copiar el driver JDBC para MySQL (mysql-
connector-java-3.0.12-production-bin.jar) en el directorio {OC4J_HOME}/j2ee/
home/applib. Para instalar la base de datos es necesario ejecutar la tarea ANT createdb incluida en
build.xml (quizá sea necesario cambiar el usuario y contraseña para conectarse a MySQL).
A continuación se edita el fichero data-sources.xml, que se encuentra en el directorio
{OC4J_HOME}/j2ee/home/config, y se le define un nuevo origen de datos para la aplicación añadiéndole
el siguiente código al fichero:
<data-source
class="com.evermind.sql.DriverManagerDataSource"
name="MySQLDS"
location="jdbc/CarritoDS"
xa-location="jdbc/xa/CarritoXADS"
ejb-location="jdbc/MySQLDS"
connection-driver="org.gjt.mm.mysql.Driver"
username="admin"
password=""
url="jdbc:mysql://localhost/carrito"
inactivity-timeout="30"/>
Si el servidor de base de datos no se encuentra en la misma máquina que OC4J, sustituir localhost por el
nombre o la dirección a dicha máquina. Hacer que los campos username y password coincidan con los de
algún usuario de MySQL con privilegios para acceder a la base de datos.
Llegados a este punto es necesario re iniciar el OC4J. Una vez re iniciado ejecutar el target deploy.localhost
del fichero build.xml, si se ejecuta desde la máquina donde está instalado OC4J, o deploy.desa si se trata
de una máquina remota (en este caso cambiar la variable desa.test.host del fichero build.xml debe apuntar
a la IP del servidor).
Una vez completado el proceso de instalación, la aplicación estará disponible desde la dirección http://
localhost:8888/carrito.
Para tener acceso al sistema puede utilizar como parámetros de autenticación los siguientes:
• Identificador de usuario: cliente.
• Contraseña: cliente.
12
21. Capítulo 2. Arquitectura Modelo -Vista-
Controlador con openFWPA
MVC
El patrón MVC – Model 2 puede ser visto como una implementación del lado del servidor del patrón de
diseño Modelo-Vista-Controlador (MVC). Este patrón describe cómo debe implementarse una aplicación
con tres elementos básicos:
Modelo Se trata de las entidades del dominio del problema, implementadas con
total independencia de su presentación.
Vista (Presentación) Esta capa se encarga de mostrar las entidades del modelo al usuario. En
el openFWPA, se implementa esta capa sobre la tecnología JSP. En esta
capa, no hay lógica de negocio
Controlador Traduce eventos/operaciones realizadas sobre la vista a invocaciones de
métodos en el modelo. En el openFWPA se emplean servlet para esta
capa. Básicamente, en esta capa se procesa la petición de entrada de
un cliente, se accede a las entidades del modelo y se coloca cualquier
elemento a pasar a la vista en algún ámbito de aplicación (request, session,
etc.). Asimismo, dispara un evento que se mapeará a una página jsp que
mostará los resultados.
Esta estrategia da lugar a una separación entre presentación y contenido, produciéndose una clara
definición de los roles y responsabilidades de los desarrolladores y diseñadores de páginas, en los equipos
de programación. De hecho, cuanto más compleja sea la aplicación, mayores son los beneficios de utilizar
la arquitectura de Modelo 2.
Figura 2.1. Modelo Vista Controlador
El proyecto Struts de la Apache Software Foundation es una implementación del MVC Modelo 2.
El núcleo del framework Struts es una capa de control flexible basada en tecnologías estándar como
servlets, JavaBeans, ResourceBundles y XML, así como varios paquetes del proyecto Jakarta Commons.
(http://jakarta.apache.org/commons).
Struts suministra su propio componente controlador (Controller) y se integra con otras tecnologías
para proporcionar el Modelo y la Vista. Para el Modelo, Struts puede interactuar con tecnologías de acceso
a datos estándar, como JDBC y EJB, así como con la mayoría de paquetes de terceras partes, como
Hibernate, iBATIS, u Object Relational Bridge. Para la Vista, Struts trabaja bien con JSPs, incluyendo
JSTL y JSF, así como con Velocity, XSLT y otros sistemas de presentación. Actualmente, el framework
del Principado de Asturias sólo da soporte a JDBC y JSP.
La figura siguiente muestra como es el ciclo petición-accion-jsp del framework Struts:
Figura 2.2. Ciclo petición-acción-jsp de Struts
Para obtener información más detallada sobre Struts consultar el tutorial que se adjunta en la
documentación de openFWPA.
13
22. Arquitectura Modelo -Vista-
Controlador con openFWPA
Figura 2.3. Estructura de capas de las aplicaciones web con openFWPA
Desarrollo de la Vista
Aspecto corporativo de las aplicaciones del Principado
de Asturias
Las aplicaciones construidas bajo los estándares del openFWPA de desarrollo J2EE se integrarán en el
portal del Principado de Asturias ya existente (http://www.princast.es) tanto en internet como
intranet. Por lo tanto debe respe-tarse el “look & feel” del portal en la medida de lo posible. Se
establece como premisa la construcción de un “look & feel” ligeramente diferenciado, pero que a su
vez respete la imagen corporativa del Principado de Asturias.
Para lograr este objetivo, se ha partido de la hoja de estilos general.css propiedad del Principado de
Asturias, y en base a ella se han desarrollado nuevas hojas de estilos que establezcan el aspecto de la vista
de las aplicaciones construidas bajo el framework. Estas hojas de estilo permiten separar las instrucciones
de formateo (posición, color, tamaño, etc) del código HTML generado por la aplicación. Esto ofrece una
mayor sencillez al desarrollo y una mayor adaptabilidad al cambio - en caso de ocurrir cambio de imagen
corporativa, se minimiza el ámbito del cambio unas pocas hojas de estilo CSS.
Figura 2.4. Aspecto corporativo del portal princast.es
Figura 2.5. Aspecto de la aplicación de ejemplo (Sample App)
Cascading Style Sheets (CSS)
La aplicación ejemplo (Sample App) maneja 5 hojas de estilos CSS. Debe tomarse esta implementación
como referencia de posicionamiento y formateo de textos, bloques, párrafos, etc. En general, se prohíbe
el uso de directrices de estilo dentro del código HTML. Cualquier estilo o posicionamiento de bloques
deberá ir contenido en una hoja de estilos CSS.
Hojas de estilo en la aplicación de ejemplo (Sample App)
Las hojas de estilo son enlazadas a través de la página head.jsp. En caso de necesitar nuevas hojas de
estilo, se utilizará este componente para hacerlo, de forma que esta tarea quede totalmente centralizada.
El código actual de la página head.jsp es:
<!-- Css basicas -->
<link rel="stylesheet" type="text/css" href="../../css/general.css" />
<link rel="stylesheet" type="text/css" href="../../css/position.css" />
<link rel="stylesheet" type="text/css" href="../../css/princast-ui.css" />
<!-- Css para el menú Tabs -->
<link rel="stylesheet" type="text/css" href="../../css/tabs.css" />
14
23. Arquitectura Modelo -Vista-
Controlador con openFWPA
<!-- Css para los listados -->
<link rel="stylesheet" type="text/css" href="../../css/displaytag.css" />
<!-- Css especifica de la aplicacion -->
<link rel="stylesheet" type="text/css" href="../../css/carrito.css" />
Las hojas de estilo manejadas por la aplicación de ejemplo SampleApp son:
general.css proviene de la hoja de estilos de referencia con el mismo nombre, incluida
en el portal princast.es. Ha sufrido ligeras modificaciones para adaptarse a las
necesidades del framework PA. Establece los estilos para los elementos más
comunes de una página HTML (enlaces, tablas, celdas, párrafos, listas, textos…)
position.css define el posicionamiento de los bloques <div> dentro de la página. La estructura
de una página se ha definido en base a bloques, de los cuales no todos tienen
porque aparecer, según las necesidades de página. Para más información, véase
los apartados correspondientes a los layouts tiles.
princast-ui.css hoja de estilos para el estilo de los componentes de las etiquetas de princast para
las páginas
tabs.css hoja de estilos para el tabbed menu.
displaytag.css hoja de estilos exclusiva para el aspecto de las tablas generadas por el tag
displaytag (Ver ???). El displaytag genera listas paginadas.
carrito.css Hoja de estilo para la ubicación y formato de componentes específicos de la
aplicación de ejemplo.
Estos ficheros CSS definen los estilos para aplicaciones de tramitación. Además de estas hojas de estilo,
se incluyen en el openFWPA ficheros CSS que definen estilos para aplicaciones de portal. Estas hojas de
estilo son: componentsPortal.css, displaytagPortal.css y carritoPortal.css.
Según lo expuesto, el código de las páginas JSP debe reducirse al mínimo imprescindible, obteniendo así
un código mucho más claro y mantenible.
Ejemplo: código JSP del cuerpo de una página de la aplicación Sample App:
<%@ page errorPage="/pages/errorEnJSP.jsp" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>
<%@ taglib uri="http://displaytag.sf.net" prefix="display" %>
<%@ taglib uri="/WEB-INF/tld/princast-ui.tld" prefix="ui" %>
<html:xhtml />
<div id="cuerpo">
<ui:errors/>
<ui:box bodyId="productos_box">
<ui:box-caption headingLevel="1">
<bean:message key="productos.box.caption" />
</ui:box-caption>
<display:table
name="sessionScope.ListaProductoKey"
id="listProd"
15
24. Arquitectura Modelo -Vista-
Controlador con openFWPA
pagesize="3"
export="false"
sort="page"
requestURI="../../../action/viewlistaproducto?paginate=true"
summary="Listado de productos"
>
<display:column>
<%=listProd_rowNum%>
</display:column>
<display:column titleKey="productos.column.name" sortable="true" >
<bean:define id="nombreProducto" name="listProd" property="name" toScope="page"
<html:link action="/viewdetalleproducto" paramId="id" paramName="listProd" para
<bean:write name="listProd" property="name" />
</html:link>
</display:column>
<display:column titleKey="productos.column.description" property="description" /
<display:column titleKey="productos.column.basePrice" property="basePrice" sorta
<display:column>
<bean:define id="url" name="listProd" property="smallImageURL" />
<bean:define id="nombre" name="listProd" property="name" toScope="page"/>
<html:img styleClass="imagen_producto" src="<%=url%>" alt="<%="Imagen de " +
</display:column>
<display:column titleKey="productos.column.moreInfo" sortable="false" class="cen
<html:link action="/viewdetalleproducto" paramId="id" paramName="listProd" para
<html:img src="../../images/icon_info_sml.gif" altKey="label.masinformacion"
</html:link>
</display:column>
</display:table>
</ui:box>
<html:img styleClass="carrito_image" src="../../images/productos.jpg" alt=""/>
<span id="pdf_link">
<html:link styleClass="enlace_imagen enlace_pdf" action="/viewlistaproductopdf" t
<bean:message key="productos.descargaPDF"/>
</html:link>
</span>
</div>
El código anterior responde a la forma en que se construye un cuerpo de página. No se ha utilizado en
ningún caso directrices de estilo o posicionamiento dentro de este código, y en esta forma resulta más
claro, donde se atiende únicamente a lo que debe mostrar la página y no a como y dónde debe mostrarlo.
Desarrollo del Controlador
Declaración de Actions
Desde la versión 1.5, las aplicaciones desarrolladas con el openFWPA, están basadas en el framework
Spring. Para poder inyectar dependencias en las Actions de las aplicaciones, es necesario que éstas
sean definidas como beans de Spring. En concreto, las definiciones de Actions se realizarán ahora en
el fichero: beans/web/action-beans.xml, este fichero se debe ubicar en el CLASSPATH.
<bean id="login" class="es.princast.sampleapp.web.action.LoginAction" singleton="fa
16
25. Arquitectura Modelo -Vista-
Controlador con openFWPA
</bean>
<bean id="logout" class="es.princast.sampleapp.web.action.LogoutAction" singleton=
<property name="carritoDelegate"><ref bean="carritoDelegate" /></property>
</bean>
Mientras que las Actions (clases) se declaran ahora en el fichero action-beans.xml, todos los aspectos
relativos a la navegación (forwards), mappings, formularios, etc. se sigue definiendo en el fichero struts-
config.xml.
En cada uno de los <action-mappings>, se debe inidcar el identificador (id) del bean que implementa
la lógica de la Action, utilizando el atributo "type". Si el valor de este atributo es el identificador
de un bean (de la clase Action), se tomará dicho bean para procesar las peticiones. Si el valor del
atributo "type" es el nombre de una clase (una Action), se instanciará normalmente (como en versiones
anteriores del openFWPA).
<action path="/login" type="login" scope="request" validate="false" input="/pages/l
<forward name="success" path="/action/viewperfil" redirect="true" />
<forward name="failure" path="/action/login" redirect="true" />
</action>
<action path="/logout" type="logout" scope="request">
<forward name="success" path="/action/login" redirect="true" />
</action>
En el código anterior se puede ver cómo se realiza el mapeo, en el fichero struts-config.xml, de
las Actions definidas más arriba como beans de Spring.
Atención
Para poder realizar este tipo de mapeos es necesario utilizar como controlador (Controller)
la clase PrincastRequestProcessor:
<controller processorClass="es.princast.framework.web.action.PrincastRequestProc
Jerarquía de Actions
En el openFWPA se proporciona un conjunto de Actions de Struts. Estas Actions definen un nuevo
ciclo de ejecución diferente del existente en las Actions típicas de Struts (ver más adelante). Las
aplicaciones que utilicen el openFWPA deben, obligatoriamente extender las Actions del Framework.
Además de ser una imposición, las Actions del openFWPA ofrecen funcionalidad de uso habitual en
las aplicaciones web.
Figura 2.6. Jerarquía de Actions
PrincastAction
La clase base de la jerarquía es PrincastAction. Es una clase abstracta que implementa una máquina
de estados de la que podrán hacer uso el resto de Actions. Define métodos que deben ser sobrescritos
por las actions de la aplicación. Estos métodos sobrescritos serán invocados por el framework para dar
respuesta a una solicitud de un cliente, y en un orden preestablecido. Este orden se presenta como un
esquema de la máquina de estados:
17
26. Arquitectura Modelo -Vista-
Controlador con openFWPA
Figura 2.7. Maquinaria de Estados de PrincastAction
Cada uno de los métodos que aparecen en la figura anterior tiene un cometido en particular. Este cometido
es el siguiente:
preProcess () Se emplea para comprobar las precondiciones que debe cumplir la
PrincastAction. En caso de que no se cumpla alguna precondición
se debe dejar un registro de ello mediante la creación de un error o un
mensaje, dependiendo de la gravedad del mismo. Al dejar constancia
de la incidencia se redireccionará el flujo de ejecución hacia una
página de error o a una de alerta, invocándose findFailure() y
findAlert(), respectivamente. La forma de crear una incidencia se
detalla en la sección 4.5.1.1.1.
executeActionLogic () Implementa la lógica de negocio de la PrincastAction. Éste será
el método sobrescrito de forma obligatoria por todas las acciones que
hereden de PrincastAction.
catchException() Se encarga del tratamiento de cualquier excepción que se pueda lanzar
durante la ejecución de la lógica de negocio de la PrincastAction.
Si no se quiere que la excepción sea lanzada de nuevo debe notificarse
su tratamiento mediante la llamada al método unsetException().
De esta forma se entenderá que todo el tratamiento necesario ya ha sido
llevado a cabo y la excepción no será elevada.
18
27. Arquitectura Modelo -Vista-
Controlador con openFWPA
postProcess() Se emplea para comprobar las poscondiciones que debe cumplir la
PrincastAction. En caso de que no se cumpla alguna poscondición
se debe dejar constancia de ello mediante la creación de un error o un
mensaje. Al dejar constancia de la incidencia se redireccionará el flujo
de ejecución hacia una página de error o a una de alerta, invocándose
findFailure() y findAlert(), respectivamente. La forma de
crear una incidencia se detalla en la sección 4.5.1.1.1.
findFailure() Redirecciona a una página de error. Por defecto, la redirección se hace a
lo que se indique en el atributo input de la Action. En caso de que este
atributo no sea definido se intentará hacer la redirección a un forward
llamado “failure”.
findAlert() Redirecciona a una página de alerta en la que se muestra un mensaje
informativo. Por defecto la redirección se hace a un forward llamado
“warning”.
findSuccess() Redirecciona a la página de éxito, es decir, a aquella a la que se debería
ir si la ejecución de la acción no tiene ningún error. Por defecto se
redirecciona a un forward llamado “success”.
Creando un error en una PrincastAction
El openFWPA posee soporte integrado a la gestión de errores para usuario. Por error se entiende cualquier
situación anómala en la aplicación, sea por un fallo del sistema o por datos incorrectos suministrados por
el usuario. Los errores que no son tratados por las aplicaciones se muestran al usuario final.
Atención
El método saveErrors(HttpServletRequest, List) está deprecado a partir de la
versión 1.5 del openFWPA . Los errores ya no se deben almacenar directamente en la request, en
su lugar, se utiliza el almacenamiento interno de las Action . Si se utiliza el método deprecado,
las Actions pueden no funcionar correctamente.
A continuación se muestra un ejemplo de creación de un error:
protected void preProcess(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
java.util.List error = new java.util.ArrayList();
error.add(“error.general”);
saveErrors(error);
};
Para crear un error, se debe crear una instancia de java.util.List a la que se le añadirán hasta cinco
elementos. El primero de estos elementos es la clave asociada al mensaje de error en el fichero de recursos.
En caso de que el mensaje de error sea una simple cadena de caracteres (como ocurre en el ejemplo) bastará
con un solo parámetro. En caso de que el mensaje lleve parámetros de la forma {0},{1},{2},{3},
un posible mensaje sería:
error.general=Ha ocurrido un error de tipo {0} a las {1} horas en {2} con usuario {
En este caso, la creación del error sería como sigue:
java.util.List error = new java.util.ArrayList();
error.add(“error.general”);
19
28. Arquitectura Modelo -Vista-
Controlador con openFWPA
error.add(“GRAVE”); // Parámetro {0}
error.add(“15:30”); // Parámetro {1}
error.add(“Gestión de usuarios”); // Parámetro {2}
error.add(“Administrador”) // Parámetro {3}
El usuario de la aplicación vería el siguiente mensaje:
Ha ocurrido un error de tipo GRAVE a las 15:30 horas en Gestión de usuarios con usu
Creando un mensaje de advertencia en una PrincastAction
La forma de crear un mensaje de advertencia es similar al de la creación de un mensaje de error, con la
salvedad de que en lugar de llamar al método saveErrors(HttpServletRequest, List) se ha
de invocar el método saveMessages(List).
Modificando una redirección
En el curso de tratamiento de una petición, puede ser necesario redirigir la petición a otro servlet.
PrincastAction proporciona una implementación por defecto para las redirecciones que pueden tener
lugar durante la ejecución de una petición a una acción. Los métodos que se encargan de estas redirecciones
son:
findSuccess() Redirecciona a un forward etiquetado “success”.
findFailure() Redirecciona a lo que se indique en el atributo input del elemento <action>
correspondiente o a un forward etiquetado “failure” en caso de que no se
defina el atributo input.
findAlert() Redirecciona a un forward etiquetado “warning”.
Todos ellos siguen la misma signatura:
ActionForward find<redireccion> (ActionMapping mapping, ActionForm
form, HttpServletRequest request, HttpServletResponse response);
La forma de modificar la redirección de estos métodos es devolviendo una instancia diferente del
ActionForward. Por ejemplo, imaginemos que cuando la ejecución de la PrincastAction es
éxitosa deseamos que se nos redireccione a un forward etiquetado como “ok”. En este caso, deberíamos
sobrescribir el método findSuccess() como se muestra a continuación:
ActionForward findSuccess(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
return mapping.findForward(“ok”);
};
Como se puede apreciar en el ejemplo anterior, la cuestión es obtener del mapping (o crear indicando el
path) un ActionForward a donde deseamos redireccionar la repuesta.
ActionForward findSuccess(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
return new ActionForward("ok", "/action/test?method=ok", true);
};
20
29. Arquitectura Modelo -Vista-
Controlador con openFWPA
Almacenamiento interno de una Action
Las Actions de Struts no son thread-safe. No es correcto utilizar atributos de instancia para compartir
información entre los distintos métodos del ciclo de vida de una Action. En las ocasiones en que fuera
indispensable utilizar un atributo de instancia, se recomienda utilizar el almacenamiento interno de la
Action. Este almacén es un mapa de parámetros thread-local, cuyo ámbito se limita a los métodos del
ciclo de vida de la Action (preProcess(), executeActionLogic(), catchException()
y postProcess()).
Figura 2.8. Almacenamiento de la Action
Para acceder y manipular este almacenamiento, la PrincastAction dispone de los siguientes métodos:
deleteActionParameter(nombre) del almacén el parámetro especificado.
Borra
getActionParameter(nombre)Obtiene del almacén el parámetro cuyo nombre se especifica.
getActionParameters() Obtiene un iterador con los nombres de todos los parámetros del
almacén.
setActionParameter(nombre,Almacena un parámetro identificándolo con el nombre dado.
valor)
A continuación se muestra un ejemplo de uso de este almacén:
public class MyAction extends PrincastAction {
public MyAction(){
setActionParameter("oneParam", "oneValue");
}
protected void preProcess(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
setActionParameter("myParam", "foo");
}
protected void executeActionLogic(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String param1 = (String) getActionParameter("myParam");
String param2 = (String) getActionParameter("oneParam");
…
}
}
En la Action del ejemplo: MyAction, se han sobrescrito dos métodos del ciclo de vida de la Action:
preProcess() y executeActionLogic(). En el método preProcess(), se establece el valor
de un parámetro: “myParam”, asignándole la cadena “foo”. Por otro lado, en el constructor, se establece
un valor para el parámetro “oneParam”. En el método executeActionLogic(), se recuperan los
valores de ambos parámetros. Recuérdese que únicamente los métodos del ciclo de vida de la ejecución de
la Action tienen visibilidad del almacén. Por este motivo, en el método executeActionLogic(),
la variable param1 tomará el valor “foo”, mientras que la variable param2 tendrá como valor null.
21
30. Arquitectura Modelo -Vista-
Controlador con openFWPA
Interrupción de la maquinaria de estados de la Action
En algunas ocasiones es necesario interrumpir el proceso de la maquinaria de estados de la Action sin
redirigir a un estado de error. Para interrumpir la ejecución de la Action, basta con disparar una excepción
de tipo ActionProcessInterruption.
Un uso práctico de esta excepción es el siguiente:
Paginación sin reejecución de la lógica de negocio.
El problema es el siguiente: utilizando la librería Display Tag, cada vez que se produzca un movimiento de
página, se solicita una nueva ejecución de la Action que genera el listado, suponiendo esto la reejecución
de la lógica de negocio completa (con acceso a datos incluido). La solución a este problema es la que sigue:
• Almacenar siempre las listas de bean a mostrar por el Display Tag en el scope session.
• En la etiqueta del Display Tag, en el atributo “requestUri”, añadir a la URL de la Action un
parámetro GET (que la no entre en conflicto con alguno que ya utilice la Action).
<display:table name="sessionScope.ListaProductoKey" align="center"
id="listProd"
pagesize="3"
export="false"
sort="page"
requestURI="../../action/viewlistaproducto?paginate=true">
• Extender el método preProcess(). En este método se detectará la existencia del parámetro definido
y, en tal caso, se disparará una ActionProcessInterruption.
protected void preProcess(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
if (request.getParameter("paginate") != null) {
throw new ActionProcessInterruption();
}
}
Otra opción es utilizar una de las Actions que ya vienen con esta funcionalidad implementada:
PrincastCRUDAction y PrincastListAction.
Diferentes tipos de PrincastAction
Además de la clase base PrincastAction, en el openFWPA se proporcionan otros tipos de Actions.
Por un lado están PrincastDispatchAction y PrincastCRUDAction, una generalización de la
anterior, y por otro una serie de implementaciones concretas de la PrincastAction tratada en el punto
anterior que facilitan el desarrollo de funcionalidades recurrentes en aplicaciones de gestión.
Implementaciones concretas
Existen varias clases que tienen una funcionalidad determinada y que pueden ser reutilizadas tal y como
están. Estas son:
• PrincastExistAttributeAction
• PrincastRemoveAttributeAction
22
31. Arquitectura Modelo -Vista-
Controlador con openFWPA
• PrincastForwardAction
• PrincastParameterAction
PrincastExistAttributeAction
Esta clase se encarga de verificar la existencia de un atributo en alguno de los scopes o ámbitos (request,
session o application) de la aplicación web. En la propiedad "parameter" del <action-
mapping> se indicará el scope y el nombre del atributo a eliminar, separados por ";". Por ejemplo:
parameter="application;HOURS". Si se quiere buscar el atributo en cualquier scope se utilizará
un *. Por ejemplo:
parameter="*;HOURS". Si no se especifica alguno de los dos parámetros, se produce un error.
PrincastRemoveAttribute
Esta clase trata de eliminar un atributo dentro de uno de los ámbitos posibles (application, request,
session). Si el atributo existe devuelve el control a un ActionForward etiquetado con “success”
y, sino, a uno etiquetado con “failure”.
Tanto el ámbito como el atributo se pasan en la propiedad parameter de ActionMapping separados por
";" (parameter="application;HORAS").
Para indicar que la búsqueda se realice en todos los ámbitos, el primer parámetro debe ser un asterisco
("*") en lugar del nombre de un ámbito (parameter="*;HORAS"). El atributo sólo será eliminado del
primer contexto en el que sea localizado.
PrincastForwardAction
Acción que redirecciona a la URI relativa al contexto especificada por la propiedad parameter del
ActionMapping. Esta clase puede ser usada para integrar la aplicación con otra lógica de negocio de
otros componentes implementados como Servlets o páginas JSP, pero manteniendo la funcionalidad
del Servlet controlador de Struts (como el procesado de form beans).
Para configurar una PrincastAction de este tipo en el fichero struts-config.xml es necesario
crear una etiqueta como ésta :
<action path="/guardaSuscripcion"
type="es.princast.framework.web.action.PrincastForwardAction"
name="suscripcionForm" scope="request" input="/suscripcion.jsp"
parameter="/path/a/servlet"/> que redireccionará el control a la URI relativa al contexto /
path/a/servlet .
PrincastParameterAction
Esta Action busca un parámetro en la request llamado dispatch y usa su valor para recuperar
un forward local. Una vez conseguido este forward busca un segundo parámetro en la request
cuyo nombre debe ser especificado en la propiedad parameter del ActionMapping. Este valor
se concatena con el valor de la propiedad path del forward obtenido con anterioridad. La
URI resultante es la que se usa para hacer la redirección. Un ejemplo de la declaración de una
PrincastParameterAction de este tipo es:
<action
path="/menu/busca"
type="es.princast.framework.web.action.PrincastParameterAction"
name="menuForm"
validate="false"
23
32. Arquitectura Modelo -Vista-
Controlador con openFWPA
parameter="keyValue">
<forward
name="titulo"
path="/do/busca/Titulo?titulo=" />
<forward
name="autor"
path="/do/busca/Autor?autor=" />
<forward
name="contenido"
path="/do/busca/Contenido?contenido=" />
</action>
Un fragmento de una página JSP que hiciera uso de esto podría ser:
<html:form action="menu/busca">
Busca artículos por :
<html:select property="dispatch">
<html:option value="titulo">Titulo</html:option>
<html:option value="autor">Autor</html:option>
<html:option value="contenido">Contenido</html:option>
</html:select>
<html:text property="keyValue" />
<html:submit>Enviar</html:submit>
</html:form>
Si el usuario elige Contenido y escribe Java en el campo de texto, el navegador
enviará: dispatch=contenido keyValue=Java Con esta información la
PrincastParameterAction busca el forward contenido y concatena el valor de keyValue
al path del forward, quedando algo del estilo: /do/busca/Contenido?contenido=Java
En los forwards definidos dentro del mapping de la PrincastParameterAction es posible
incluir parámetros almacenados en la request utilizando la notación ${<nombre del parámetro>}.
La PrincastParameterAction buscará, en el path (definido en el forward) la cadena
"${<parámetro>}" y la sustituirá por “<parámetro>=<valor de parámetro>". Si, por
ejemplo, el valor del parámetro "Titulo" es "Rambo" y se define la siguiente forward: <forward
name=”titulo” path=”/do/busca?${Titulo}” /> La PrincastParameterAction
dirigirá a la siguiente URL: /do/busca?Titulo=Rambo.
Actions Compuestas (Dispatch)
En muchas ocasiones interesa tener juntas aquellas acciones que se encargan de tareas relacionadas. Los
métodos que se encargan de la ejecución de tales tareas son encapsulados en una misma clase. Para estos
casos están pensadas las acciones que se presentan en este apartado: PrincastDispatchAction,
PrincastCRUDAction.
PrincastDispatchAction
Esta clase es una especialización de la PrincastAction. Mantiene la misma estructura de máquina
de estados que su clase padre pero se puede decir que cada una de las acciones que encapsula dispone de
su propia máquina de estados.
Si por ejemplo queremos encapsular juntas las acciones “update” e “insert” tendríamos:
updatePreProcess, updateExecuteActionLogic, etc. - y también insertPreProcess,
insertExecuteActionLogic, etc. A pesar de que cada acción pueda tener su propia máquina de
estados, puede interesar que las acciones compartan determinada funcionalidad. Para estos casos están los
métodos defaultPreProcess, defaultExecuteActionLogic, etc.
24
33. Arquitectura Modelo -Vista-
Controlador con openFWPA
¿Cómo identificar los métodos a ejecutar?
A la hora de seleccionar los métodos a ejecutar la PrincastDispatchAction hace uso del valor
que se le pasa en el parámetro parameter del ActionMapping asociado. Si lo que queremos es ejecutar
los métodos de la máquina de estados asociada a la acción “update”, entonces este parámetro debe ser
<action-mapping …… parameter="method" ….. />, donde el valor del parámetro method,
será update. Si no se da implementación a alguno de los métodos update<estado_máquina>,
por ejemplo updatePreProcess(), la PrincastDispatchAction ejecutará el método
defaultPreProcess(). De igual modo ocurre con el resto de métodos.
Es posible desacoplar el valor del parámetro del nombre del método. Se pueden establecer mapeos
{valor_de_parameter, nombre_de_método} extendiendo el método getMethodKey() de la clase
PrincastDispatchAction.
La PrincastDispatchAction permite, por defecto, una salida de éxito (success), otra de error
(error) y para cada método de la Action. Por convenio, en la PrincastDispatchAction, la
salida de éxito de un método será un forward cuyo nombre será el mismo que la clave del método. El
forward de error equivaldrá al nombre del método concatenado con la cadena “-failure”. Para el
forward de advertencia se concatenará la cadena “-warning” al nombre del método.
<action path="/customDispatchAction"
name="aForm"
parameter="method"
type="customDispatchActionBean"
validate="false"
scope="session">
<forward name="method1" path="success.path" />
<forward name="method1-failure" path="failure.form" />
<forward name="method2" path="success.dos.path" />
<forward name="failure" path="failure.path" />
</action>
En el ejemplo superior, se está mapeando una Action de tipo PrincastDispatch con dos
métodos: method1 y method2. Cuando se ejecute con éxito el método method1, se redireccionará
al path: “success.path”. Si hay algún error, la redirección se realizará al path: “failure.form”.
Por el contrario, cuando se ejecute el método method2, en caso de éxito la redirección se hará
al path: “success.dos.path” y cuando se produzca un error, el path de redirección será:
“failure.path” (ya que, aunque no ha sido definido un forward de error específico, se ha definido el
forward de error por defecto: “failure”).
Figura 2.9. Esquema de la PrincastDispatchAction del ejemplo
En ocasiones, es necesario que una DispatchAction tenga mayor control sobre las redirecciones
(forwards) que debe realizar para cada uno de los métodos de dispatch. Al igual que ocurre con
otros métodos de la Action (executeActionLogic(), catchException(), etc.) es posible
redefinir los métodos de redirección (findSuccess(), findAlert() y findFailure()). El
sistema es exactamente el mismo: prefijar cada método con la clave (MethodKey). Por ejemplo:
method1FindSuccess(), method2FindFailure(), etc.
PrincastLookupDispatchAction
La clase PrincastLookupDispatchAction pemite implementar un tipo especial de Dispatch
Actions para formularios con mas de un botón (submit). Es este escenario, el botón que se utilice para
el envío del formulario (submit) será quien determine el método que se ejecutará en la Action.
25