Documentos de Académico
Documentos de Profesional
Documentos de Cultura
de Aplicaciones J2EE
Tabla de contenidos
1. Presentacin de openFWPA .............................................................................................. 1
Introduccin .............................................................................................................. 1
Visin General de openFWPA ...................................................................................... 2
Empaquetamiento de openFWPA .......................................................................... 4
Requerimientos tcnicos 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
Compilacin y despliegue del sistema ................................................................... 11
Pruebas unitarias ............................................................................................... 11
Instalacin de la aplicacin 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
Declaracin de Actions ...................................................................................... 16
Jerarqua de Actions .......................................................................................... 17
Action Forms ............................................................................................. 29
Desarrollo de lgica 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. Implementacin de la Arquitectura de Referencia con openFWPA .......................................... 37
Inversin de Control en la Arquitectura de Referencia ..................................................... 37
Introduccin al manejo de la Arquitectura con Spring ...................................................... 37
Estableciendo el Datasource ........................................................................................ 38
Enlazando con los DAOs ........................................................................................... 39
Enlazando con los Managers ....................................................................................... 40
Gestin de transacciones ............................................................................................ 41
Enlazado con los Delegates ........................................................................................ 42
Enlazado con las Actions ........................................................................................... 42
Acceso directo al ApplicationContext ................................................................. 43
BeanDoc para obtener la grfica de arquitectura ............................................................. 43
Plugin SpringIDE para Eclipse .................................................................................... 43
4. Componentes para acceso a datos ..................................................................................... 45
Acceso a Bases de Datos Relacionales .......................................................................... 45
iv
Manual de Desarrollo
de Aplicaciones J2EE
5.
6.
7.
8.
9.
Manual de Desarrollo
de Aplicaciones J2EE
Pruebas unitarias de objetos Configurables ....................................................
Pruebas unitarias en contenedor .........................................................................
Pruebas unitarias de informes ............................................................................
Ms informacin sobre la implementacin de pruebas unitarias ................................
Pruebas de Rendimiento ...........................................................................................
Modo de Prueba de Rendimiento .......................................................................
vi
112
113
114
115
116
116
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 peticin-accin-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 aplicacin de ejemplo (Sample App) ........................................................... 14
2.6. Jerarqua 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. Jerarqua de Excepciones ............................................................................................ 32
3.1. Ficheros de configuracin de Beans ............................................................................... 37
3.2. Ejemplo de grfica generada con BeanDoc ...................................................................... 43
3.3. Spring IDE para visualizar ficheros de Spring .................................................................. 44
4.1. Ejemplo de necesidad de lookup .................................................................................... 49
4.2. Navegacin de una relacin en BD con un LookupPropertyBean ......................................... 49
5.1. Proceso de generacin de informes ................................................................................ 51
6.1. Estructura del sistema de configuracin .......................................................................... 64
6.2. Jerarqua de Plugins .................................................................................................... 68
6.3. Estados del Sistema de Logging .................................................................................... 74
7.1. Esquema del sistema de autenticacin ............................................................................ 91
9.1. Set de pruebas unitarias disponibles .............................................................................. 106
9.2. Autowiring de DAOs y DataSources ............................................................................ 110
vii
Lista de tablas
1.1. Componentes necesarios para la ejecucin del openFWPA ................................................... 7
1.2. Capas de la Arquitectura de Referencia de openFWPA ........................................................ 9
viii
Presentacin de openFWPA
Esta funcionalidad solo est disponible para los proyectos internos, al carecer de inters en aplicaciones
desarrolladas fuera de la organizacin.
Ciclo de vida. Las aplicaciones poseen un ciclo de vida ms all de su desarrollo y puesta en produccin.
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 operacin. Los
componentes del framework estn preparados para ser gestionados en caliente desde una consola
de operaciones, y ofrece componentes para aspectos crticos de operacin (como gestin adecuada de
logging, pistas de auditora, estadsticas 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.
Entorno de desarrollo
Presentacin de openFWPA
Mdulos de integracin
Seguridad
Operacin
Presentacin de openFWPA
Soporte
Empaquetamiento de openFWPA
El conjunto completo de entregables que puede acompaa 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 configuracin de la seguridad.
Directrices de aceptacin de aplicaciones J2EE del Principado de Asturias.
Presentacin de openFWPA
Presentacin de openFWPA
Fundacin Apache.
Struts Menu
sourceforge.net
struts-menu.jar
struts-menu.tld
struts-menu-el.tld
Presentacin
de openFWPA
2.2
Librera
para
facilitar
el
desarrollo de mens
en
aplicaciones
web.
Tabla
necesarios para la ejecucin
Apache1.1.
Ant Componentes
ASF
1.6.1del openFWPA
Herramienta
para
la automatizacin
de las operaciones
de
compilacin,
construccin
y
despliegue
de
proyectos.
Java SDK
Sun Microsystems
1.3.1_11 - 1.4.x
Conjunto
herramientas
libreras Java.
de
y
Oracle AS9i
Oracle
9.0.3.0.0 - 10.1.2
Servidor
aplicaciones
Oracle.
de
de
JMX
Reference Sun Microsystems jmxri.jar
Implementation
jmxgrinder.jar
jmxtools.jar
1.0
Librera para la
gestin dinmica de
aplicaciones Java
(slo es necesaria
con OC4J 9.0.3).
Base de
Oraclae
8.1.7.3
Sistema de Gestin
de Bases de Datos.
0.6.0
Herramienta para
la generacin de
informes
en
diferentes formatos:
PDF, HTML, XLS,
CSV y XML.
oc4.jar admin.jar
Datos Oracle
Jasper Reports
sourceforge.net
JSSE
1.0.3_03
Proporciona
soporte para la
conexin
bajo
protocolo SSL.
JAAS
1.0
Proporciona
soporte
para
autentificacin
y
autorizacin.
JCE
Proporciona
soporte para uso
de protocolos de
encriptacin.
JDBC
2.0
Extensiones JDBC
para la compilacin
con
versin
1.3.1_11 de la JDK.
Spring
1.2.6
Framework IoC.
JAMon API
JAMon.jar
1.1.2
Librera
de
monitorizacin y
medicin
de
tiempos
dwr.jar
1.0
Librera de AJAX
Direct
Web Get Ahead
Remoting (DWR)
jasperreports.jar
Presentacin de openFWPA
Arquitectura de referencia
El framework de desarrollo del Principado de Asturias hace un uso intensivo de Patrones de Diseo. 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 Aceptacin de aplicaciones.
Una arquitectura de referencia es una descripcin de los elementos de los que se compone una aplicacin, 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 slo 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 prcticas y tecnologas. La arquitectura de referencia ha de mantenerse, de manera
que se vayan introduciendo cambios basados en cambios tecnolgicos o en el establecimiento de mejores
prcticas.
La arquitectura de referencia J2EE propuesta se basa en el patrn Modelo2 sobre una disposicin en capas,
y puede verse en el siguiente diagrama:
Presentacin de openFWPA
Descripcin
Patrones relevantes
Capa de Negocio
Capa de Controlador
Capa de Vista
Filtro web
Datasource
Gestin de sesin
Sistema externo
Dado el nmero de libreras que implementan el patrn MVC, tiene todo el sentido usar alguna de ellas
en vez de implementarlo para un proyecto. El openFWPA da soporte para este patrn. Caso de ser una
aplicacin 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 reseados en ella. Por ejemplo, para la capa del controlador se ha
optado por usar una implementacin de un proyecto del software libre en vez de proceder a realizar una
implementacin propia. Asimismo, el openFWPA ofrece soporte en la implementacin de todas las capas,
desde acceso a datos hasta presentacin.
En general, prcticamente todas las libreras utilizadas por el openFWPA provienen de la Apache Software
Foundation (ASF) [5] y tambin pueden ser consideradas como estndares de facto en sus respectivas
reas. Las libreras proporcionadas por la ASF, son de cdigo libre y abierto, estn mantenidas por un
nutrido grupo de desarrolladores de todo el mundo y son muy habituales en proyectos de desarrollo
(principalmente Java) de cualquier ndole.
Presentacin de openFWPA
Desarrollo de aplicaciones
Antes de comenzar el desarrollo de una aplicacin web con el openFWPA, es importante tener en cuenta
las directrices y recomendaciones que se indican en este apartado.
Estructura de directorios
Las aplicaciones definirn una estructura de directorios siguiendo la plantilla:
build, target: Contendr los .class generados para el proyecto.
db: Contendr los scripts de creacin de la base de datos o la propia base de datos. En caso de darse
soporte a ms de una base de datos o ms de una versin, ha de crearse un directorio para cada una
de las BD.
config: Contendr los ficheros necesarios para la creacin del fichero EAR necesario para desplegar
la aplicacin en el contenedor J2EE (como por ejemplo application.xml), as como los ficheros
con la informacin necesaria para la configuracin de recursos que necesitar la aplicacin (por ejemplo
DataSources. En este caso podra incluirse un fichero data-sources.xml con la informacin a
aadir al fichero data-soruces.xml del contenedor J2EE para la definicin de los mismos).
src: Este directorio contendr dos subdirectorios:
java: Contendr los ficheros de cdigo fuente Java y de recursos de la aplicacin, y el fichero
build.xml.
webapp:
pages: Contendr el resto de ficheros de la aplicacin: pginas HTML, JSP, imgenes, hojas de
estilo CSS, etc.
WEB-INF: Contendr los ficheros de configuracin XML (web.xml, struts-config.xml,
validation.xml, etc.), DTDs y TLDs.
lib: Contendr las libreras que ser necesario distribuir con la aplicacin, puesto que no estarn
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 aplicacin. Estos ficheros sera ejbjar.xml, orion-ejb-jar.xml, y cualquier otro fichero que fuera necesario.
dist: Se trata de un directorio temporal empleado para la generacin 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 aplicacin de ejemplo (Sample App):
10
Presentacin de openFWPA
Pruebas unitarias
Es muy recomendable la implementacin de pruebas unitarias, al menos para todos los componentes
crticos de la aplicacin. Es tambin recomendable, en aplicaciones web, implementar pruebas unitarias
para todos los objetos de acceso a datos (DAO). Para facilitar esta tarea se puede utilizar la librera dbUnit
y la clase PrincastDatabaseTestCase, suministrada en el openFWPA.
11
Presentacin de openFWPA
Configuracin de la seguridad
Para habilitar la seguridad en la aplicacin de ejemplo deben seguirse los pasos especificados en el
documento [Manual de Operaciones].
12
Vista (Presentacin)
Controlador
Esta estrategia da lugar a una separacin entre presentacin y contenido, producindose una clara
definicin de los roles y responsabilidades de los desarrolladores y diseadores de pginas, en los equipos
de programacin. De hecho, cuanto ms compleja sea la aplicacin, mayores son los beneficios de utilizar
la arquitectura de Modelo 2.
El proyecto Struts de la Apache Software Foundation es una implementacin del MVC Modelo 2.
El ncleo del framework Struts es una capa de control flexible basada en tecnologas estndar 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 tecnologas
para proporcionar el Modelo y la Vista. Para el Modelo, Struts puede interactuar con tecnologas de acceso
a datos estndar, como JDBC y EJB, as como con la mayora 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 presentacin. Actualmente, el framework
del Principado de Asturias slo da soporte a JDBC y JSP.
La figura siguiente muestra como es el ciclo peticin-accion-jsp del framework Struts:
Para obtener informacin ms detallada sobre Struts consultar el tutorial que se adjunta en la
documentacin de openFWPA.
13
Desarrollo de la Vista
Aspecto corporativo de las aplicaciones del Principado
de Asturias
Las aplicaciones construidas bajo los estndares del openFWPA de desarrollo J2EE se integrarn 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 construccin 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 (posicin, color, tamao, etc) del cdigo HTML generado por la aplicacin. 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.
14
position.css
princast-ui.css
hoja de estilos para el estilo de los componentes de las etiquetas de princast para
las pginas
tabs.css
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
Estos ficheros CSS definen los estilos para aplicaciones de tramitacin. Adems 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.
Segn lo expuesto, el cdigo de las pginas JSP debe reducirse al mnimo imprescindible, obteniendo as
un cdigo mucho ms claro y mantenible.
Ejemplo: cdigo JSP del cuerpo de una pgina de la aplicacin 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
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 cdigo anterior responde a la forma en que se construye un cuerpo de pgina. No se ha utilizado en
ningn caso directrices de estilo o posicionamiento dentro de este cdigo, y en esta forma resulta ms
claro, donde se atiende nicamente a lo que debe mostrar la pgina y no a como y dnde debe mostrarlo.
16
Atencin
Para poder realizar este tipo de mapeos es necesario utilizar como controlador (Controller)
la clase PrincastRequestProcessor:
<controller processorClass="es.princast.framework.web.action.PrincastRequestProc
Jerarqua de Actions
En el openFWPA se proporciona un conjunto de Actions de Struts. Estas Actions definen un nuevo
ciclo de ejecucin diferente del existente en las Actions tpicas de Struts (ver ms adelante). Las
aplicaciones que utilicen el openFWPA deben, obligatoriamente extender las Actions del Framework.
Adems de ser una imposicin, las Actions del openFWPA ofrecen funcionalidad de uso habitual en
las aplicaciones web.
PrincastAction
La clase base de la jerarqua es PrincastAction. Es una clase abstracta que implementa una mquina
de estados de la que podrn hacer uso el resto de Actions. Define mtodos que deben ser sobrescritos
por las actions de la aplicacin. Estos mtodos sobrescritos sern 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 mquina de estados:
17
Cada uno de los mtodos que aparecen en la figura anterior tiene un cometido en particular. Este cometido
es el siguiente:
preProcess ()
executeActionLogic ()
catchException()
18
findFailure()
findAlert()
findSuccess()
Atencin
El mtodo saveErrors(HttpServletRequest, List) est deprecado a partir de la
versin 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 mtodo deprecado,
las Actions pueden no funcionar correctamente.
A continuacin se muestra un ejemplo de creacin 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 aadirn 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 parmetro. En caso de que el mensaje lleve parmetros de la forma {0},{1},{2},{3},
un posible mensaje sera:
error.general=Ha ocurrido un error de tipo {0} a las {1} horas en {2} con usuario {
En este caso, la creacin del error sera como sigue:
java.util.List error = new java.util.ArrayList();
error.add(error.general);
19
Ha ocurrido un error de tipo GRAVE a las 15:30 horas en Gestin de usuarios con usu
findFailure()
findAlert()
20
}
}
En la Action del ejemplo: MyAction, se han sobrescrito dos mtodos del ciclo de vida de la Action:
preProcess() y executeActionLogic(). En el mtodo preProcess(), se establece el valor
de un parmetro: myParam, asignndole la cadena foo. Por otro lado, en el constructor, se establece
un valor para el parmetro oneParam. En el mtodo executeActionLogic(), se recuperan los
valores de ambos parmetros. Recurdese que nicamente los mtodos del ciclo de vida de la ejecucin de
la Action tienen visibilidad del almacn. Por este motivo, en el mtodo executeActionLogic(),
la variable param1 tomar el valor foo, mientras que la variable param2 tendr como valor null.
21
Implementaciones concretas
Existen varias clases que tienen una funcionalidad determinada y que pueden ser reutilizadas tal y como
estn. Estas son:
PrincastExistAttributeAction
PrincastRemoveAttributeAction
22
23
24
En ocasiones, es necesario que una DispatchAction tenga mayor control sobre las redirecciones
(forwards) que debe realizar para cada uno de los mtodos de dispatch. Al igual que ocurre con
otros mtodos de la Action (executeActionLogic(), catchException(), etc.) es posible
redefinir los mtodos de redireccin (findSuccess(), findAlert() y findFailure()). El
sistema es exactamente el mismo: prefijar cada mtodo 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 botn (submit). Es este escenario, el botn que se utilice para
el envo del formulario (submit) ser quien determine el mtodo que se ejecutar en la Action.
25
26
Este mtodo debe precargar los campos necesarios para mostrar el formulario de creacin
de una nueva entidad.
retrieve
list
delete
update
create
Atencin
Para poder utilizar correctamente este tipo de Actions es necesario mapearlas dos veces en
el fichero struts-config.xml. Uno de los mapeos tendr la validacin de formularios
desactivada (validate = true) y se utilziar para solicitar los mtodos que no requieren un
formulario: new, retrieve, list y delete. El otro mapeo tendr la validacin activada y
se utilizar para los mtodos que s requieren formulario: update y create.
<action path="/productosAction"
type="productosActionBean"
input="facturas.listaProductos"
validate="false"
scope="request"
name="productoForm">
<forward name="list" path="facturas.listaProductos"/>
<forward name="retrieve" path="facturas.listaProductos"/>
<forward name="new" path="facturas.listaProductos"/>
<forward name="delete" path="facturas.listaProductos"/>
</action>
<action path="/productosFormAction"
type="productosActionBean"
input="facturas.listaProductos"
validate="true"
scope="request"
name="productoForm">
<forward name="create" path="facturas.listaProductos"/>
<forward name="update" path="facturas.listaProductos"/>
</action>
Estas Action tambin soportan, adems, paginacin sin necesidad de reejecutar la lgica de negocio
(Ver Paginacin sin reejecucin de la lgica de negocio.). Basta con incluir en la request el parmetro
27
PrincastListAction
Si una Action tiene nicamente como propsito obtener un listado, se puede utilizar la
PrincastListAction. No hace falta sobrescribir ningn mtodo del ciclo de vida de esta Action,
basta con implementar el mtodo getContentList() y devolver el objeto (o coleccin de objetos)
que sern mostrados. El objeto devuelto quedar registrado en sesin, bajo la clave que se especifique en
el atributo parameter, en el mapeo de ese action, en el fichero struts-config.xml.
28
Action Forms
El openFWPA dispone de una clase base para el desarrollo de los beans de formulario. Se trata de la clase
PrincastActionForm. Entre las propiedades destacables de esta clase se encuentran:
mutable
Para evitar que una PrincastActionForm sea rellenada de forma automtica al hacer
un forward entre diferentes acciones, establezca el valor de mutable a true y asegrese
de que todos los setters comprueban el valor de dicha propiedad (if (isMutable())
this.field = field;).
locale
29
getSessionLocale()
setMutable(boolean)
isMutable()
reset(ActionMapping,
HttpServletRequest)
resetSessionLocale(HttpServletRequest)
Cambia el atributo locale al valor que tenga el objeto locale
almacenado en la sesin e la peticin en curso bajo la clave
Globals.LOCALE_KEY.
putSessionLocale(HttpServletRequest)
Cambia el atributo Globals.LOCALE_KEY de la sesin por el
atributo locale o por el Locale por defecto si el atributo locale
es null.
getLocaleDisplay()
setLocaleDisplay(String)
isBlank(String)
describe()
Devuelve
un
Map
con
las
propiedades
de
esta
PrincastActionForm.
Se
usa
el
mtodo
PropertyUtils.describe(). Sobrescriba el mtodo si
considera que alguna propiedad no debera ser mostrada de este
modo, o si un nombre de una propiedad debera ser cambiado. Este
mtodo devuelve las propiedades pblicas.
set(PrincastValueObject)
populate(PrincastValueObject)
Permite cargar los datos del formulario sobre un Value Object. Este
mtodo recibe como parmetro el Value Object sobre el que se van
a cargar los datos. Devuelve una referencia al objeto que contiene
todos los datos del formulario.
Para la definicin de ActionForms dinmicos, se incluye en el openFWPA una clase base:
PrincastDynaActionForm. Se incluye adems una clase base para los formularios que van a
ser utilizados por dispatch actions: PrincastDispatchActionForm. Este tipo de formularios
incluyen un campo (method) para seleccionar el mtodo de dispatch que se ejecutar para
procesarlo. Las clases para la implementacin de formularios se encuentran en el paquete:
es.princast.framework.web.form.
La clase LookupDispatchForm permite disponer de formularios con ms de un botn de
submit. Para obtener ms informacin acerca de este tipo de forms, vase el apartado
PrincastLookupDispatchAction en la seccin dedicada a las Actions.
30
Utilizando esta estructura, se puede modificar la implementacin del servicio sin que sea necesario
modificar el resto de la aplicacin. Un ejemplo de implementacin puede verse en la aplicacin de ejemplo
(Sample App). En ningn caso la lgica de negocio ha de tener dependencias con el protocolo http (como
por ejemplo hacer uso de la sesin), ya que sus servicios han de poder reutilizarse desde cualquier otro
entorno (como Web Services, JMS, etc.). Las nicas dependencias al protocolo concreto de acceso han de
estar en las acciones (View Adapters y Actions).
Service Locator
El patrn de diseo Service Locator permite encapsular, en una clase, la localizacin y acceso a objetos de
servidor. El openFWPA incluye un componente que implementa este patrn: la clase ServiceLocator.
El ServiceLocator proporciona los siguientes mtodos para la bsqueda de objetos:
getDataSource()
getLocalHome()
getRemotelHome()
getQueue()
getQueueConnectionFactory()
Obtiene una factory de conexiones a colas de mensajes JMS.
getTopic()
getTopicConnectionFactory()
Obtiene una factory de conexiones a Topics JMS
Session EJBs
Habitualmente, es necesario, cuando se trabaja con Session EJBs, gestionar, para cada uno de ellos,
de forma especfica el mantenimiento del contexto de la sesin (SessionContext). Para evitar la
obligacin de implementar los mtodos de mantenimiento de la sesin, se ha incluido en el openFWPA,
una clase base para los Session EJBs: PrincastSessionEJBTemplate. Esta clase implementa los
mtodos setSessionContext() y unsetSessionContext(), dejando la instancia del contexto
en la variable protegida context.
Value Objects
Los objetos de datos (Patrn Value Object), en las aplicaciones desarrolladas sobre el openFWPA, deben
implementar el interfaz PrincastValueObject.
31
Esta interfaz define el mtodo toXML() que permite ver una descripcin del objeto en formato XML.
Para facilitar la implementacin de Value Objects, se han includo dos clases base: BasePrincastVO,
que realiza una implementacin por defecto para el mtodo toXML() basada en reflectividad, y
BasePrincastLazyLoadingVO, que debe ser utilizada si los Value Objects de la aplicacin se van
a usar en conjuncin con Lazy loading de los Value Objects.
Ambas clases extienden la clase AbstractBasePrincastVO, que define otro mtodo de utilidad:
toPropertyBeans().
En la clase BasePrincastVO, este mtodo permite "desmenuzar" un VO, mapendolo a una lista
de objetos de tipo PropertyBean. El nombre de la propiedad se asignar al campo "value" del
PropertyBean. El valor se asignar al campo "label".
Si alguna de las propiedades del VO es un objeto compuesto (una lista, una tabla, un array u otro VO)
estos sern, a su vez, descompuestos. Se seguir el siguiente convenio de nombrado para las propiedades:
Propiedades de tipo VO
(PrincastValueObject)
Excepciones
El openFWPA dispone de su propia jerarqua de excepciones. La poltica general de manejo de excepciones
en el openFWPA es que se utilicen excepciones Runtime (no manejadas estticamente).
La clase base para la creacin de excepciones es PrincastException. Existen dos ramas en esta
jerarqua de excepciones runtime: excepciones de sistema (PrincastSystemException), reservadas
para el openFWPA y sus componentes y excepciones de modelo (PrincastModelException), que
son disparadas por las excepciones.
32
Utilidades
Junto con las excepciones, se incluye una clase (ToXMLExceptionHelper) auxiliar para facilitar el
fromateo de las mismas y su traduccin a XML.
PrincastMessageFmtter
Clase para facilitar el formateo de cadenas de caracteres (mensajes, etc). Esta clase permite:
Reemplazar tokens en un String. Mtodo replace().
Formatear un mensaje, siendo ste una cadena con parmetros del tipo {0}, {1}, {n}. Este
mtodo (format()) recibir como parmetros una cadena de texto y un array de objetos. El objeto en
la posicin 0 se introducir en lugar de la subcadena {0} y as sucesivamente.
PrincastUtils
Contiene mtodos de utilidad general. Actualmente nicamente implementa el mtodo
normalizePath() que tiene como objetivo normalizar los paths en los distintos sistemas operativos.
ParameterCaster
Clase de utilidad para la capa web. Permite traducir el tipo (casting) de los parmetros que se reciben de
una request http.
ServletPathUtils
Clase de utilidad del paquete web que permite gestionar paths de peticiones http. Los mtodos que define
son:
match()
extractRelativePath()
getCompleteURL()
getURLParametersSeparator()
A partir de una URL, determina si los parmetros que se vayan
a aadir a continuacin se preceden de un carcter ? &,
33
DateDecorator
Clase que facilita la escritura de fechas y horas con un formato determinado. Esta clase implementa
el patrn Decorator sobre la clase java.util.Date, sobrescribiendo su mtodo toString().
La clase es.princast.framework.core.util.DateDecorator permite definir el patrn
de formato que se aplicar al obtener la representacin textual de la fecha utilizando el mtodo
Date.toString().
Adems, tambin define los patrones para los formatos de fecha ms comunes:
/**
* Formato corto para las fechas tomando como separador el caracter /.
*/
public static final String SHORT_DATE = "dd/MM/yyyy";
/**
* Formato corto para las fechas tomando como separador el caracter -.
*/
public static final String SHORT_DATE_DASH = "dd-MM-yyyy";
/**
* Formato para mostrar slo horas, minutos y segundos. Las horas varan en
* el rango 0..24.
*/
public static final String ONLY_TIME = "HH:mm:ss";
/**
* Formato largo para la fecha, tomando como caracteres de separacin el
* caracter / para da, mes, ao y el caracter : para horas, minutos y
* segundos.
*/
public static final String LONG_DATE = "dd/MM/yyyy HH:mm:ss";
/**
* Formato largo para la fecha, tomando como caracteres de separacin el
* caracter - para da, mes, ao y el caracter : para horas, minutos y
* segundos.
*/
public static final String LONG_DATE_DASH = "dd-MM-yyyy HH:mm:ss";
PrincastPathResolver
El objetivo del PrincastPathResolver es ofrecer, al programador de aplicaciones, un punto
centralizado para resolver paths (a recursos) uniformemente.
Este objeto (que implementa el patrn Singleton) define los siguientes mtodos:
resolvePath(path)
resolveToFile(path)
34
WebAppPathResolver
PrincastOSCacheInterceptor
Esta clase permite a travs de Spring y OSCache, realizar cacheos transparentes de las llamadas a cualquier
mtodo de cualquier bean de Spring. Esto es til, por ejemplo para cachear las llamadas al sistema de
Genricos del Gobierno del Principado de Asturias.
El uso de esta clase est documentado en la Javadoc. La funcionalidad por defecto establece una cach
por mtodo cacheado, donde la clave para buscar en la cache es la concatenacin del toString, de los
argumentos. Si dos llamadas al mismo mtodo tienen el mismo toString concatenado de los argumentos
se devuelve el resultado cacheado. Este comportamiento se puede sobreescribir heredando de la clase.
El tiempo de refresco se establece en la definicin de bean, por defecto son 600 segundos se recomienda
ver la Javadoc, para ver la sintxis de los tiempos de refresco en funcin del mtodo.
Providers
Para aislar la capa de acceso a datos de otras capas de la aplicacin, habitualmente es buena idea definir
interfaces providers. Estos interfaces proporcionan datos a la capa del controlador, o directamente a la
vista, sin indicar donde ni cmo se obtienen esos datos. El controlador (o la vista) pueden manipular los
providers directamente sin preocuparse de cmo stos se han obtenido.
Desde la versin 1.5 del openFWPA, los providers
es.princast.framework.facilities.providers.
se
encuentran
en
el
paquete:
ListContentProvider
PaginatedContentProvider
35
XMLProvider
PropertyBeansProvider
Para conocer con mayor detalle el interfaz de cada uno de los providers, consltese la documentacin
Javadoc del openFWPA.
36
Captulo 3. Implementacin de la
Arquitectura de Referencia con
openFWPA
Inversin de Control en la Arquitectura de
Referencia
A partir de la versin 1.5 de openFWPA, se hace un uso intensivo de la inversin de control (IoC), para
implementar la arquitectura de referencia, en las aplicaciones realizadas con el openFWPA.
Para ello, se hace uso de Spring Framework, que ofrece la implementacin del patrn
AbstractFactory basado en ficheros XML. Esto permite, eliminar los elementos de unin en las
aplicaciones, como las factoras, y singletons. Adems, permite tener la arquitectura modularizada en
"piezas", que por estar definidas en un fichero XML, son intercambiables. Lo que deriva, en un sistema
dbilmente acoplado, ms tolerable a cambios y modificaciones.
Los ficheros siguen la sintaxis de definicin de beans de Spring, al igual que el fichero de inicializacin
de openFWPA (princast-init-script.xml).
Para hacer uso de la inversin de control, es necesario seguir una serie de pasos. Como ejemplo, se va a ver
cmo se construye una clase Action dependiente de una clase Delegate desde cero. El proceso de inyectar
la dependencia se ha denominado "enlazado", tomndolo como traduccin libre del trmino "wiring",
utilizado en el manual de referencia de Spring.
La primera tarea que hay que hacer, es implementar el Action. Como se tiene una dependencia, con un
Manager, se introduce un campo o propiedad (privado o protegido), en la clase Action. Adems, se define
un setter para ese campo, de esta forma se puede inyectar esa dependencia.
A la hora de usar el objeto Delegate se utiliza normalmente, aunque parezca que al usarlo apunta a un valor
nulo, el motor de inversin de control se encarga de inicializarlo.
public class GetListaProductoAction extends PrincastListAction {
// inyeccion de dependencia (/beans/web/action-beans.xml)
protected CarritoDelegate carritoDelegate;
37
Implementacin de la Arquitectura
de Referencia con openFWPA
public void setCarritoDelegate(CarritoDelegate carritoDelegate) {
this.carritoDelegate = carritoDelegate;
}
Para inyectar la dependencia se realiza mediante el elemento property, donde se establece un atributo
name, que coincide con el nombre asociado al setter, que se ha definido en la clase que se implement
anteriormente.
En el contenido del elemento property, se hace referencia mediante ref al identificador (id) de otro
bean. Este bean puede estar definido, en ese mismo fichero o en cualquiera de la estructura comentada
anteriormente. En este caso, la definicin es de un Delegate, por lo que estar definido en el fichero
delegate-beans.xml.
Estableciendo el Datasource
La inversin de control, comienza desde la primera dependencia que se tiene. En este caso el datasource,
para ello se define en el fichero datasource-beans.xml, un bean que representa un datasource JNDI,
a continuacin se muestra un ejemplo de definicin del mismo:
38
Implementacin de la Arquitectura
de Referencia con openFWPA
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc/MySQLDS</value>
</property>
</bean>
En el caso de la aplicacin en blanco, para que una aplicacin pueda desplegar sin necesidad de datasource,
se ha definido un datasource nulo. Este datasource, sirve para poder enlazar las dependencias sin la
necesidad de un datasource real. En el momento que se disponga de uno real, es recomendable cambiarlo
por el datasource JNDI.
Para realizar las pruebas unitarias, es necesario disponer de un datasource para realizar los test. En la
aplicacin de ejemplo, se suministra un test sobre una clase DAO, que utiliza un datasource para test. Un
ejemplo de definicin de datasource de test, es el siguiente:
Para ms informacin sobre la realizacin de pruebas sobre los DAOs, ver Pruebas unitarias de objetos
que acceden a bases de datos.
39
Implementacin de la Arquitectura
de Referencia con openFWPA
Se recuerda que para que se produzca la inyeccin de la dependencia, la clase que implementa el DAO,
debe disponer de un setter para el campo dependiente, como se observa en el siguiente ejemplo:
En el caso de estar sujeto a transacciones, la definicin del bean es un poco ms complicada, ya debe
heredar de una plantilla para transacciones. Esto se realiza mediante el atributo parent, donde se le
especifica el nombre de la plantilla, que estar definida en el fichero transaction-beans.xml.
La definicin propiamente dicha de la clase Manager, se realiza dentro de la propiedad target, y se le
inyecta las dependencias normalmente. A continuacin, se muestra la definicin de un Manager sujeto a
manejo de transacciones.
40
Implementacin de la Arquitectura
de Referencia con openFWPA
Como en los casos anteriores, la dependencia se establece por medio de la definicin de un setter, para
cada campo dependiente.
Gestin de transacciones
Desde el fichero transaction-bean.xml se controla la gestin de transacciones. Esta gestin se
realiza de forma declarativa, por lo que los Managers que hereden de estas plantillas de transacciones, no
tendrn que implementar cdigo para la gestin de transacciones, ni conexiones.
Antes de la definicin de la plantilla se establece un transactionManager sobre el datasource a
utilizar. Un ejemplo de definicin es el siguiente:
Una vez declarado el transactionManager, se define una plantilla para el manejo de transacciones.
De esta plantilla se debe de heredar, en la definicin de beans, los Manager que esten sujetos a transacciones
(mediante el atributo parent, visto en el apartado anterior). Se podran definir varias plantillas, en funcin
de las necesidades. Un ejemplo de plantilla para la gestin de transacciones es el siguiente:
41
Implementacin de la Arquitectura
de Referencia con openFWPA
El comportamiento por defecto, para la poltica de rollback, define que si se produce una excepcin de
tipo Runtime durante la ejecucin del mtodo, se har un rollback.
Algunas de las propiedades que se pueden establecer son:
PROPAGATION_LEVEL: Nivel de propagacin. Por defecto se establece el nivel de propagacin a
PROPAGATION_REQUIRED, esto significa que crear una nueva transaccin, slo si se necesita.
ISOLATION_LEVEL: Nivel de aislamiento. Por defecto trendr el valor ISOLATION_DEFAULT.
readOnly: Optimizacin de slo lectura. Se optimiza la transaccin para las operaciones de slo
lectura.
Lista de Excepciones: Establece la poltica de rollback o commit, al margen del comportamiento por
defecto. Por ejemplo, si se le aade la cadena '-MiExcepcion', se hara rollback en caso de que
dispare la excepcin de nombre 'MiExcepcion', aunque el tipo de excepcin no sea Runtime. Si se
aade la cadena '+OtraExcepcion', se har commit aunque la excepcin sea Runtime.
Para ms informacin sobre las propiedades disponibles consultar el manual de referencia de Spring.
Se recuerda que la clase CarritoDelegate debe disponer de un setter para cada dependencia.
42
Implementacin de la Arquitectura
de Referencia con openFWPA
Una vez definidos los beans para las Actions deben ser referenciados desde el fichero strutsconfig.xml, la referencia se har mediante el atributo type. Hasta ahora, ese atributo referenciaba el
nombre cualificado de una clase, a partir de la versin 1.5, se buscar primero por id de bean definido
en el fichero action-beans.xml, si no encuentra ningn bean definido, tomar el nombre como el de
una clase, tal y como se haca en versiones anteriores.
Un ejemplo de un Action referenciando a una definicin de bean en struts-config.xml, es el
siguiente:
Se observa que el atributo type tiene el valor type="viewdetalleproducto" que coincide con
el id del bean definido en action-beans.xml.
Atencin
En aplicaciones Struts, nicamente se puede acceder, por este mtodo, a los beans cargados por
el mdulo por defecto (mdulo sin prefijo).
43
Implementacin de la Arquitectura
de Referencia con openFWPA
Este plugin, permite ver de una forma visual la definicin de beans, adems incluye caratersticas como el
autocompletado de clases y el acceso directo desde el grfico de visualizacin, a la definicin del bean o
de la clase. Para su instalacin y primeros pasos, se debe acudir a la pgina del proyecto SpringIDE.
44
El patrn DAO
Para realizar el acceso a datos se utilizar el patrn DAO (Data Access Object). El openFWPA dispone de
una interface base PrincastDAO que deben de implementar todos los DAOs, o extender de una clase que
la implemente. Esta interfaz posee dos mtodos, getDataSource y setDataSource que permiten
obtener y establecer, el DataSource que utliza el DAO, para acceder a Base de Datos.
El framework tambin dispone de una clase de utilidad para facilitar la implementacin de objetos DAO: la
clase PrincastDAOHelper. Un objeto PrincastDAOHelper siempre debe estar asociado con un
objeto DAO (que se llamar OwnerDAO). Solamente los OwnerDAOs de un HelperDAO podrn acceder a
sus mtodos. Es altamente recomendable, que para mejorar el rendimiento general de la aplicacin, todos
los DAO de una misma clase puedan acceder al mismo DAOHelper a travs de una variable static.
La caracterstica ms interesante que proporcionan los DAOHelpers es la capacidad de cargar consultas
SQL desde un fichero .properties. Este fichero debe cumplir las normas de ficheros properties Java.
Cada propiedad del fichero se corresponder con una consulta SQL identificada por una etiqueta.
Las consultas SQL del fichero de properties pueden tener parmetros, utilizndose para ello el carcter
? de forma anloga a los PreparedStatement.
Los mtodos pblicos de esta clase DAOHelper son:
PrincastDAOHelper(Class)
getQueries()
getQuery(String)
getStament(String,
Object [])
executeQuery(String,
Object[], Object[],
DataSource)
45
reload()
Desde la versin 1.5 del framework, se ha introducido la posibilidad de mapear los ResultSet a clases de
negocio, generalmente VOs. Para ello se necesita crear una clase que herede de PrincastRowMapper,
e implemente el mtodo mapRow. Desde una clase DAOHelper se podr, usar y reutilizar estos
mapas, mediante llamadas al mtodo executeQueryForList que acepta como parmetro un
PrincastRowMapper. Un ejemplo de mapeo se puede observar en la clase ProductosMapper, en
la aplicacin Sample App.
public class ProductosMapper extends PrincastRowMapper{
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
ProductoVO producto = new ProductoVO();
producto.setId(rs.getInt("id"));
producto.setName(rs.getString("nombre"));
producto.setDescription(rs.getString("descripcion"));
producto.setSmallImageURL(rs.getString("smallImageURL"));
producto.setBasePrice(rs.getDouble("basePrice"));
return producto;
}
}
La aplicacin en blanco (App Blank) dispone de plantillas para la realizacin de DAOs (concretamente en
la clase DAOTemplate), y la aplicacin de ejemplo ( Sample App) dispone de un ejemplo de utilizacin
en la clase MySQLCarritoDAO.
public class MySQLCarritoDAO implements CarritoDAO, PrincastDAO {
...
protected static PrincastDAOHelper helper = new PrincastDAOHelper(
MySQLCarritoDAO.class);
...
46
/**
* Devuelve una List con todos los productos que maneja la aplicacin.
*/
public List getListaProducto() {
List listaProducto;
<!-- Con estas dos definiciones se auditan todas las expcepciones que
se produzcan en los DAOs a nivel de log de ERROR-->
<bean id="loggerThrowsAdvice" class="es.princast.framework.facilities.interceptor.
<property name="level"><value>ERROR</value></property>
</bean>
Listas clave/valor
Existe un tipo especial de DAO que permite acceder y manipular a informacin estructurada como listas
de pares clave/valor sobre una tabla de una base de datos. Se trata de la clase PropertiesTableDAO.
El principal uso de este tipo de objetos DAO es facilitar el acceso a listas de valores que puedan ser
utilizadas para cargar componentes de interfaz de usuario como inputs HTML de tipo select.
47
Esta clase devuelve objetos (o listas de objetos) del tipo PropertyBean, que tiene dos campos value
y label correspondientes a la clave y su valor asociado respectivamente.
Los mtodos pblicos de esta clase son:
PropertiesTableDAO(DataSource,
Constructor. Recibe un DataSource, el nombre de la tabla,
String, String, String)
nombre de la columna donde se almacenan las claves y nombre de
la columna que tiene los valores.
getAllProperties()
getProperties(String)
findProperty(String)
insertProperty(String,
String)
updateProperty(String,
String)
deleteAllProperties()
deleteProperty(String)
getReportIterator(Object[])
Devuelve un Iterator con todos los pares de la tabla. Si el array que
se le pasa esta vaco o es nulo devolver todos los valores de la
tabla. Sin embargo, si contiene valores se buscarn todos los pares
cuya clave est en el array
Puede verse un ejemplo de utilizacin en la clase MySQLFormaPagoDAO, de la aplicacin de ejemplo
(Sample App).
public class MySQLFormaPagoDAO implements FormaPagoDAO, PrincastDAO {
...
protected static List formasPago = null;
public MySQLFormaPagoDAO() {}
/**
* Devuelve una List con las formas de pago existentes
*/
public List getFormaPago() {
// se mantiene en memoria las formas de pago en una variable static
if (formasPago==null){
PropertiesTableDAO propsTable = new PropertiesTableDAO(dataSource,
"formapago", "id","descripcion");
formasPago = propsTable.getAllProperties();
}
return formasPago;
}
...
}
48
Otra forma de crear listas de beans con pares atributo/valor (PropertyBean) es a partir de
un Map. La propia clase PropertyBean dispone de un factory method esttico que, recibiendo como
parmetro una referencia a un objeto Map, crea una lista de pares atributo / valor (PropertyBeans).
public static List populateList(Map props)
LookupPropertyBean
Una situacin habitual es aquella en la que se necesita navegar una relacin entre entidades. En esta
situacin, se dispone de una clave y se necesita obtener el valor de dicha clave.
En ocasiones, los datos sobre los que hay que hacer " lookup ", no estn almacenados en una base de
datos. Estos datos pueden estar en memoria, en un Map o en una lista de PropertyBeans . Para poder
manejar todas estas situaciones, el componente LookupPropertyBean , dispone de los siguientes
constructores:
LookupPropertyBean(DataSource
Constructor estndar para este tipo de objetos. Asocia el lookup
dataSource, String
bean con una base de datos. Como parmetros debe recibir: el
tableName, String
dataSource de la base de datos, la tabla en la que se almacenan los
keyColumn, String
datos de la relacin, el nombre de la columna de las claves y el
valueColumn)
nombre de la columna de los valores.
LookupPropertyBean(Map
props)
LookupPropertyBean(List
beans)
Providers
A partir de la versin 1.5 del openFWPA, los providers estn ubicados en el
paquete: es.princast.framework.facilities.providers. Los providers del paquete
es.princast.framework.dao.providersestn deprecados. Ver Providers.
Generadores de Secuencia
Otra utilidad incluida en el openFWPA son los generadores de secuencia. Este tipo de objetos permiten
generar secuencias de nmeros consecutivos. Su utilidad ms habitual es la generacin de claves primarias.
49
Pools de conexiones
La configuracin de Pools de conexiones en el contenedor oc4jse realiza en el fichero
datasources.xml. El propio fichero trae un ejemplo de configuracin para base de datos Oracle, y en la
aplicacin de ejemplo (Sample App) se puede encontrar la definicin de un DataSource para el servidor
MySQL.[17]
<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"/>
</data-sources>
Para opciones avanzadas de configuracin (nmero mnimo y mximo de conexiones del Pool, nmero
mximo de intentos de conexin, etc.) consultar el DTD de dicho fichero, disponible en la direccin
http://xmlns.oracle.com/ias/dtds/data-sources.dtd.
50
La herramienta iReports
La herramienta iReports es un editor visual de ficheros XML listos para ser usados por el motor de
reporting JasperReports. Trabaja en modo standalone (aplicacin de ventana de java) y tiene un interfaz
claro. En la pgina del proyecto http://ireport.sourceforge.net puede obtenerse una amplia
documentacin sobre como manejar esta herramienta, e incluso un video tutorial que muestra algunos de
los aspectos ms interesantes sobre ella.
51
Construccion de
informes con openFWPA
Al estar estrechamente relacionada con JasperReports, es necesario conocer los aspectos en que
este ltimo organiza su informacin (bandas, grupos, subreports, parameters, fields, variables)
para optimizar el manejo de la herramienta visual. Una vez descargado el proyecto y ejecutado, se
abrir una ventana como la de la siguiente figura, donde se ha abierto un fichero XML llamado
solicitudQuemaEnBlanco.xml.
No es objeto de este manual mostrar el manejo detallado de iReports. No obstante, se introducen algunos
conceptos sobre la herramienta. Una vez se tiene un diseo cargado, o bien se ha optado por un diseo
nuevo a partir de cero al cual se le van aadiendo elementos, se puede compilar el diseo, tal y como la
hara JasperReports a travs de su motor. Con esto se asegura que el diseo que se est generando es vlido
y no producir errores de compilacin en el momento de que la aplicacin a desarrollar tome el fichero
XML para compilarlo y mostrarlo en pantalla. Para esto se dispone del icono Compliar (1) a la derecha
en la barra del men. Tambin es posible observar como se vera el documento que se est diseando
con alguno de los visores predeterminados, previa configuracin de los programas externos que maneja la
herramienta, de dos modos distintos: con una fuente de datos vaca o con la fuente de datos actual (previa
configuracin de las fuentes de datos).
52
Construccion de
informes con openFWPA
Report Wizard
Men # Report Wizard Esta opcin permite la creacin de nuevos diseos a partir del wizard de iReports.
El proceso consta de una serie de pasos que se detallan a continuacin:
1. Introducir la consulta que obtendr los datos de la fuente de datos.
4. Elegir una plantilla para el layout. iReports viene con una serie de plantillas que se pueden utilizar, o
bien el desarrollador podra construir sus propias plantillas.
Con esto finaliza el proceso, y se genera un informe en vista diseo como el siguiente:
En este ejemplo se ha utilizado una fuente de datos JDBC Connection. No se han realizado pruebas
para obtener datos de collecciones de Beans (fuente de datos JRDataSource) aunque el proceso no
debera diferir sustancialmente de lo aqu expuesto.
Report Parameters
Men # View # Report Parameters Los parmetros son una buena forma de aadir datos dinmicos al
informe y parametrizar ste, de forma que se puedan visualizar elementos segn el valor o rango de algn
parmetro, e incluso modificar la consulta SQL segn parmetros. Los parmetros aaden ms flexibilidad
a la generacin de los informes, hasta el punto de que es posible crear informes sin fuente de datos, y que
toda su informacin llegue por parmetros.
Un parmetro tiene un nombre, un tipo (clase java seleccionable de una lista) y opcionalmente un valor
por defecto (expresin java que ser compilada en el proceso de compilacin y evaluada en el proceso
de completado del informe) Los parmetros son referencias a objetos que son pasadas al proceso de
completado (fill) del informe. Su uso, como ya se ha comentado, servir para enviar informacin al
motor de reporting que no puede ser encontrada en la fuente de datos (DataSource)
Los parmetros se identifican en el fichero XML por construcciones similares a la siguiente:
<parameter name="ejemplar_para" isForPrompting="false" class="java.lang.String">
53
Construccion de
informes con openFWPA
<defaultValueExpression >
<![CDATA[new String("Ejemplar para ... por defecto")]]>
</defaultValueExpression>
</parameter>
En el entorno de iReports, se puede hacer referencia a este parmetro mediante la construccin
$P{ejemplar_para}
Consultas parametrizadas
Men # View # Report quey Es posible parametrizar la consulta que lanzar el informe segn el valor de
uno o varios parmetros en tiempo de ejecu-cin. Para hacer referencia a un parmetro definido se utiliza
la construccin $P{nombre_de_parametro} y estas construcciones se pueden insertar en las propia
consulta, de forma que sean evaluadas durante el proceso de completado. Un ejemplo puede verse en la
siguiente imagen, donde se observa la intrusin de los parmetros fecha_inicio y fecha_fin
como parte de la sentencia SQL. El objetivo de esta consulta es filtrar la bsqueda entre dos fechas, que
posi-blemente el usuario introduzca en algn formulario de la vista de su aplicacin. Una forma de hacer
llegar dinmicamente estos valores a la consulta es utilizando parmetros de informe, cuyos valores sern
asignados por programacin en tiempo de ejecucin y pasados como informacin adicional al proceso de
completado del informe.
Fields
Los fields representan la forma de mapear campos en el diseo del report con datos de la fuente de datos.
Si el DataSource es una base de datos, entonces el mapeo es directo con los nombres de campos en
una o varias tablas. Si el DataSource es una colleccin de Beans, el mapeo se realizar con las property
s de stos.
Un Field se puede idetificar en el XML por una construccin como: <field name="DL_FINALIDAD"
class="java.lang.String"/> En el entorno de iReports se le puede hace referencia como
$F{DL_FINALIDAD}
Variables
Se declaran como expresiones en java, y ms tarde pueden ser usadas de forma masiva. Pueden servir
como forma de no repetir cdigo. Tamben se utilizan para realizar clculos. Exiten funciones builtin que facilitian algunas tareas de clculo, como Count, Sum, Average, Lowest, Highest y
StandardDeviation. Las variables sern reinicializadas segn la jerarqua de niveles: Report,
Page, Column y Group.
Exiten una serie de variables inherentes a todo informe (built-in variables), a las que se puede hacer
referencia en todo momento.
PAGE_NUMBER
REPORT_COUNT
COLUMN_COUNT
En el entorno de iReports se les puede hace referencia como $V{NOMBRE_DE_VARIABLE}
54
Construccion de
informes con openFWPA
El diseo XML
Ya sea con la herramienta iReports o con cualquier otra disponible, el objetivo ser obtener un fichero
XML que se considerar el diseo del documento. Este fichero ser pasado al proceso de compilacin,
completado y visualizacin de las aplicaciones construidas bajo el framework, en la forma que se ver
ms adelante.
El cdigo XML generado es extenso y pesado de tratar con herramientas de edicin de texto o editores
XML. Es por esto la necesidad del uso de herramientas como iReports para disear los informes de las
aplicaciones. A continuacin se pueden ver trozos de XML que generan las herramientas:
55
Construccion de
informes con openFWPA
56
Construccion de
informes con openFWPA
2. Utilizar como encoding UTF-8 en lugar de ISO-8859-1. El XML debera comenzar con la siguiente
lnea: <?xml version="1.0" encoding="UTF-8"?>
3. Eliminar todas las referencias al atributo pdfEncoding. Los elementos de texto son
generados por defecto con el atributo pdfEncoding=CP1252. Borrar todos los literales
pdfEncoding=XXXXXX del fichero XML.
4. Si se utilizan imgenes en los informes, modificar todas las rutas. La herramienta introduce rutas
absolutas para mapear las imgenes. Deber cambiar estas rutas a relativas de acuerdo a la estructura
de las aplicaciones que se estn desarrollando.
5. El creador de iReports ha introducido una opcin para que las expresiones puedan ser multilnea
(una facilidad para el diseador del informe) Esta posibilidad se controla en Men # Tools # Options
(Pestaa General) # CheckBox Using multi line expresions. Si est habilitada, en el XML aparecer el
atributo isCode en ciertos elementos. Este atributo no forma parte del DTD, por lo que no ser posible
parsear el XML convenientemente y mucho menos compilar el diseo por JasperReports. Eliminar el
atributo isCode del XML.Es posible que en futuras versiones de JasperReports el atributo isCode
forme parte del DTD, si fructifican las conversaciones a este respecto entre el creador de JasperReprots
y el de iReports.
6. Si no se va a utilizar una clase Scriptlet en el informe, no ser necesario que
esto conste en el diseo. Es posible que al generar un nuevo diseo con la herramienta
iReport se aada por defecto la clase dori.jasper.engine.JRDefaultScriptlet.
En la versin de jasperreports actualmente utilizada (0.6.0) esta clase no existe, con lo
que si se intenta compilar el informe ocurrir una excepcin ClassNotFoundException.
Para eliminar esta referencia se puede editar el XML y eliminar la siguiente lnea
scriptletClass="dori.jasper.engine.JRDefaultScriptlet del elemento raz
<jasperReport>. Tambin se puede hacer directamente con la herramienta iReport mediante
Project # ProjectOptions # Pestaa Scriptlety configurando aqu la clase que se desea utilizar, o
indicando que no se va a usar una clase Scriptlet.
En la versin 0.4 de la herramienta iReports, estos bugs estn resueltos, por lo tanto, no es necesario
realizar ninguna modificacin al fichero XML generado.
Compilacin de Reports
Para poder utilizar los reports generados con la herramienta iReports, en las aplicaciones que utilizan el
framework, es necesario que los ficheros XML obtenidos sean compilados al formato .jasper. Para ello,
se puede utilizar la clase JasperCompilerManager o, mejor an, el propio programa editor iReports.
Informes simples
Para crear un informe simple se usar la clase PrincastReport. Para poder crear un
PrincastReport, es necesario indicarle, en su constructor, los parmetros:
Nombre del informe
El informe debe tener un nombre. Este nombre puede ser el que se utilice
para generar un fichero PDF.
57
Construccion de
informes con openFWPA
Fuente de datos
El origen de datos para cargar el informe tambin debe ser especificado. Por
defecto, se utilizar el origen de datos nulo: JREmptyDataSource. El
informe no tomar datos de ninguna fuente.
Report compilado
Adems, si en el diseo del informe se han definido parmetros, sus valores deben ser especificados al
PrincastReport utilizando el mtodo setParams(Map).
Atencin
Antes de obtener el informe es MUY recomendable pregenerarlo (para validar que no se producen
errores antes de exportar el informe). Para pregenerar un informe se debe utilizar el mtodo
process().
Para obtener un informe de un PrincastReport (correctamente creado y con los parmetros que
necesite asignados) se puede utilizar uno de los siguientes mtodos:
a. getReportToPrint(). Devuelve el objeto jasper imprimible: JasperPrint. Este objeto puede
ser manejado por las clases de Jasper Reports (se puede exportar a mltiples formatos, imprimir, etc.)
b. getPDFContent(). Devuelve el informe exportado a formato PDF, en un array de bytes, listo para
ser volcado a un fichero (o enviado a un cliente, etc.)
c. exportPDF(OutputStream). Exporta el informe, en formato PDF, al OutputStream que se
pasa como parmetro.
A continuacin se muestra un ejemplo de construccin de un PrincastReport.
//Obtener el fichero del Report (.jasper)
InputStream stream = loadReport(REPORT_NAME+".jasper");
//Obtener parametros
Map parameters = new HashMap();
MessageResources messages = (MessageResources) request.getAttribute(Globals.MESSAGE
parameters.put("P_Titulo", messages.getMessage("report.title"));
parameters.put("P_AmpliacionTitulo", messages.getMessage("report.description"));
//Crear report
PrincastReport report = new PrincastReport(REPORT_NAME, dataSource, stream);
report.setParams(parameters);
report.process();
Multi Reports
Los Multi-reports son informes compuestos de informes simples. El objetivo de los multi-reports es
agrupar un conjunto de informes para que puedan ser volcados en un mismo fichero PDF.
El openFWPA incluye la clase PrincastMultiReport para la generacin de informes compuestos.
Esta clase es muy simple de manejar: basta con especificarle un nombre (para el fichero PDF) y aadir
todos los informes simples que se quieran adjuntar.
58
Construccion de
informes con openFWPA
Los multi-reports tambin deben ser procesados, al igual que los informes simples, utilizando el mtodo
process().
El informe se puede obtener con el mtodo getPDFContent() que, al igual que en la clase
PrincastReport, devuelve un array de bytes con el informe en formato PDF, listo para ser volcado a
un fichero. Tambin se puede exportar con el mtodo exportPDF(OutputStream).
Si, durante la composicin de un multi-report, se produce un error en la generacin de alguno de los
informes que componen, existen dos posibles polticas para su tratamiento:
a. Ignorar el error. Se trata del comportamiento por defecto. El multi-report se compondr normalmente,
se ignora el informe defectuoso.
b. Propagar el error. En este caso, se interrumpe la generacin del multi-report y se eleva una excepcin
PrincastReportException. Para activar esta poltica, el multi-report se debe crear utilizando el
constructor: PrincastMultiReport(String name, bolean failOnError), asignando
el valor true al parmetro failOnError.
59
Construccion de
informes con openFWPA
tableExporter.addCell("2");
tableExporter.addCell("3");
// se retorna el objeto
return tableExporter;
60
Captulo 6. Operaciones
Sistema de Inicializacin y Arranque
El ncleo del openFWPA se construye sobre un sistema de inicializacin que permite definir, de forma
declarativa, los componentes que deben ser creados, configurados e iniciados durante el perodo de
arranque de las aplicaciones. Generalmente estos componentes son objetos de utilidad que tienen alcance
global a toda la aplicacin, como el sistema de logging, de configuracin, monitorizacin, contadores,
consola de administracin, etc.
A partir de la versin 1.3 del openFWPA el Sistema de Inicializacin se basa en el framework IoC Spring
(www.springframework.org).
61
Operaciones
Donde ruta del fichero es el path del fichero de properties del que se cargarn l
Un ejemplo de uso de variables es el que sigue:
<bean id="myBean" class="es.princast.framework.examples.MyBean
lazy-init="false" singleton="true">
<property name="exampleProp"><value>${PROP}</value></property>
</bean>
Es posible utilizar rutas de fichero absolutas. Para ello, es necesario utilizar la construccin de Spring
FileSystemResources, tal y como se indica en el siguiente ejemplo:
62
Operaciones
<listener>
<listener-class>es.princast.framework.web.startup.PrincastStartupListener</li
</listener>
Arranque manual
El arranque automtico de los servicios del openFWPA (configuracion, management, etc.) unicamente
est operativo en aplicaciones web (al estar basado en un ServletContextListener). Para cualquier
otro tipo de aplicaciones (consola, EJBs, etc.) en las cuales no hay una parte web disponible, para acceder
a los servicios del openFWPA es necesario lanzar la inicialziacin de forma manual.
Para realizar esta tarea, se incluye la clase PrincastStandaloneInitializer. Esta clase se debe
iniciar (utilizando el mtodo esttico init()) al arrancarse la aplicacin. Durante la ejecucin pone
a disposicin de la aplciacin todos los beans declarados en el fichero de inicializacin (princastinit.script.xml), a travs del PrincastApplicationContext, que se obtiene con el mtodo
getInitScriptContext().
63
Operaciones
configuracin de forma completamente transparente, sin necesidad de preocuparse por la forma o el lugar
en que stos estn almacenados.
Atencin
El interface ConfigurationListener ha sido marcado como "deprecated". En su lugar,
se debe utilizar el interface Configurable.
2. Registrarse en el configurador: FrameworkConfigurator.
reconfigure()
Se invoca cuando el valor de algn parmetro que pueda ser relevante para la
configuracin del objeto, es actualizado. Este mtodo recibe como parmetro un
evento de configuracin (ConfigurationEvent).
64
Operaciones
En la implementacin de estos mtodos, el objeto configurable debe obtener, bien del conjunto de
parmetros (ConfigurationParameters), bien del evento (ConfigurationEvent) los datos
que necesite para su configuracin.
Conjunto de Parmetros de Configuracin (ConfigurationParameters)
Se trata de un almacn que contiene todos los parmetros de configuracin de la aplicacin, agrupados
en contextos. Es responsabilidad del objeto configurable seleccionar aquellos parmetros que le puedan
ser de utilidad.
Se pueden obtener todos los parmetros de un conjunto utilizando el mtodo getKeys(). Este mtodo
devuelve una enumeracin (Enumeration) con los nombres (String) de todos los parmetros
existentes en el sistema. Otra opcin es buscar nicamente los parmetros clasificados bajo un contexto
determinado. En este caso, se utilizar el mtodo getKeys(String), pasndo como argumento el
nombre del contexto cuyos parmetros se quieren enumerar.
Para obtener un parmetro del conjunto ConfigurationParameters, se utilizar el mtodo
getParameter(String), si se sabe con certeza que el valor del parmetro es una cadena de
caracteres, o el mtodo getConfigurationObject(String) si se quiere recuperar un Object
genrico. Ambos mtodos reciben como argumento el nombre del parmetro a localizar.
Utilizando estos mtodos, si dos parmetros coinciden en nombre, se devolver el primero que
se encuentre. Para evitar colisiones de nombrado, se pueden utilizar los mtodos alternativos:
getParameter(String, String) y getConfigurationObject(String, String). A
los cuales, se les especifica, como primer argumento, el nombre del contexto en el que se quiere buscar
el parmetro.
public void configure(ConfigurationParameters params) {
String param = params.getParameter(MY_FOO_KEY_1) ;
if (param != null) {
this.fooKey = param;
}
param = params.getParameter(FOO_CONTEXT, MY_FOO_KEY_2);
if (param != null) {
this.fooKey2 = param;
}
}
65
Operaciones
Plugins de Configuracin
Los plugins de configuracin son los componentes que proporcionan los parmetros que maneja el Sistema
de Configuracin. Un plugin de configuracin se encarga de gestionar un nico almacn de datos (un
fichero, una base de datos, etc.), sin embargo, un plugin puede servir parmetros a varios contextos de
configuracin. Los plugins de configuracin, implementan el interface ConfigurationPlugin.
66
Operaciones
67
Operaciones
Plugins en openFWPA.
En el openFWPA se incluyen algunos plugins de configuracin listos para ser utilizados. Adems, se
proporcionan clases para facilitar el desarrollo de plugins por parte de los usuarios.
68
Operaciones
</entry>
<entry key="PARAMETRO.DOS">
<value>Otro valor</value>
</entry>
</map>
</property>
<property name="contexts">
<list>
<value>CONTEXTO.UNO</value>
</list>
</property>
</bean>
En la propiedad properties se deben indicar todos los pares {clave, valor} que va a servir el
plugin. Este plugin puede ser actualizado, pero no se pueden guardar los cambios realizados.
PropertiesFileConfigurationPlugin, que obtiene los parmetros de un fichero de
properties.
Operaciones
</property>
<property name="contexts">
<list>
<value>EXAMPLE.CONTEXT</value>
</list>
</property>
</bean>
Para configurar este plugin, debe escribirse el documento XML (que contiene la configuracin) en la
propiedad xml. Es importante observar que debe escribirse en una seccin CDATA, de lo contrario,
el fichero de inicio no sera valido de acuerdo a su DTD. Este plugin es de solo-lectura.
XMLFileConfigurationPlugin. Carga la configuracin de un fichero xml.
extender
la
clase
Analizar el documento XML. El anlisis del documento se realiza utilizando el API Apache Commons
Digester. Los mtodos a implementar son: setDigesterRules(Digester), en el que se definirn
las reglas del Digester para analizar el fichero y registerDTDs(Digester), para registrar las
DTD que se quieran utilizar para validar el documento XML proporcionado.
Gestionar los parmetros de configuracin. Adems, se deben implementar mtodos que permitan
obtener un determinado parmetro (getParameter()), escribir un valor (setParameter()), etc.
/**
*
* El esquema de la configuracin que acepta es:
*
* <elements>
*
<element value="myId" label="bar"/>
*
<element value="myId2" label="bar2"/>
* </elements>
*/
public class FooContentHandler extends XMLConfigContentHandler {
70
Operaciones
71
Operaciones
}
public void setConfigurationObject(String key, Object value) {
PropertyBean pb = (PropertyBean) getConfigurationObject(key);
if (pb != null) {
if (value instanceof PropertyBean) {
pb.setLabel(((PropertyBean) value).getLabel());
} else {
pb.setLabel(value.toString());
}
} else {
List objects = (List) getXMLObject();
if (value instanceof PropertyBean) {
objects.add(pb);
} else {
objects.add(new PropertyBean(key, value.toString()));
}
}
}
public String getParameter(String path, String key) {
return getParameter(key);
}
public Object getConfigurationObject(String path, String key) {
return getConfigurationObject(key);
}
protected void registerDTDs(Digester digester) {
//No se registran DTDs
}
}
Logging
Para la gestin de las sentencias de log, en el openFWPA, se utiliza la librera: Log4j [18] (http://
logging.apache.org/log4j/). Log4j tiene tres componentes principales: loggers, appenders y
layouts. Estos tres tipos de componentes trabajan juntos para permitir a los desarrolladores escribir
mensajes de log de acuerdo a un tipo de mensaje y prioridad, y para controlar en tiempo de ejecucin la
forma en que estos mensajes se formatean y donde se escriben.
Log4J. Componentes
Loggers
Son entidades con nombre. Sus nombres son sensibles al contexto y siguen una regla de
nombrado jerrquica. Por ejemplo, el logger de nombre com.foo es padre del logger de nombre
com.foo.Bar.
El logger root reside en la cima de la jerarqua de logres. Siempre existe y no puede ser recuperado por
nombre. Para recuperarlo se ha de invocar a mtodo esttico Logger.getRootLogger().
Es posible asignar un nivel a un logger. Los niveles disponibles por orden de menor a mayor son:
DEBUG para mostrar mensajes de depuracin
72
Operaciones
INFO
WARN para mostrar mensajes de alerta sobre eventos de los que se desea mantener constancia, pero que
no afectan al correcto funcionamiento del problema
ERROR para mostrar mensajes de error que afectan a la aplicacin, pero que lo permiten seguir
funcionando (por ejemplo, algn error en un parmetro de configuracin)
FATAL para mostrar mensajes crticos del sistema, generalmente despus del mensaje la aplicacin
finalizar
Si a un logger no se le asigna un nivel, lo hereda de su antecesor ms cercano que tenga asignado uno.
Para asegurarse que todos los loggers tienen un nivel, el logger raz siempre tiene asignado un nivel.
Las escrituras se realizan invocando a alguno de los mtodos de impresin del logger: debug, info, warn,
error, fatal y log. El mtodo de impresin define el nivel de la escritura. Una escritura se dice que est
habilitada si su nivel es mayor o igual que el nivel de su logger. De otra forma se dice que la escritura esta
deshabilitada. El orden de los niveles es: DEBUG < INFO < WARN < ERROR < FATAL.
Appenders
Log4j permite que los mensajes se impriman en mltiples destinos, a cada uno de los cuales se le
denomina Appender. Algunos de los Appenders disponibles son:
ConsoleAppender
FileAppender
RollingFileAppender
DailyRollingFileAppender
SocketAppender
SMTPAppender
JDBCAppender
SyslogAppender
NTEventLogAppender
JMSAppenders
Layouts
El Layout es el responsable de formatear los mensajes de log de acuerdo a las definiciones del
desarrollador. Los tipos de Layouts disponibles son:
73
Operaciones
SimpleLayout
PatternLayout
HTMLLayout
XMLLayout
especifica que la salida ser un fichero XML que cumple con el log4j.dtd
TTCCLayout
Configuracin
En el diagrama de la Figura 6.3, Estados del Sistema de Logging se puede ver el ciclo de vida de la
configuracin del Sistema de Log de una aplicacin que utiliza openFWPA. Los estados por los que puede
pasar son los que siguen:
1. No Log: En este estado no hay configuracin alguna cargada. Si se lanza alguna sentencia de log,
aparecer un WARNING en la salida estndar del servidor OC4J. Este estado no debera producirse pero
se puede dar en caso de que se inicialicen componentes antes que el framework (listeners, ejbs, etc.)
2. Arranque: Se carga la configuracin de arranque del openFWPA. Esta configuracin se definir en
el fichero log4j.properties ubicado en el classpath de la aplicacin. En este fichero se puede
definir una configuracin de log, nicamente activa durante el proceso de arranque de la aplicacin.
3. Runtime: En este estado se supone activa la configuracin de log de la aplicacin. Esta configuracin
se define en el fichero xml indicado en el parmetro de configuracin LOGGING_XMLCONF, o en el
fichero de properties, cuyo path se indica en el parmetro de configuracin, LOGGING_PROPERTIES.
Ejemplo de Configuracin
El sistema de logging se configura a travs de, por ejemplo, el fichero WEB-INF/log4j.xml (path que
se especifica bajo la constante de configuracin: LOGGING_XMLCONF). Este fichero debiera estar dentro
del fichero war de la aplicacin. Puede verse un ejemplo de utilizacin en la aplicacin en blanco (App
Blank) y en la de ejemplo (Sample App).
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
<appender name="HTML" class="org.apache.log4j.DailyRollingFileAppender">
74
Operaciones
Atencin
Obsrvese que a pesar de haberse definido el appender STDOUT, no se est utilizando en ningn
caso. Este "no uso" es intencionado para evitar que, por descuido o por accidente, se vuelque
indiscriminadamente el log de las aplicaciones en la consola de los servidores, ya que se puede
producir un error por desbordamiento, en caso (muy probable) de que los administradores hagan
una redireccin a fichero de la salida.
En este fichero se definen varios Appenders (o destinos donde el logger va a escribir). La salida estndar,
un fichero Html (que cambiar todos los dias) y otro Appender de nombre Audit similar al anterior. Para
cada uno de ellos se define tambin el layout o plantilla que se utilizar para escribir la salida.
Tambin se definen categoras, donde se especifica para cada logger el nivel que tendr y los Appenders
que utilizar.
A continuacin se muestra la salida de un Appender que escribe en un fichero Html.
Para ms informacin sobre la configuracin del logger consultar la documentacin del mismo en la
direccin http://logging.apache.org/log4j/docs/manual.html
75
Operaciones
Obtener los loggers estndar del framework: Pista de Auditora y Pista de Rendimiento.
El LoggerManager se puede gestionar desde la consola JMX.
PrincastHTMLLayout
Adems de los layouts incluidos en Log4J (Ver Layouts), las aplicaciones tambin pueden utilizar
PrincastHTMLLayout. Este objeto es igual que el HTMLLayout estndar, con la diferencia de que
muestra la fecha y hora en que se escribe la sentencia de log.
Pista de auditora
Las aplicaciones han de registrar todas las operaciones de usuario que realicen en la denominada pista
de auditoria. Para cada entrada aparecer el usuario y la direccin IP desde la que se realiz la operacin
(registro NDC), ms una descripcin de la operacin realizada.
La salida es configurable, pudiendo ser de distintos formatos y en distintos soportes. Por defecto, se
vuelca en un fichero en formato HTML. Cada da se mueve el contenido de este log a un fichero con la
extensin .YYYY-MM-DD. El siguiente ejemplo se ha sacado de la aplicacin de ejemplo, y muestra la
ejecucin de dos operaciones marcadas como auditables:
76
Operaciones
Pista de Rendimiento
La Pista de Rendimiento es un logger, muy similar a la Pista de Auditora, que permite escribir las
mediciones de rendimiento que se realicen en la aplicacin. La configuracin de la Pista de Rendimiento,
se realizar en el fichero log4j.xml.
Ficheros de Configuracin
Para la implementacin de aplicaciones web, utilizando el openFWPA, es necesario definir correctamente
los ficheros web.xml y struts-config.xml. En los apartados siguientes, se describe el contenido
que stos deberan tener.
web.xml
Como ejemplo de fichero web.xml, se tomar el incluido en la aplicacin en blanco (Blank App).
El primer bloque que se encuentra es el referente a la configuracin de filtros. Se define el filtro Gzip
(llamado GZIPFILTER), y se indica que todas las peticiones servlet de nombre action (que es el
ActionServlet) pasen por dicho filtro.
<!-- filtro GZip -->
<filter>
<filter-name>GZIPFILTER</filter-name>
<filter-class>es.princast.framework.web.filter.gzip.GZIPFilter</filter-class>
</filter>
<!-- Mapear el filtro GZip con el ActionServlet -->
<filter-mapping>
<filter-name>GZIPFILTER</filter-name>
<servlet-name>action</servlet-name>
</filter-mapping>
Otro filtro que se proporciona en la aplicacin en blanco es el de control de autenticacin. Para su activacin
es necesario incluir los siguientes elementos XML:
77
Operaciones
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>es.princast.framework.web.filter.security.corp.PrincastSecurityFilte
</filter>
<!-- Mapeo del filtro de seguridad -->
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<servlet-name>/action/*</servlet-name>
</filter-mapping>
El siguiente conjunto de elementos hacen referencia al arranque e inicializacin de la aplicacin. Se
trata de la variable de contexto que indica la ubicacin del fichero de arranque (princast-initscript.xml) y el listener de inicializacin:
<context-param>
<param-name>INIT.SCRIPT.FILE</param-name>
<param-value>/WEB-INF/princast-init-script.xml</param-value>
</context-param>
<listener>
<listener-class>es.princast.framework.web.startup.PrincastStartupListener</li
</listener>
En el siguiente bloque se configura el ActionServlet. Se le pasan como parmetros:
config
debug
detail
el nivel de detalle del Digester que se usa para procesar los ficheros de
configuracin de la aplicacin. Acepta los mismos valores que el parmetro
debug.
application
validating
definitions-config
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>es.princast.framework.web.action.PrincastActionServlet</servle
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
78
Operaciones
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>application</param-name>
<param-value>resources.ApplicationResources</param-value>
</init-param>
<init-param>
<param-name>validating</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>definitions-config</param-name>
<param-value>/WEB-INF/tiles-defs.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
El siguiente bloque indica al contenedor que debe redirigir cualquier peticin que contenga /action/
al ActionServlet, es decir, al servlet configurado en el bloque anterior.
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/action/*</url-pattern>
</servlet-mapping>
En este bloque se indica que fichero servir por defecto la aplicacin. Tiene que ser un fichero fsico, no
es posible indicar una accin. Si se desea, en el propio fichero se puede redirigir a una accin como se
hace en la aplicacin de ejemplo (Sample App).
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
A continuacin se configuran las libreras de tags que utiliza la aplicacin. A partir de la versin del
Framework 1.5, se utiliza la versin de Struts 1.2, por lo que no se necesitan configurar las tags de Struts.
<taglib>
<taglib-uri>/WEB-INF/princast.tld</taglib-uri>
<taglib-location>/WEB-INF/princast.tld</taglib-location>
</taglib>
struts-config.xml
En este apartado se explicar el formato del fichero struts-config.xml incluido en la aplicacin
en blanco (Blank App). Este fichero est dividido en varios bloques: form-beans, globalexceptions, global-forwards, action-mappings, message-resources y plug-ins.
<form-beans>
Aqu se definen los beans de formulario, es decir, clases que heredan de
es.princast.framework.web.action.PrincastActionForm, y que sirven para almacenar
79
Operaciones
las propiedades introducidas en formularios enviados mediante peticiones Http. Estos formularios sern
utilizados por las acciones.
<form-bean name="detalleProductoForm"
dynamic="true"
type="es.princast.framework.web.action.PrincastDynaActionForm">
<form-property name="detalle" type="es.princast.framework.carrito.vo.ProductoVO" />
</form-bean>
<global-exceptions>
Se utilizan para tratar excepciones que no han sido tratadas en la Action.
En el siguiente ejemplo se indica que las excepciones no capturadas del tipo
es.princast.framework.exceptions.PrincastException, sean reenviadas a la pgina
indicada en el atributo path (en este caso se trata de una definition). El mensaje de error que
se mostrar en la pgina de error con el tag <html:errors/>, estar en el fichero de recursos
(ApplicationResources.properties) con la clave cuyo valor se indique en el atributo key.
Mediante el atributo handler se especifica qu manejador de errores se utilizar para tratar la excepcin.
En este caso se trata del manejador por defecto de Struts (que en el mtodo execute no realiza nada), pero
podra definirse un manejador que heredase de l y sobrescribiese el mtodo execute.
Se recomienda utilizar el mtodo catchException() de las acciones para tratar las excepciones y no
recurrir a excepciones globales.
type
scope
80
Operaciones
Poner a true si el mtodo validate del bean de formulario debe ser llamado
antes de llamar a este mapeo.
A continuacin se comentarn de forma ms detallada los distintos tipos de acciones que maneja el
framework.
PrincastAction
Operaciones
PrincastExistsAttributeAction
PrincastRemoveAttributeAction
Trata de eliminar un atributo en alguno de los mbitos
posibles (request, session o application). Si el
atributo existe devuelve el control a un ActionForward
instanciado con Tokens.SUCCESS y sino con uno instanciado
con Tokens.FAILURE. La sintaxis es idntica a la de la
PrincastExistsAttributeAction.
<controller>
En
el
siguiente
bloque
se
configura
el
controlador (RequestProcessor). Se recomienda utilizar
el
controaldor
proporcionado
por
el
openFWPA
(PrincastTilesRequestProcessor). El uso de este
controlador permite aadir alguna funcionalidad extra que no
implementa el controaldor por defecto (por ejemplo, mltiples
input por action, forwards a entradas de men, etc.)
<controller processorClass="es.princast.framework.web.act
El uso de este RequestProcessor limita los posibles
mapeos que se pueden hacer sobre el ActionServlet (ver a
continuacin). Las Actions nicamente se pueden mapear a un path
del tipo: /path/*. No se permiten mapeos del tipo: /path/
*.do.
<message-resources>
82
Operaciones
Indica
que
fichero
contiene
los
mensajes
que
mostrar
la
aplicacin.
En
este
caso
se
trata
del ApplicationResources.properties del paquete
resources.
<message-resources parameter="resources.ApplicationResour
<plug-in>
Aqu se indica que plug-ins va a utilizar la aplicacin. En primer
lugar se indica que se utilizar el validador de Struts, y que las reglas
de validacin se encuentran en validator-rules.xml y los
mapeos entre los formularios y las reglas en validation.xml.
<plug-in className="org.apache.struts.validator.Validator
<set-property property="pathnames" value="/WEB-INF/valida
</plug-in>
A continuacin se indica que se utilizara tiles, y que las definitions
se describirn en el fichero tiles-defs.xml.
<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config" value="/WEB-I
<set-property property="moduleAware" value="true" />
<set-property property="definitions-parser-validate" valu
</plug-in>
Y por ltimo se indica que se utilizara el Struts Menu [16] y que su
configuracin residir en el fichero menu-config.xml.
<plug-in className="net.sf.navigator.menu.MenuPlugIn">
<set-property property="menuConfig" value="/WEB-INF/menu</plug-in>
Filtros web
Con vistas a poder acceder de forma sencilla a las peticiones y respuestas HTTP que circulan entre el
navegador del cliente y el servidor Web se proporciona una arquitectura de filtros extensible de forma
sencilla.
83
Operaciones
Atencin
El mtodo que se debe sobreescribir es filter() y no doFilter() como se hara para
escribir un filtro normal. El mtodo doFilter() es final en la clase PrincastFilter.
3. Crear un interfaz java que extienda el interfaz PrincastFilterMBean. Este interfaz debe tener
como nombre el de la clase Java que define el nuevo filtro seguido de MBean. Esto es necesario para
poder hacer uso de las facilidades JMX [19] aportadas por el openFWPA para la gestin de los filtros.
No es necesario que el nuevo interfaz tenga mtodos.
4. Si se quiere implementar alguna lgica al inicializar el filtro, se debe extender el mtodo
initFilter().
Atencin
A partir de la versin 1.5, el mtodo init() de la clase PrincastFilter es final, por lo
tanto ya no se puede extender dicho mtodo.
84
Operaciones
<param-name>EXCLUDED.URL.LOGOUT </param-name>
<param-value>
/action/logout
</param-value>
</init-param>
</filter>
Adems, utilizando la consola JMX, es posible actualizar, en caliente, los patrones de URLs que se
excluirn del efecto del filtro.
Filtro de navegacin
El Filtro de Navegacin (clase NavigationFilter) tiene dos objetivos:
1. Mantener siempre el conocimiento de las entradas de men (y submenu) activas, evitando la necesidad
de utilizar tecnologas del lado del cliente como JavaScript y Cookies.
85
Operaciones
<filter>
<filter-name>NavigationFilter</filter-name>
<filter-class>es.princast.framework.web.filter.navigation.NavigationFilter</filter
</filter>
<filter-mapping>
<filter-name>NavigationFilter</filter-name>
<url-pattern>/action/*</url-pattern>
</filter-mapping>
El Filtro de Navegacin debe estar mapeado a todas las URLs referenciadas por alguna entrada de men
o submenu.
El Filtro de Navegacin, extrae de la Request los valores de los parmetros GET que indican la entrada
de men y submenu activas y, a partir de ellas, se encarga de mantener el estado del men y de la barra
de navegacin, manteniendolos siempre sincronizados.
Para conocer los nombres de los parmetros GET a los que tiene que acceder, el Filtro de Navegacin
implementa el interface ConfigurationListener (es decir, es un objeto configurable por el sistema
de configuracin del openFWPA) que escucha el contexto del men (MENU.CONTEXT), lo que significa,
que no se requiere ninguna configuracin especial para el Filtro de Navegacin, siempre y cuando, se
configure convenientemente el men.
Filtro de activacin
El Filtro de Activacin (clase AppActivationFilter) permite definir, cuando una aplicacin est
activa y cuando no. Este filtro tiene dos funciones:
1. Implementar lgica para activar/desactivar las aplicaciones en funcin de la fecha actual.
2. Servir como clase base para la implementacin de otros filtros que permitan determinar nuevas
condiciones para la activacin/desactivacin de aplicaciones.
Nombre del contexto de configuracin que se utilzar para especificar los intervalos de
actividad de la aplicacin. Por defecto vale: ACTIVATION.FILTER.
DATE.FORMAT
ERROR.URL
URL a la que se redirigir en caso de no estar activa la aplicacin para la fecha actual.
Este atributo es obligatorio.
86
Operaciones
Los intervalos se definen utilizando dos fechas separadas por el caracter "-". El formato de las fechas se
define con el parmetro de inicializacin: DATE.FORMAT.
Si el extremo de un intervalo est indeterminado, se puede utilizar el caracter "?".
Por ejemplo:
ACTIVE.INTERVAL.1:
ACTIVE.INTERVAL.2:
ACTIVE.INTERVAL.3:
ACTIVE.INTERVAL.4:
handleInactive()
Filtros de Activacin
En ocasiones, es necesario poder activar (o desactivar) una aplicacin o determinadas partes de la misma,
de forma declarativa. El openFWPA, desde la versin 1.5, incluye una clase base (ActivacionFilter)
que facilita la implementacin de filtros web para la gestin de la activacin de las aplicaciones.
Bsicamente este tipo de filtros tienen dos responsabilidades: a) determinar cuando la aplicacin est activa
(o no) y b) en caso de que la aplicacin est inactiva ejecutar alguna operacin (generalmente redireccionar
a una pgina de aviso).
Para implementar filtros de activacin es necesario extender la clase ActivationFilter. Los mtodos
ms relevantes de esta clase son:
isActive()
handleInactive()
configure()
Filtro de Temporalidad
El Filtro de Temporalidad permite activar/desactivar una aplicacin (o partes de la misma) en funcin de
la fecha en la que se produzca el acceso.
87
Operaciones
El Filtro de Temporalidad (clase TimingFilter) es un filtro de activacin y, por tanto, tiene todas sus
caractersticas.
El Filtro de Temporalidad permite que los recursos que protege estn activos nicamente durante
determinados intervalos temporales, definidos como parmetros de configuracin. Estos parmetros
seguirn el siguiente convenio de nombrado: ACTIVE.INTERVAL.<id del intervalo>. El valor
del intervalo, se especificar siguiendo el convenio: <inicio intervalo> - <fin intervalo>,
pudiendo especificarse el inicio o el fin del intervalo de las siguientes formas:
a. Con una fecha, especificada segn cualquier formato estndar vlido (SimpleDateFormat). El
formato concreto a utilizar se define con el parmetro de configuracin: DATE.FORMAT. Por defecto
vale: ."dd/MM/yyyy HH:mm:ss".
b. Utilizando el caracter "?". En este caso, se supone que se trata de un intervalo abierto, cuyo extremo
est inespecificado.
Algunos ejemplos de intervalos pueden ser:
ACTIVE.INTERVAL.1
ACTIVE.INTERVAL.2
ACTIVE.INTERVAL.3
ACTIVE.INTERVAL.4
=
=
=
=
Consola de gestin
Los componentes del openFWPA, estn diseados para que puedan ser monitorizados y gestionados, en
tiempo de ejecucin, utilizando una consola de gestin. A travs de la consola de gestin, el administrador
de sistemas puede arrancar, detener y reconfigurar en caliente los componentes del framework que
estime conveniente.
Para la implementacin de la consola de administracin se utiliza el API JMX (Java Management
Extensions). Este API permite la gestin y configuracin de objetos de la aplicacin.
El sistema de gestin JMX del openFWPA se configura utilizando el contexto de configuracin de nombre
JMX.CONTEXT. Los parmetros necesarios para activar la consola de gestin son los siguientes:
MBEAN.SERVER.NAME
JMX.SERVER.ADAPTOR
es.princast.framework.core.management.adapters.NullMBeanServe
Para no utilizar ningn servidor. La consola de administracin JMX
aparecer desconectada.
88
Operaciones
es.princast.framework.core.management.adapters.JMXRIMBeanServ
Para conectar con la implementacin JMX de referencia (JMX-RI). Este
adaptador se debe utilizar con el contenedor OC4J 9.0.3. Si se va a utilizar
este adaptador, se deben definir, adems, los siguientes parmetros de
configuracin.
JMX.HTTP.PORT. Puerto donde escuchar la consola HTML.
JMX.HTTP.USERNAME. Nombre de usuario vlido para acceder a la
consola.
JMX.HTTP.PASSWORD. Contrasea vlida para acceder a la consola.
es.princast.framework.core.management.adapters.OC4JMBeanServe
Para conectar con la implementacin incluida en el servidor OC4J 10g. Si
se utiliza este adaptador, todo el sistema de operacin de las aplicaciones
estar integrado en la consola de administracin del contenedor.
Para conocer ms detalles a cerca de la consola de gestin, consultar el Manual de Operaciones.
89
Autentificacin bsica
La autentificacin bsica delega el control de acceso al servidor Web. El usuario podr navegar libremente
por el sitio Web sin necesidad de facilitar una contrasea. Sin embargo, cuando se intente acceder a una
pgina protegida ser el propio navegador el que solicite al usuario un nombre de usuario (username) y
una contrasea (password) mostrndole una ventana de dialogo.
Tanto el nombre de usuario como la contrasea son enviados sin encriptar al servidor Web, quien se
encarga de validar-los contra un fichero plano, un base de datos o servidor de directorios.
Si el usuario consigue validarse se comprueba que se tenga privilegio suficiente para acceder al recurso
basndose en ciertas polticas definidas, por ejemplo, en un fichero tipo http.conf. Si la comprobacin
es positiva se sirve la pgina al cliente. En caso contrario, se le solicita de nuevo la combinacin usuario/
contrasea o se le muestra una pgina de error denegando el acceso.
90
Seguridad en aplicaciones
con openFWPA
Configuracin
El sistema de seguridad estndar se configura utilizando el Sistema de Configuracin del openFWPA.
Todo el sistema tomar parmetros del contexto de seguridad llamado SECURITY, por lo tanto, es
importante recordar que cualquier plugin que sirve parmetros al sistema de seguridad debe registrarse
para el contexto SECURITY.
91
Seguridad en aplicaciones
con openFWPA
Parmetros bsicos
Los parmetros bsicos son:
app-config
http.PORT
https.PORT
https/cert.PORT
Puerto https (SSL-3) con certificado digital de cliente, que se utiliza para acceder
a la aplicacin. Si no se especifica este parmetro se utilizar el puerto SSL (443)
por defecto.
http.IP
https.IP
Direccin IP (o nombre DNS) del servidor que atiende peticiones https (SSL v2),
con certificado de servidor. Si no se especifica este parmetro, la redireccin se
realizar sobre la IP del propio contenedor.
https/cert.IP
Direccin IP (o nombre DNS) del servidor que atiende peticiones https (SSL v3),
con certificado de cliente. Si no se especifica este parmetro, la redireccin se
realizar sobre la IP del propio contenedor.
Por ejemplo:
#
#Fri Jan 07 10:08:36 CET 2005
HIT.COUNTER=es.princast.framework.core.management.mcounters.historic.HistoricalCoun
ACTION_MGMT=es.princast.framework.web.action.monitoring.PrincastActionMgmtInterface
LOGGING_XMLCONF=/WEB-INF/log4j.xml
app-config=EjemploApp
http.PORT=8888
https.PORT=4443
https/cert.PORT=8844
https/cert.IP=192.168.7.7
JMX.SERVER.ADAPTOR = es.princast.framework.core.management.adapters.OC4JMBeanServer
92
Seguridad en aplicaciones
con openFWPA
Configuracin JAAS
El sistema de autenticacin del openFWPA est basada en el estndar JAAS (Java Authentication and
Authorization Service). En realidad, el Filtro de Seguridad, no realiza ninguna tarea de autenticacin.
Estas funciones son delegadas en un Mdulo de Login JAAS (LoginModule). La configuracin del
mdulo a utilizar para autenticar y autorizar usuarios se realiza a travs del plug-in de configuracin JAAS
(JAASConfigurationPlugin), que debe ser declarado en el fichero de inicializacin princastinit-script.xml. Por ejemplo:
<!DOCTYPE jaas
PUBLIC "-//Framework PA - Team//DTD JAAS Configuration 1.3F//ES"
"jaas-config.dtd">
<jaas>
<application name="Carrito" controlFlag="required">
<module>es.princast.framework.modules.security.standalone.StandaloneLoginModule</
<options>
<option>
<name>USERS.FILE</name>
<value>/WEB-INF/authorized-users.xml</value>
</option>
</options>
</application>
</jaas>
En este fichero se definen los mdulos de configuracin a utilizar. Cada mdulo se define con la etiqueta
<application ..>. Cuando se vaya a autenticar a un usuario, se utilizar el mdulo cuyo valor del
atributo name coincida con el parmetro app-config (de los parmetros bsicos de autenticacin,
ver seccin anterior).
Eventualmente, el atributo controlFlag est desactivado. No se tiene en consideracin el valor
especificado para realizar la autenticacin.
Para cada mdulo, es obligatorio indicar el nombre de la clase que implementa la lgica de autenticacin,
utilizando la etiqueta anidada: <module>. Esta clase debe implementar el interface: LoginModule,
definido en el paquete JAAS. Por ltimo, en la etiqueta <options> se pueden definir todas las opciones
de configuracin especficas del mdulo JAAS que se vaya a utilizar.
Reglas de Seguridad
Por ltimo, es necesario configurar las reglas de seguridad que definirn que recursos de la aplicacin
estn protegidos, y de que forma.
Un recurso slo puede estar protegido una vez. Si una URL encaja en varios patrones definidos en el
fichero de reglas de seguridad, se tendr en cuenta el patrn ms restrictivo.
93
Seguridad en aplicaciones
con openFWPA
Para configurar las reglas de seguridad, se debe definir, en el fichero princast-init-script.xml,
un plug-in de configuracin de tipo: SecurityRulesConfigurationPlugin. Por ejemplo:
94
Seguridad en aplicaciones
con openFWPA
Generalmente, un nivel de seguridad permite el login por los mecanismos para s definidos y tambin
mediante los definidos para niveles superiores. Por ejemplo, un recurso protegido bajo usuario/ contrasea
tambin ser accesible con certificado digital. La semntica exacta del nivel de seguridad, la define el
mdulo JAAS.
El protocolo (atributo protocol) define el tipo de acceso deseado al recurso. Puede tomar dos valores:
http si no se quiere ninguna encriptacin del recurso o https si se desea garantizar la privacidad de
los datos transmitidos entre el cliente y la aplicacin. Este atributo puede omitirse, en tal caso, se permite
el acceso al recurso bajo cualquier protocolo.
Un recurso protegido es, exactamente, un patrn URL que se aplica sobre el espacio de direcciones de la
aplicacin. Este patrn URL se define en la etiqueta anidada <url-pattern>. Si, en un mismo fichero
de reglas, varios patrones, de varios recursos, coinciden, el recurso que se utiliza para autenticar es el que
defina el patrn ms restrictivo de todos.
Cuando se produce un error autenticando al usuario, en funcin de la naturaleza de dicho error, el Filtro
de Seguridad, actuar redireccionando a un path determinado. Por ejemplo, si no se puede autenticar al
usuario porque la contrasea es incorrecta, se le redirigir a una pgina donde se muestra el formulario de
entrada. Sin embargo, si no se puede autenticar al usuario porque no tiene privilegios suficientes (roles)
para acceder a un recurso, se le puede redireccionar a otra pgina distinta informndole de dicha situacin.
Las redirecciones se especifican bajo la etiqueta <forwards>. Cada redireccin tendr un nombre que
la identifica (name) y una url a la que se redirigir al usuario (path).
Los nombres de forwards vlidos son:
login
Se redirige a login la primera vez que un usuario trata de acceder a un recurso protegido.
no-login
Esta redireccin se ejecuta cuando no se puede autenticar al usuario por cualquier motivo
(por ejemplo, contrasea equivocada)
no-roles
Se redirige a este forward cuando el usuario, que est correctamente autenticado, no tiene
autorizacin para acceder al recurso.
error
En cada recurso tambin se definirn los nombres de los roles que tienen acceso. Si no se incluye la
etiqueta <roles> , no se realizar chequeo de roles.
Por ltimo, se pueden definir las opciones de configuracin (<options>) que se estimen convenientes
para el recurso. La semntica de estas opciones depende exclusivamente del mdulo JAAS que realiza
la operacin de login.
Paso de Credenciales
Durante el proceso de autenticacin, se recaba una serie de datos del usuario. Estos datos se
guardan en la sesin http en un objeto de tipo javax.security.auth.Subject, bajo la clave
SecurityGlobals.SUBJECT.
Este objeto tiene los siguientes mtodos:
1. java.util.Set getPrincipals(). Devuelve un Set con los Principals (datos de
usuario) conocidos durante el proceso de autenticacin.
95
Seguridad en aplicaciones
con openFWPA
2. java.util.Set getPrincipals(PrincastIdentifier.class). Devuelve un Set con
el Principal ms importante, el DNI. Es equivalente a request.getUserPrincipal().
3. java.util.Set getPrincipals(PrincastCompositePrincipal.class). Devuelve
un Set con los Principal secundarios, de tipo java.util.Properties. Este objeto contiene
todas las propiedades capturadas en cada escenario en concreto, que son especficas a l (por ejemplo,
puede haber o no un IDTercero en funcin del escenario).
4. java.util.Set getPrincipals(Group.class). Devuelve un Set con todos los roles que
soporta un usuario.
5. java.util.Set getPrincipals(ScenarioPrincipal.class). Devuelve un Set que
contiene el Principal con los datos del escenario. Este Principal es un mapa que contiene
los parmetros que definen el escenario bajo el que se realiz el proceso de autenticacin (nivel de
seguridad, canal de acceso, tipo de actor, etc.)
Atencin
No es recomendable obtener los datos de autenticacin (j_username y j_password)
directamente de los parmetros de la request. No se garantiza que estos datos vayan a ser los
correctos. Adems, desde la versin 1.5, cualquier parmetro que se utilice como contrasea ser
enmascarado (reemplazado por la cadena "*********") por el filtro de autenticacin.
A continuacin se muestran diferentes ejemplos de recuperacin de credenciales.
Recuperacin del identificador de tercero de un usuario
...
PrincastCompositePrincipal principal = //Obtener el principal normalemente...
Map uniOrgs = new HashMap();
String id = principal.getPrincipal(SecurityConstants.ORGANIZATIONAL_UNIT_ID);
String name = principal.getPrincipal(SecurityConstants.ORGANIZATIONAL_UNIT_NAME);
if (id != null) {
uniOrgs.put(id, name);
}
96
Seguridad en aplicaciones
con openFWPA
int index = 1;
do {
id = princpal.getPrincipal(SecurityConstants.ORGANIZATIONAL_UNIT_ID+"_"+index);
name = princpal.getPrincipal(SecurityConstants.ORGANIZATIONAL_UNIT_NAME+"_"+index)
if (id != null) {
uniOrgs.put(id, name);
}
} while (id != null);
...
Recuperacin de los dominios de usuario.
Subject subject = (Subject) request.getSession(true).getAttribute(
SecurityGlobals.SUBJECT);
Set principals = subject.getPrincipals(PrincastRole.class);
Iterator it = principals.iterator();
while (it.hasNext()) {
PrincastRole pr = (PrincastRole) it.next();
Iterator itDom = pr.getDomains().iterator();
while (itDom.hasNext()) {
PrincastDomain pd = (PrincastDomain) itDom.next();
if (!pd.isProcedure()) {
logger.info("Nombre del dominio: " + pd.getName())
}
}
}
97
Seguridad en aplicaciones
con openFWPA
<body onload="document.forms[0].j_username.focus()">
<princast:login>
<princast:panel layouterClass="es.princast.framework.web.view.layout.DivLayouter
<princast:panel-legend>Login</princast:panel-legend>
<princast:block cssClass="login_message">
<p>Bienvenido a la aplicacin de ejemplo SampleApp</p>
</princast:block>
<princast:block cssClass="login_inputs">
<label for="j_username">Usuario:</label>
<input type="text" name="j_username" id="j_username" />
</princast:block>
<princast:block cssClass="login_inputs">
<label for="j_password">Contrasea:</label>
<input type="password" name="j_password" id="j_password" />
</princast:block>
<princast:block cssClass="login_submit">
<p>
<input type="image" src="images/botones/enter-button.gif" alt="Entrar"/>
<input type="image" src="images/botones/right-arrow.gif" alt="Entrar"/>
</p>
98
Seguridad en aplicaciones
con openFWPA
</princast:block>
</princast:panel>
<princast:login-footer>
Por favor, si no va a utilizar la aplicacin cierre la sesion para evitar que ot
</princast:login-footer>
</princast:login>
</body>
</html:html>
<table>
<logic:iterate id="pos" name="PASSWORD_POSITIONS">
<tr>
<td>Introduzca la posicion <%=pos%><input type="hidden" name="PASSWORD_POSITIONS
<td><input type="text" name="PASSWORD_POSITIONS_<%=pos%>" size="1" maxlength="1"
</tr>
</logic:iterate>
</table>
99
Seguridad en aplicaciones
con openFWPA
100
Seguridad en aplicaciones
con openFWPA
<%@ page import="es.princast.framework.web.filter.security.common.SecurityGlobals"
<html:html locale="es" xhtml="true" >
<head>
<html:base />
<title>
Bienvenido al Principado de Asturias
</title>
<link type="text/css" rel="stylesheet" href="css/general.css" />
<link type="text/css" rel="stylesheet" href="css/components.css" />
<link type="text/css" rel="stylesheet" href="css/login.css" />
</head>
<body onload="document.forms[0].j_username.focus()">
<princast:login>
<princast:panel layouterClass="es.princast.framework.web.view.layout.DivLayouter
<princast:panel-legend>Login</princast:panel-legend>
<princast:block>
<princast:instanceOf variableName="<%=SecurityGlobals.LOGIN_EXCEPTION%>" class
<div id="errors">
<ul>
<li>Validación incorrecta de NIF/NIE y Clave personal</li>
</ul>
</div>
</princast:instanceOf>
<princast:instanceOf variableName="<%=SecurityGlobals.LOGIN_EXCEPTION%>" clas
<div id="errors">
<ul>
<li>Introduzca todos los datos que se solicitan</li>
</ul>
</div>
</princast:instanceOf>
</princast:block>
<princast:block cssClass="login_message">
<p>Bienvenido a la pgina de login de colaborador de ejemplo</p>
</princast:block>
<princast:block cssClass="login_inputs">
<p>Identificador de Colaborador</p>
<input type="text" name="j_username" id="j_username" value="<%=session.getAttri
</princast:block>
<princast:block cssClass="login_inputs">
<p>Contrasea del Colaborador</p>
<input type="password" name="proxyPassword" id="proxyPassword" value=
"<%=session.getAttribute(SecurityConstants.PASSWORD) != null ? session.get
</princast:block>
<princast:block cssClass="login_inputs">
<p>NIF/NIE del ciudadano</p>
<input type="text" id="nif" name="nif" value=
"<%=session.getAttribute(SecurityConstants.NIFNIE)!=null ? session.getAttr
</princast:block>
<princast:block cssClass="login_inputs">
<p>Si representa a una persona jurdica, introduzca su CIF</p>
101
Seguridad en aplicaciones
con openFWPA
className
102
classNam
Seguridad en aplicaciones
con openFWPA
Como
se
puede
apreciar
se
comprueba
que
la
excepcin
que
se
encuentra
almacenada
en
la
clave
SecurityGlobals.LOGIN_EXCEPTION
sea
de
la
misma
clase
que
es.princast.framework.facilities.security.
exceptions.WrongPasswordException. En caso afirmativose incluyen los elementos
contenidos entre <princast:instanceOf></princast:instanceOf>. Las excepciones
que se pueden disparar durante el proceso de autenticacin, se encuentran en el paquete:
es.princast.framework.facilities.security.exceptions.
Niveles de Seguridad
Para la autenticacin se contemplan tres niveles de seguridad:
Nivel 0
Nivel 1
Con este nivel es necesaria la validacin mediante usuario y contrasea. Para ello, deben
especificarse dos parmetros denominados j_username y j_password con dicha
informacin.
Nivel 2
Single Sign On
Con el fin de facilitar la integracin de aplicaciones en un mismo portal, el Principado de Asturias dispone
de una solucin Single Sign On (SSO), basada en el producto Novell iChain.
El sistema Single Sign On permite a un usuario, acceder a varias aplicaciones autenticndose una nica
vez, valiendo esta autenticacin para todas ellas.
Actualmente, se pueden autenticar contra el sistema SSO todos los usuarios dados de alta en el LDAP
corporativo del Principado de Asturias.
El filtro de seguridad del openFWPA soporta, a partir de la versin 1.5 , de forma automtica, autenticacin
basada en el SSO del Principado de Asturias para todos los escenarios de autenticacin de Nivel 1 (salvo
los que utilizan posiciones de contrasea).
Atencin
Para que el filtro de seguridad se pueda integrar correctamente con SSO, ste debe enviar, en la
cabecera de la peticin http (header) el par usuario/contrasea codificado en Base64, utilizando
es esquema bsico (Basic) de autenticacin http.
Para utilizar el SSO en versiones anteriores a la 1.5, se debe utilizar el "parche para compatibilidad con
SSO".
103
104
Integracin de Sistemas
es.princast.framework.facilities.backends.genericXML.connection.
Establece una conexin con el sistema, sin efectuar validacin
FrameworkConnectionXML
de la DTD. Se recomienda su uso nicamente en entornos con
conectividad limitada.
Realiza URL encode del contenido a enviar al sistema XML
Genrico con el que interactua.
es.princast.framework.facilities.backends.genericXML.connection.
Establece una conexin con el sistema, sin efectuar validacin
FrameworkConnectionXMLNoEncoding
de la DTD. Se recomienda su uso nicamente en entornos con
conectividad limitada.
Esta conexin es igual a la anterior con la salvedad de que no
se realiza el URL encoding. Es el tipo de conexin a utilizar
cuando el sistema a conectar sea BDGENERICOS.
es.princast.framework.facilities.backends.genericXML.connection.
Si se utiliza este tipo de conexin, no se producir ninguna
MockConnectionXML
comunicacin real con el sistema cliente. La conexin ser
nicamente simulada. Este tipo de conexin se debe utilizar
nicamente para pruebas de desarrollo.
105
Captulo 9. Pruebas
Pruebas unitarias
Toda aplicacin J2EE desarrollada utilizando el openFWPA debera tener presente, en todo momento, la
realizacin de pruebas unitarias de todos sus componentes relevantes. De esta forma se tiene una batera
de pruebas que pueden ejecutarse en cualquier momento como pruebas de regresin. Debiera disponerse
de un proceso en el servidor que se encargue de lanzar tales pruebas un nmero determinado de veces y
genere un informe con los resultados de la ejecucin de las pruebas.
Todo esto se ha tenido en cuenta a la hora de desarrollar el openFWPA y se proporciona una infraestructura
basada en JUnit [11] que se puede utilizar a tal efecto. Esta infraestructura base para la implementacin
de pruebas unitarias se empaqueta en la librera de herramientas del openFWPA: fwpa-toos.jar
Se proporciona un conjunto de clases plantilla para facilitar la implementacin de pruebas unitarias. Estas
clases de prueba se pueden clasificar en dos grandes grupos:
Pruebas locales. Se ejecutan en el propio PC de desarrollo.
Pruebas en contenedor. Se ejecutan en una aplicacin web, sobre el servidor de aplicaciones. El
openFWPA proporciona soporte para la implementacin de pruebas unitarias en contenedor, utilizando
la librera Cactus, de Apache.
106
Pruebas
PrincastJspTestCase. Se utiliza para implementar pruebas para pginas JSP o para etiquetas
(Custom Tags). Este tipo de pruebas se ejecuta en contenedor.
PrincastFilterTestCase. Se utiliza para pruebas unitarias de filtros (Servlet Filter). Este tipo
de pruebas se ejecuta en contenedor.
PrincastServletTestCase. Se utiliza para probar Servlets. Este tipo de pruebas se ejecuta
en contenedor.
PrincastWebTestCase. Se utiliza para probar la navegacin Web, envo y respuesta de
formularios, etc. Este tipo de pruebas se ejecuta en contenedor.
Convenciones a seguir
A la hora de implementar las diferentes pruebas unitarias se recomienda que las clases
sigan el convenio de nombrado masivamente seguido que establece que stas deben llamarse
<nombre_de_la_clase>Test.java.
En cuanto a la signatura de los mtodos que implementen los diferentes casos de pruebas, se suele emplear:
public void test<nombre_caso_prueba> () {};
JUnit reconoce como casos de prueba todos aquellos mtodos que sigan esta convencin de nombrado.
En la imagen siguiente se puede ver el informe detallado de una de las pruebas pertenecientes a la batera
de pruebas anterior.
107
Pruebas
Atencin
Desde la versin 1.5 del openFWPA, las pruebas unitarias de acceso a base de datos estn basadas
en el framework Spring.
El hecho de que este tipo de pruebas unitarias est basado en Spring supone que:
1. Es necesario declarar los DataSources que se van a utilizar en un fichero de definicin de beans
de Spring.
2. No es necesario controlar las transacciones que se realicen durante el test.
3. La clase de prueba es, a su vez, un bean de Spring. La clase de pruebas realizar autowiring por tipo
para todas sus propiedades setter. Es decir, para todos los setter que tenga la clase de pruebas busca, en
los ficheros de definicin de beans, un bean que encaje en el tipo de la propiedad y se lo asigna.
Atencin
Es muy importante tener en cuenta que el autowiring de beans con la clase de test se realiza
por tipo. Si ms de un bean encaja en el tipo de la propiedad puede producirse un error. El
DataSource a utilizar tambin se asigna a la clase de test utilizando autowiring, por lo tanto,
nicamente se puede declarar un DataSource en los ficheros de definicin de beans.
Para implementar tests extendiendo PrincastDatabaseTestCase, se seguirn todas las normas
y convenciones definidos para implementar casos de prueba estndar (Ver Convenciones a seguir).
Adems, se debe implementar el mtodo:
getDataSourceFile(), que devuelve el path donde se encuentra el fichero de defincin de beans
en el que se declara el DataSource a utilizar. Por ejemplo:
108
Pruebas
}
La clase base PrincastDatabaseTestCase proporciona las siguientes utilidades:
logger. Como todos los tests, se dispone de un atributo, de nombre logger, que permite acceder
al log de la clase de prueba.
getDataSource(). Este mtodo permite obtener la fuente de datos (DataSource) que conecta
con la base de datos. Este origen de datos se puede asignar, posteriormente, a los objetos que se vayan
a probar.
jdbcTemplate. La clase base para pruebas en base de datos dispone de un atributo, de la clase
org.springframework.jdbc.core.JdbcTemplate, que permite ejecutar, directamente
consultas contra la base de datos. Para ms informacin sobre cmo usar esta clase, consltese el manual
de referencia del framework Spring.
onSetUpInTransaction(). Extendiendo este mtodo, se pueden realizar todo tipo de
actualizaciones (inserciones, borrados, etc.) que sean necesarios para la posterior ejecucin de la prueba.
Todas las actualizaciones que se realicen estarn disponibles, nicamente durante la ejecucin del test.
No quedar rastro de estas operaciones en la base de datos.
Este mtodo sustituye al fichero DataSet XML de dbUnit. Si se utiliza este mtodo, y se quiere utilziar
tambin dbUnit, se debe hacer una llamada a super.onSetUpInTransaction().
onSetUpBeforeTransaction(). Este mtodo es anlogo al anterior con al diferencia de que las
actualizaciones realizadas en este mtodo s que son persistentes en la base de datos.
Un ejemplo de uso de estos elementos es el que sigue:
protected void onSetUpInTransaction() throws Exception {
jdbcTemplate.execute("insert into foo values ('1', 'foo foo')");
}
con
la
clase
1. Escribir el fichero XML (DataSet XML) de datos para la prueba. El fichero DataSet XML est
definido por la librera DBUnit y tiene el formato que se muestra en el siguiente ejemplo:
<dataset>
<PROPS id='1' value='pepe'/>
<PROPS id='2' value='ramon'/>
</dataset>
Cada registro de la base de datos se escribir en una etiqueta independiente, indicando, el valor de cada
campo, como atributos de dicha etiqueta.
En estos test siempre se puede suponer que la base de datos est cargada con los registros definidos
en el fichero DataSet XML. Al finalizar los tests, la base de datos, siempre volver a su estado inicial
(antes de lanzar los test).
2. Extender el mtodo getDataSetXML() para especificar el path de dicho fichero. Este path siempre
debe ser relativo al classpath.
109
Pruebas
3. Indicar la operacin a realizarse por defecto para incializar los tests. Se debe extender el mtodo
getDatabaseSetupOperation(). Las operaciones soportadas son:
DatabaseOperation.CLEAN_INSERT
Elimina todo lo que haya en la tabla e inserta los datos del fichero
XML obtenido con el metodo getDataSetXMLFile().
DatabaseOperation.INSERT
DatabaseOperation.UPDATE
DatabaseOperation.REFRESH Inserta los registros del fichero XML que no existan en la base
de datos. Actualiza los que ya existan previamente.
DatabaseOperation.NONE
No se realiza ninguna operacin con la base de datos.
Estas operaciones solamente tienen efecto durante la ejecucin del test. No se realizarn cambios
permanentes en la base de datos.
Por defecto, este mtodo devuelve la operacin: DatabaseOperation.CLEAN_INSERT.
4. Configurar las conexiones (DataSource) como cualquier otro tipo de prueba unitaria de base de
datos.
(que
extiende
de
Atencin
La clase PrincastIBatisTestCase, existente en versiones del openFWPA anteriores
a la 1.5, cuyo objetivo era probar DAOs implementados con iBatis, ha sido eliminada del
openFWPA. El uso de la clase PrincastDAOTestCase permite probar cualquier tipo de
DAOs, independientemente de la tecnologa con que se implementen (por supuesto incluyendo
iBatis).
Todas las caractersticas propias de la superclase (PrincastDataBaseTestCase) se aplican a
PrincastDAOTestCase, incluyendo, por supuesto, la gestin y obtencin de DataSources.
Los objetos DAO a probar se deben declarar en un fichero de defincin de beans de Spring. La ubicacin
de este ficho se proprocionar extendiendo el mtodo: getDaoFile().
110
Pruebas
111
Pruebas
<beans>
<bean id="foo2" autowire="byType" class="es.princast.framework.facilities.dao.
</beans>
Con el mtodo getDataSourceFile() se define la ubicacin del fichero de declaracin de beans
donde se especifica el DataSource a utilizar. En este ejemplo, el fichero se llama datasourcebeans.xml, est ubicado en el classpath y su contenido es el que sigue:
<beans>
<!-- DataSource para Test -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManager
<property name="driverClassName"><value>org.gjt.mm.mysql.Driver</value>
<property name="url"><value>jdbc:mysql://localhost/foo</value></propert
</bean>
<!-- Es necesario tambin definir un TransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.Da
<property name="dataSource"><ref bean="dataSource"/></property>
</bean>
</beans>
Todas las operaciones realizadas sobre la base de datos en este mtodo ser unicamente visibles a
lo largo del test.
Finalmente, se puede realizar el test normalmente utilizando los beans declarados en los ficheros
correspondientes.
112
Pruebas
loadPropertiesFile
loadPlugin
configureObject
ConfigurableObjectTestingHelper.configureObject(props, CounterFactory.getFac
Pruebas de filtros
Para facilitar las pruebas unitarias de filtros, la clase base PrincastFilterTestCase, ofrece los siguientes
mtodos de utilidad:
113
Pruebas
assertPassingThruFilter() Sirve para verificar que el flujo que pasa por una cadena de filtros
no se ha interrumpido. No se ha realizado ni redirect, ni forward.
assertForwardTo()
Pruebas de validadores
Se ha incluido una clase base para facilitar la implementacin de pruebas de validadores de formularios.
Este tipo de pruebas se ejecutan en contenedor.
La clase base que debe ser extendida es PrincastValidatorTestCase. Esta clase pone a disposicin de sus
clases hijas los siguientes atributos:
request
errors
va
Estos tres atributos se pueden utilizar para realizar llamadas a los mtodos de validacin (sin necesidad
de disponer de instancias con valores reales).
Si se necesitan unos valores especficos para estos atributos, se pueden extender los mtodos
createValidatorAction() y createErrors(), de la clase base.
public void testValidateTwoFieldsOk() throws Exception {
FooForm form = new FooForm();
form.setDate1("21/11/2005");
form.setDate2("21/11/2005");
Field field = configureField();
assertTrue(FieldValidations.validateTwoFields(form, va, field, errors,
request));
}
Este mtodo abstracto debe ser extendido por las subclases para especificar
el nombre del informe. El nombre del informe se utilizar para encontrar el
fichero de defincin del mismo (con el convenio de nombrado <nombre del
informe>.xml) y para nombrar el fichero PDF resultante (con el convenio
<nombre del informe>.pdf).
getOutputDir()
114
Pruebas
getInputDir()
generateReport()
generatePDFReport()
115
Pruebas
Pruebas de Rendimiento
Las pruebas de rendimiento de aplicaciones web, se deben realizar, de forma automatizada, utilizando
herramientas inyectoras de carga. La herramienta recomendada para aplicaciones desarrolladas con el
openFWPA es OpenSta[22].
116