ATLAS Normativa Versión 1.17 (Corresponde a Versión de ATLAS 1.2.6) Arquitectura de Software Framework Atlas Normativa Hoja de Control Título NORMATIVA Documento de Referencia Responsable Arquitectura de Software Versión 1.17 Fecha Versión 08/05/2014 Registro de Cambios Versión Responsable del Causa del Cambio Cambio Fecha Área de Aplicaciones 1.0 Versión inicial del documento, se parte de la normativa creada antes de desarrollar el framework Especiales y Arquitectura de 24/05/2010 Software Modificaciones sobre versión 1.0: - Norma: JSFHttpSession: Se cambia la redacción de la norma ya que podía malinterpretarse. - Norma: JSFNavegacion: Se modifica la nomenclatura de la clase para el caso de haber varios bloques funcionales. Área de Aplicaciones Especiales y 1.1 - - Norma: SNDependencias: Se modifica la norma para permitir varios ficheros de contexto. Arquitectura de 02/07/2010 Software Norma: DAODependencias: Nueva norma sobre versión 1.0. Se incluye una norma para la nomenclatura del fichero de contexto de los DAOS. Aunque esta norma no existía el arquetipo ya venía con esta nomenclatura. Modificaciones sobre versión 1.1: 1.2 - applicationContext-database.xml: Ya no se anotan las clases, se hace por paquete con la propiedad packagesToScan. EntornoEjecucion: Se cambia de la jdk de Sun a la jRockit. Área de Aplicaciones Especiales y Arquitectura de 17/08/2010 Software Se modifica la versión de la jdk y versión de weblogic 1.3 Área de Aplicaciones Modificaciones sobre versión 1.2: - Apartado 6.3.5: Se incluye un aviso al 2 de 198 Especiales y 31/08/2010 Framework Atlas Normativa Versión Responsable del Causa del Cambio Cambio final del apartado. 1.4 Fecha Arquitectura de - Apartado 6.4.3: Nueva implementación en la clase Cliente de los métodos equals / hashcode / toString. Se añade una recomendación a este respecto - Apartado 6.4.4: Se incluye información sobre BaseDAO y se actualiza el código correspondiente. Se adaptan las normas según esta nueva implementación. Se amplia la norma ADCatalogos para indicar que no se debe borrar en cascada sobre un catálogo. - Apartado 6.4.4.1: Nuevo apartado y norma ADNamedParameter para uso obligatorio de ‘named parameters’ en consultas de BBDD. - Apartado 6.4.6.1: Se elimina un texto ‘El siguiente ejemplo …’ en el apartado 6.4.6.1 que no tenía lugar ahí ya que está prohibido su uso. - Norma Arquetipos: Añadido a la norma requisito para arquetipo de proyectos. - Apartado 9.5: Nueva regla INTNomClient Se incluyen las siguientes buenas practicas: - JSFMessages - JSFStoreError - JSFAtlasFacesUtils - JSFAccesoMessages Que se refieren a la utilización de la clase AtlasFacesUtils en distintos casos. Software Área de Aplicaciones Especiales y Arquitectura de 2/11/2010 Software Modificaciones sobre versión 1.4: - Apartado 6.3.3: Se incluye nueva norma SNSpringLIB sólo para módulos de tipo librería - Apartado 6.3.3: Se modifica la norma SNDependencias indicando que no aplica a módulos de tipo librería 1.5 - - Apartado 6.4.2.3: Se modifica la norma DAODependencias indicando que no aplica a módulos de tipo librería Apartado 7: Se modifica la norma CONFNomenclatura sustituyendo nombre de proyecto por nombre de módulo. 3 de 198 Área de Aplicaciones Especiales y Arquitectura de Software 10/01/2011 Framework Atlas Normativa Versión Responsable del Causa del Cambio Cambio - Apartado 7: Se incluyen dos nuevas normas sobre las particularidades en la configuración de los módulos de tipo librería. - Apartado 5: Nueva norma VERSIONADO. - Apartado 9.7.1: Se modifica la normativa de acceso a Crystal Reports. Se modifica la norma SOLRptConf. Fecha Modificaciones sobre versión 1.5: - Apartado 5: Se actualiza gráfico de módulos para eliminar el sufijo intra. El framework Atlas permite que el mismo módulo sirva para intranet e Internet por lo tanto este sufijo ya no tiene sentido. Área de Aplicaciones Especiales y 1.6 - Apartado 6: Modificada norma JSFJavascript. - Arquitectura de 25/04/2011 Software Apartado 7: Modificada norma CONFEntorno. - Apartado 10.1: Se incluye la posibilidad de excluir la comprobación de normas en la herramienta de validación. Modificaciones sobre versión 1.6: - Apartado 8.1: Nueva norma SBAutoPerfiles - Nuevo Apartado 6.3.6: Ficheros temporales. - Apartado 6.3.6: Nueva norma SNFicherosTemporales y nueva buena 1.7 práctica SNNomFicheroTemporal - Apartado 6.2.1: Nuevas buenas prácticas JSFGet y JSFEL. - Apartado 6.2.1.9: Modificada buena práctica JSFAjaxLimite. - Apartado 11.1 Tipos de pruebas: Incluida nuevo tipo de prueba para las 4 de 198 Área de Aplicaciones Especiales y Arquitectura de Software 21/09/2011 Framework Atlas Normativa Versión Responsable del Causa del Cambio Cambio Fecha pruebas de los servicios web. Por lo tanto se incluye una nueva norma TestServicioWeb - Se actualiza el nombre del Area (Area de Aplicaciones Especiales y Arquitectura Software) Modificaciones sobre versión 1.7: - Apartado 6.4.4: Modificado código fuente de clases BaseDAO y BaseDAOImpl 1.8 - Apartado 6.3.2: Incluidas en los arquetipos las clases BaseService y Área de Aplicaciones Especiales y Arquitectura de 24/02/2012 Software BaseServiceImpl. Añadida la nueva buena pràctica ADBaseService - Apartado 6.2.1: PAGINAS JSF: Se eliminan las referencias a la librería de componentes de JSF Tomahawk, ya que ha dejado de utilizarse. - Apartado 6.2.3 Configuracion de JSF: Se incluye la posibilidad de usar anotaciones. Área de Aplicaciones - Nuevo Apartado 6.2.3.5: Anotaciones. - Buena Práctica JSFMessages: Se 1.9 cambia el uso de t:message a h:message. - Buena Práctica JSFStoreError: Se cambia el uso de t:message a h:message. - Buena Practica JSFSavestate Se sustituye el uso del componente savestate de tomahawk por una etiqueta propia de atlas atlas:guardarEstado - Nuevo apartado 6.2.1.10: Ayuda contextual. 1.10 - Nueva buena practica JSFAYUDA - Modificado apartado 6.2.1.7 Uso de 5 de 198 Especiales y Arquitectura de Software 14/06/2012 Framework Atlas Normativa Versión Responsable del Causa del Cambio Cambio Fecha Javascript para hablar de Jquery. - Nueva regla JSFJQuery - Nuevo apartado 10.3 Generación automática de código - Apartado 6.3.1 Modificada norma SNFacade para quitar que la fachada debe gestionar la transaccionalidad. Nueva buena practica SNFacadeWS que recomienda no generar fachada en los servicios web. - Apartado 6.2.1.8: Normas de estilo Nueva norma JSFIFRAME que prohibe el uso de IFRAMES. - Apartado 10: Servicios Web. Nuevo apartado. Se añaden una nueva norma WSSECURITY. - Apartado 9.3: Modificado Servicio de Certificados digitales pasa a llamarse Servicio de Criptografía. Se modifica el texto de la norma SICert. 1.11 Apartado 8.1: Se incluye información sobre los mecanismos implementados 01/03/2013 para cumplir los requisitos mínimos del Esquema Nacional de Seguridad en el acceso a las aplicaciones. Se crea nueva norma SBENS. - Apartado 9.7.10: Envío de SMS. Se modifica para que en lugar de invocar al servicio web de mentes se utiliza un servicio propio de Atlas llamado Servicio de envío de SMS. - Apartado 9.7.11: Visor Mapas. Nuevo componente. 1.12 - Apartado 12: Entrega. Se cambia Unidad 6 de 198 25/03/2013 Framework Atlas Normativa Versión Responsable del Causa del Cambio Cambio Fecha de Recepción de Aplicaciones por Unidad de Paso a Producción y he informa acerca de la creación de repositorio de subversion. - Indice: Se regenera el indice ya que no estaba bien. 1.13 - Apartado 6.4.3.2: Se elimina la regla ADLOB. - Apartado 9.7.8 XML sólo lectura - Apartado 6.2.1.8: Se modifica el nombre 29/05/2013 de la regla JSFAccesiblidad para incluir la i que faltaba (JSFAccesibilidad). - Apartado A1.1: Se actualiza el nombre de la regla en la lista de reglas. - Apartado 6.4.5: Modificada norma ADStoredProc, se permite el uso de CallableStatement en ciertos casos 1.14 - Apartado 6.4.4: Modificada la norma 04/12/2013 ADSQLUso, si se permiten sentencias SQL-DML - Apartado 6.2.2.3 Inicialización de los Beans (@PostContruct) - Apartado 6.2.1.6 Nueva norma JSFCustomMenu - Apartado 9.7.10 Añadida configuración del environment.properties para envío de correo 1.15 - No estaban bien en el PDF generado los marcadores a los manuales - 18/12/2013 Nueva norma ADUsoAtlasLegacy para requerir autorización excepcional para el 1.16 uso de la anotación @AtlasLegacy - Norma JSFPOB: Modificadas versiones 7 de 198 19/12/2013 Framework Atlas Normativa Versión Responsable del Causa del Cambio Cambio Fecha mínimas de los browsers requeridos. - Norma NOMPaquetes: Se aceptan números en le nombre de los paquetes. - Norma ADIdentificador. Se modifica para incluir una excepción en el caso de tablas para relaciones de muchos a muchos. - Apartado 10 Herramientas: Actualizado para comtemplar el uso del servicio SAVT en lugar de la herramienta de validación HVAL. 1.17 EntornoEjecucion: A partir de la versión 1.2.6 de ATLAS se realizan los despliegues en Tomcat no en Weblogic. También cambia la JDK. 8 de 198 08/05/2014 Framework Atlas Normativa Índice 1 INTRODUCCION ................................................................................................................................................. 12 1.1 1.2 AUDIENCIA OBJETIVO ............................................................................................................................... 12 CONOCIMIENTOS PREVIOS ...................................................................................................................... 13 2 DESCRIPCION ..................................................................................................................................................... 15 3 PORTAL PARA EL DESARROLLO DE APLICACIONES ........................................................................... 17 4 ENTORNO DE DESARROLLO ......................................................................................................................... 18 5 PROYECTOS, MODULOS Y ARQUETIPOS .................................................................................................. 20 5.1 5.2 5.3 5.4 6 MODULO WEB .............................................................................................................................................. 23 MODULO LIBRERÍA .................................................................................................................................... 24 MODULO SERVICIO WEB........................................................................................................................... 25 MODULO BATCH ......................................................................................................................................... 26 ARQUITECTURA ................................................................................................................................................ 26 6.1 CONSIDERACIONES GENERALES ............................................................................................................ 26 6.2 PRESENTACION ........................................................................................................................................... 28 6.2.1 PAGINAS JSF......................................................................................................................................... 30 6.2.1.1 6.2.1.2 6.2.1.3 6.2.1.4 6.2.1.5 6.2.1.6 6.2.1.7 6.2.1.7.1 6.2.1.7.2 6.2.1.7.3 6.2.1.7.4 6.2.1.8 6.2.1.9 6.2.1.10 6.2.2 6.2.2.1 6.2.2.2 6.2.2.3 6.2.3 6.2.3.1 6.2.3.2 6.2.3.3 6.2.3.4 6.2.3.5 Manejo de eventos ............................................................................................................................................... 33 Recuperación de parámetros ................................................................................................................................ 35 Validadores .......................................................................................................................................................... 37 Conversores ......................................................................................................................................................... 39 Internacionalización ............................................................................................................................................. 39 Estructura y decoración de la página.................................................................................................................... 41 Uso de javascript .................................................................................................................................................. 46 Uso de JQuery en páginas JSF ......................................................................................................................... 46 Uso del objeto JQuery ..................................................................................................................................... 47 Uso de ready en sustitución del evento onLoad............................................................................................... 47 Localización de elementos por Id .................................................................................................................... 47 Normas de estilo .................................................................................................................................................. 48 Interfaces ricas de usuario (RIA) ......................................................................................................................... 49 Ayuda contextual ............................................................................................................................................. 52 MANAGED BEANS .............................................................................................................................. 53 Manejo de excepciones ........................................................................................................................................ 57 Navegación .......................................................................................................................................................... 59 Inicialización de los Beans (@PostContruct) ....................................................................................................... 61 CONFIGURACIÓN DE JSF ................................................................................................................... 61 faces-config.xml ................................................................................................................................................... 61 faces-managed-beans.xml .................................................................................................................................... 62 faces-navigation.xml ............................................................................................................................................ 64 Archivos de configuración adicionales y web.xml ............................................................................................... 67 Anotaciones ......................................................................................................................................................... 67 6.2.4 USO DE LA SESIÓN ............................................................................................................................. 69 6.3 SERVICIOS DE NEGOCIO ........................................................................................................................... 70 6.3.1 FACHADA.............................................................................................................................................. 72 6.3.2 SERVICIOS ............................................................................................................................................ 76 6.3.3 INYECCION DE DEPENDENCIAS ...................................................................................................... 81 6.3.4 MANEJO DE EXCEPCIONES .............................................................................................................. 84 6.3.5 TRANSACCIONALIDAD ..................................................................................................................... 87 6.3.6 FICHEROS TEMPORALES................................................................................................................... 92 6.4 ACCESO A DATOS ....................................................................................................................................... 94 6.4.1 DATASOURCE Y SESIONES DE HIBERNATE ................................................................................. 97 6.4.2 CONFIGURACIÓN ................................................................................................................................ 98 6.4.2.1 6.4.2.2 6.4.2.3 6.4.3 6.4.3.1 enviroment.properties .......................................................................................................................................... 98 applicationContext-database.xml ......................................................................................................................... 98 applicationContext-dao.xml ............................................................................................................................... 100 ENTIDADES DE DOMINIO................................................................................................................ 102 Mapeo relacional................................................................................................................................................ 108 9 de 198 Framework Atlas Normativa 6.4.3.2 6.4.4 6.4.4.1 6.4.4.2 6.4.4.3 Tipos de datos BLOB y CLOB (LOB) ............................................................................................................... 110 DATA ACCESS OBJECTS .................................................................................................................. 112 Ejecución de consultas ....................................................................................................................................... 122 Manejo de excepciones ...................................................................................................................................... 124 Transaccionalidad .............................................................................................................................................. 124 6.4.5 LLAMADA A PROCEDIMIENTOS ALMACENADOS .................................................................... 126 6.4.5.1 LLAMADA A PROCEDIMIENTOS ALMACENADOS MEDIANTE HIBERNATE UTILIZANDO NAMED QUERIES .............................................................................................................................................. 126 6.4.5.2 LLAMADA A PROCEDIMIENTOS ALMACENADOS MEDIANTE CALLABLESTATEMENT . 127 6.4.6 CACHÉS EN HIBERNATE ................................................................................................................. 129 6.4.6.1 6.4.6.2 6.4.6.3 Las cachés de primer y segundo nivel ................................................................................................................ 129 Las cachés distribuidas....................................................................................................................................... 131 La caché de consultas ......................................................................................................................................... 132 7 CONFIGURACION ............................................................................................................................................ 133 8 SERVICIOS BASICOS ...................................................................................................................................... 138 8.1 8.2 8.3 8.4 9 SERVICIO DE AUTENTICACION Y AUTORIZACION ........................................................................... 138 COMPONENTES DE PRESENTACION ..................................................................................................... 143 SERVICIO DE TRAZAS .............................................................................................................................. 144 SERVICIO DE AUDITORIA DE SEGURIDAD .......................................................................................... 146 INTEGRACION .................................................................................................................................................. 147 9.1 SERVICIO DE GESTIÓN DOCUMENTAL ................................................................................................ 148 9.2 SERVICIO DE PLANIFICACION ............................................................................................................... 149 9.3 SERVICIO DE CRIPTOGRAFIA................................................................................................................. 150 9.4 SERVICIO DE BUSSINESS INTELLIGENT .............................................................................................. 151 9.5 SERVICIO DE INVOCACIÓN DE SERVICIOS WEB ............................................................................... 153 9.6 SERVICIO DE PROCESOS DE NEGOCIO ................................................................................................. 154 9.7 OTRAS SOLUCIONES ................................................................................................................................ 155 9.7.1 REPORTING ........................................................................................................................................ 156 9.7.2 COMPOSICION DE DOCUMENTOS................................................................................................. 158 9.7.3 GESTION DE DOCUMENTOS EXCEL ............................................................................................. 160 9.7.4 GESTION DE DOCUMENTOS PDF ................................................................................................... 161 9.7.5 GENERACION DE GRAFICOS .......................................................................................................... 162 9.7.6 MANIPULACION DE ARCHIVOS MULTIMEDIA .......................................................................... 163 9.7.7 ACCESO A PLATAFORMA Y DISPOSITIVOS LOCALES ............................................................. 164 9.7.8 XML SÓLO LECTURA ....................................................................................................................... 165 9.7.9 XML LECTURA Y ESCRITURA ........................................................................................................ 165 9.7.10 ENVIO DE CORREO ........................................................................................................................... 168 9.7.11 ENVIO DE SMS ................................................................................................................................... 172 9.7.12 VISOR DE MAPAS .............................................................................................................................. 173 9.7.13 SERVICIOS WEB ................................................................................................................................ 174 10 HERRAMIENTAS .......................................................................................................................................... 175 10.1 VALIDACION DE NORMATIVA............................................................................................................... 175 10.2 REVISION DE CODIGO ESTATICO .......................................................................................................... 176 10.3 GENERACION AUTOMÁTICA DE CODIGO ........................................................................................... 178 10.3.1 ACCESO A DATOS ............................................................................................................................. 180 10.3.2 SERVICIOS DE NEGOCIO ................................................................................................................. 181 10.3.3 PRESENTACION ................................................................................................................................. 182 11 11.1 11.2 11.3 PRUEBAS ........................................................................................................................................................ 185 TIPOS DE PRUEBAS ................................................................................................................................... 185 PLAN DE PRUEBAS.................................................................................................................................... 190 DOCUMENTACION DEL CODIGO ........................................................................................................... 191 12 ENTREGA ....................................................................................................................................................... 192 13 ENLACES RELACIONADOS ...................................................................................................................... 193 A1.1 NORMAS ..................................................................................................................................................... 194 10 de 198 Framework Atlas Normativa A1.2 BUENAS PRACTICAS .............................................................................................................................. 198 11 de 198 Framework Atlas Normativa 1 INTRODUCCION La presente guía presenta el framework de desarrollo para todas las aplicaciones de la Comunidad de Madrid y establece la normativa a cumplir en estos desarrollos. El framework se ha denominado Atlas y los desarrollos deben cumplirlo en su última versión públicada. En esta normativa se incluyen dos tipos de indicaciones para el correcto desarrollo de aplicaciones: Normas: Son requisitos de obligado cumplimiento, y se encuentran definidas dentro de una caja o NORMA de color azul: NombreDeNorma Contenido de la norma. Buenas prácticas: Son recomendaciones para el desarrollo. No son de obligado cumplimiento o aunque para un correcto funcionamiento se recomienda cumplirlas siempre que sea posible. Se 1.1 PRACTICA BUENA encuentran definidas dentro de una caja de color NombreDeBuenaPractica Contenido de la Buena Práctica. AUDIENCIA OBJETIVO Este documento va dirigido a jefes de proyecto, analistas y desarrolladores de proyectos que utilicen el framework Atlas. 12 de 198 Framework Atlas Normativa 1.2 CONOCIMIENTOS PREVIOS Para un completo entendimiento del documento, el lector deberá tener conocimientos previos sobre las tecnologías que forman parte del framework. A continuación se muestra una tabla con las distintas tecnologías utilizadas por cada uno de los elementos del framework. Servicio Entorno de Desarrollo Arquetipos Arquitectura Servicios Básicos Integración Tecnología Respositorio maven Artifactory Gestión del proyecto Maven IDE de desarrollo Eclipse Servidor de Aplicaciones Antes de ATLAS 1.2.6: - Oracle Weblogic 10.3.3 A partir de ATLAS 1.2.6: - Apache Tomcat 7.0.39 Motor de base de datos Oracle Control de versiones Subversión Integración continua Cruise Control Maquina virtual java Antes de ATLAS 1.2.6: - JRockit JDK 1.6.0_20 A partir de ATLAS 1.2.6: - Oracle JDK 1.6.0_29 Generación de nuevos proyectos Maven y Eclipse Presentación JSF, RichFaces, Ajax4JSF, Facelets Servicios Spring Acceso a Datos Hibernate Servicios Web Axis 2 Servicio de Autenticación y Autorización Spring Security Componentes de Presentación JSF, RichFaces, Ajax4JSF, Facelets Servicio de Trazas Spring AOP y Log4J Servicio de Auditoria Spring AOP e Hibernate Servicio de Gestión Documental Documentum 6.0 Servicio de Planificación Control M Servicio de ASF ASF 3.5 13 de 198 Framework Atlas Normativa Otras soluciones Herramientas Servicio de Bussiness Inteligent SAP Bussiness Objects XI 3.1 Servicio de Invocación de Servicios Web Axis 1.4 Servicio de Procesos de Negocio Oracle BPM 10 Documentos PDF IText Reporting Crystal Reports 2008 Composición de documentos Velocity Documentos Excel Apache POI Generación de Gráficos JFreechart Archivos multimedia Java Media FrameWork API (JMF) Acceso a dispositivos locales Applet XML Jaxb Envío de correo Java Mail Envio de SMS Servicio web mentes_ws Monitorización JMS y JMX Pruebas de carga JMeter Pruebas de aceptación Selenium Pruebas unitarias JUnit Validación normativa Maven Validación estática de código Checkstyle y PMD 14 de 198 Framework Atlas Normativa 2 DESCRIPCION El framework Atlas es un conjunto de componentes de software para simplificar el desarrollo de las aplicaciones, ya que implementan aquellos requisitos que son compartidos por muchas de ellas. Otra parte del framework es la normativa que garantiza la homogeneidad de los desarrollos y vela por conseguir un código de calidad. A continuación se muestra una imagen que contiene los distintos elementos del framework. o Entorno de desarrollo: Herramientas necesarias para el desarrollo de aplicaciones con el framework Atlas o Arquitectura: Son los pilares que constituyen la base fundamental del Framework (JSF, Spring e Hibernate) o Servicios Básicos: Servicios de uso común en la mayoría de los aplicaciones 15 de 198 Framework Atlas Normativa o Arquetipos: Generadores de nuevos proyectos con la estructura básica de un proyecto Atlas (plantillas de partida para el arranque de nuevos proyectos). o Integración: Integración con otras tecnologías como Documentum, BPM, etc o Herramientas: Utilidades de testing, validación y monitorización de aplicaciones. o Normativa: Normativa de obligado cumplimiento para el desarrollo de aplicaciones con el framework. 16 de 198 Framework Atlas Normativa 3 PORTAL PARA EL DESARROLLO DE APLICACIONES Toda la documentación y recursos del framework Atlas se encuentra accesible en el portal para el desarrollo de aplicaciones de la Unidad de Arquitectura y Soporte de Aplicaciones en la url: http://gestiona.madrid.org/arquitecturasw. Esta web es el canal de comunicación de la Unidad de Arquitectura y Soporte de Aplicaciones hacia los proveedores. Cada vez que se publica algo en la web se incluye una noticia indicando la actualización que se ha realizado. El proveedor por lo tanto tiene la responsabilidad de conectarse asiduamente a esta web para estar al corriente de las modificaciones. Las consultas relacionadas con el desarrollo de aplicaciones se deben dirigir a la Unidad de Arquitectura y Soporte de Aplicaciones a través del portal para el desarrollo en el apartado “Contactar con Arquitectura” en la página de Inicio. 17 de 198 Framework Atlas Normativa 4 ENTORNO DE DESARROLLO Las siguientes imagenes muestran los elementos a grandes rasgos Entorno Desarrollo Proveedor Eclipse + plugin Maven (+ plugin subversion) Maven Base de Datos (Oracle) Repositorio Local Servidor de Aplicaciones (WebLogic) Entorno ICM Artifactory Arquetipos Portal para el desarrollo web jar Subversion batch service Artefactos docum CruiseControl Oracle Weblogic En el manual ATLAS_MUS_Preparacion_Entorno_Desarrollo detallan los productos y versiones de los mismos que son necesarios para el desarrollo de aplicaciones con el framework Atlas. Por otra parte se indica como preparar el entorno para comenzar a desarrollar aplicaciones. 18 de 198 Framework Atlas Normativa Entorno El proveedor deberá replicar en sus instalaciones el entorno de desarrollo de ICM en cuanto a productos y versiones de los mismos. Las aplicaciones deberán desarrollarse teniendo en cuenta los siguientes aspectos relativos al entorno: · En el entorno de producción podrán ser desplegadas en modo cluster, tanto en varias instancias de un mismo o diferentes servidores de aplicaciones. NORMA · No deben usar funcionalidades o tecnologías dependientes del sistema operativo sin la previa aprobación de ICM. · No deben usar funcionalidades propietarias del servidor de aplicaciones, sin la previa aprobación de ICM, para garantizar al máximo la portabilidad entre servidores de aplicaciones. · Los ficheros generados por las aplicaciones y que se necesiten dejar en disco se ubicarán según se indique en un parámetro del fichero de configuración. Esta ubicación corresponderá con un directorio compartido por las distintas maquinas que compongan el cluster. · Las aplicaciones web y servicios web se van a ejecutar en varias maquinas virtuales por lo tanto los objetos que se dejen en la memoria de la maquina virtual no estarán replicados en las diferentes instancias. EntornoEjecucion NORMA Las aplicaciones Atlas anteriores a la versión 1.2.6 se desplegarán en el servidor de aplicaciones Oracle Weblogic 10.3.3 y se ejecutarán con la JDK JRockit 1.6.0_20. A partir de la versión 1.2.6 se desplegarán en el servidor de aplicaciones Apache Tomcat 7.0.39 y se ejecutarán con la JDK Oracle 1.6.0_29. El codigo entregado deberá estar probado con esta versión de JDK y funcionar correctamente en este servidor de aplicaciones. 19 de 198 Framework Atlas Normativa 5 PROYECTOS, MODULOS y ARQUETIPOS Las aplicaciones de la Comunidad de Madrid se definirán en el marco de un proyecto, denominando a las distintas aplicaciones que se desarrollen para un proyecto módulos. Por lo tanto podemos decir que un proyecto es un conjunto de módulos. Todos los proyectos de la Comunidad de Madrid tienen un nombre como máximo de 4 letras que identifican al proyecto y que van a ser fundamentales en la nomenclatura de muchos de los elementos del proyecto por lo tanto es fundamental disponer de este identificador antes de abordar ningún tipo de desarrollo. A continuación se muestra la estructura de carpetas sobre como se debe crear un proyecto y sus correspondientes módulos. PROYECTO XXXX MODULOS XXXX_MODD BASE DATOS XXXX_APP APP WEB XXXX_WS SERVICIO WEB XXXX_BATCH XXXX_LIB BATCH LIBRERIA Atención xxxx se corresponde con el nombre del proyecto y como podemos ver este nombre forma parte del nombre de los módulos. 20 de 198 Framework Atlas Normativa Observar que el separador utilizado en el nombre de los módulos es el guión bajo. Dentro de los módulos de un proyecto nos podemos encontrar con módulos del framework Atlas o con otro tipo de módulos (por ejemplo un módulo de Documentum, un módulo de base de datos, etc). Los distintos tipos de módulos que podemos implementar con el framework Atlas son: o Módulo web: Para implementar aplicaciones de tipo web. o Módulo librería: Para implementar librerías (jars). o Módulo servicio web: Para implementar servicios web. o Módulo batch: Para implementar aplicaciones o procesos que se ejecutarán en modo batch. Los arquetipos son plantillas de proyectos Maven que se utilizarán como punto de partida de cualquier módulo desarrollado con el framework Atlas. Antes de crear ningún módulo debemos crear el propio proyecto, partiendo de un arquetipo de proyecto que crea la estructura necesaria. NORMA Arquetipos Todo proyecto debe partir obligatoriamente de un arquetipo de tipo proyecto (atlasfrmarquetipos-generador-proyecto). El desarrollo de cualquier módulo de un proyecto serán submódulos de éste, que obligatoriamente se deben hacer partiendo del arquetipo correspondiente al módulo en cuestión. Actualmente se dispone de los siguientes arquetipos dentro del framework Atlas: ARQUETIPOS DESCRIPCION atlasfrm-arquetipos- Genera un proyecto base de partida generador-proyecto para cualquier aplicación de ATLAS. Tipo de módulo Proyecto de inicio Cualquiera de los módulos del proyecto deberán ser submódulos de éste. atlasfrm-arquetipos- Genera un proyecto Maven generador-web preparado para el desarrollo de módulos web con JSF, Spring e Hibernate. 21 de 198 Módulo web Framework Atlas Normativa atlasfrm-arquetipos- Genera un proyecto Maven de tipo generador-servicioweb web listo para desplegar un servicio Módulo servicio web web con Axis2, Spring e Hibernate atlasfrm-arquetipos- Genera un proyecto Maven de tipo generador-documentumweb web listo para ser utilizado con Módulo web aplicaciones que se integren con Documentum atlasfrm-arquetipos- Genera un proyecto Maven generador-batch preparado para el desarrollo de Módulo batch módulos de tipo batch, con sus scripts de ejecución preparada para distribución. Contiene configuraciones de Spring e Hibernate atlasfrm-arquetipos- Genera un proyecto Maven generador-jar preparado para el desarrollo de Módulo librería módulos de tipo librería (jar). NORMA NORMA NOMArchivo Los nombres de los archivos sólo pueden estar formados por caracteres [a-z] y guiones medio y bajo, no pudiéndose utilizar caracteres acentuados ni la letra eñe. En los nombres de los archivos pueden utilizarse letras mayúsculas cuando sea conveniente. NOMPaquetes Los nombres de los paquetes de clases Java sólo pueden estar formados por caracteres [a-z] en minúscula y dígitos [0-9], no pudiéndose utilizar caracteres acentuados ni la letra eñe. NORMA VERSIONADO Todos los proyectos deben versionarse utilizando los mecanismos de versionado que ofrece Maven, utilizando la etiqueta <version> que se encuentra dentro del fichero pom.xml. Siempre que se realicen modificaciones sobre un módulo y se proceda a una entrega (en cualquier entorno) se ha de modificar el número de versión. El número de versión estará formado por tres digitos. Ejemplo 1.0.3 22 de 198 Framework Atlas Normativa 5.1 MODULO WEB Para el desarrollo de módulos web el framework Atlas incluye un arquetipo web que se deberá utilizar para la implementación del mismo. Para obtener más información sobre el arquetipo web consultar el manual ATLAS_MUS_Arquetipo_Web. IMPLWEB Para implementar un módulo/aplicación web se creará un módulo partiendo del arquetipo web y NORMA con la siguiente nomenclatura: xxxx_yyyy donde xxxx se corresponde con el nombre del proyecto (max 4 caracteres) yyyy se corresponde con el nombre descriptivo del web (No se puede poner en este nombre el sufijo “web” ya que se la va a incluir automáticamente al generar el módulo desde el arquetipo) 23 de 198 Framework Atlas Normativa 5.2 MODULO LIBRERÍA En algunos proyectos nos encontramos con que determinadas código debe de estar compartido por varios módulos del proyecto, en ese caso es necesario crear un nuevo módulo de tipo librería cuya dependencia NORMA será incluida en cada uno de los módulos que lo necesite. LIBCOMUN Cuando varios módulos de una o varias aplicaciones tengan código en común, ya sean métodos o clases, se deberá crear una librería de clases que servirá para compartir el código común anterior. Para el desarrollo de módulos librería el framework Atlas incluye un arquetipo jar que se deberá utilizar para la implementación del mismo. Para obtener más información sobre el arquetipo jar consultar el manual ATLAS_MUS_Arquetipo_Jar. IMPLLIB Para implementar un módulo librería se creará un módulo partiendo del arquetipo jar y con la NORMA siguiente nomenclatura: xxxx_lib_<yyyy> donde xxxx se corresponde con el nombre del proyecto (max 4 caracteres) yyyy se corresponde con el nombre descriptivo de la librería (Este nombre es opcional y debe distinguir a una librería de otra) 24 de 198 Framework Atlas Normativa 5.3 MODULO SERVICIO WEB Si existe la necesidad de que determinada funcionalidad de nuestra aplicación sea expuesta como un servicio web a otras aplicaciones se deberá crear un módulo específico que implemente el servicio web. El framework Atlas incluye un arquetipo de servicio web que se deberá utilizar para la implementación del mismo. Para obtener más información sobre el arquetipo de servicio web consultar el manual ATLAS_MUS_Arquetipo_Servicio_Web. IMPLWS Para implementar un servicio web se creará un módulo partiendo del arquetipo servicio web y con NORMA la siguiente nomenclatura: xxxx_ws_<yyyy> donde xxxx se corresponde con el nombre del proyecto (max 4 caracteres) yyyy se corresponde con el nombre descriptivo del servicio web (Este nombre es opcional y debe distinguir a un servicio web de otro) Para facilitar la integración de las aplicaciones clientes con este tipo de módulos es necesario proporcionales una librería cliente que permita invocar a los métodos publicados en el servicio web. Por lo tanto todos los módulos de tipo servicio web llevarán incluido un submódulo con la parte cliente necesaria para invocarlos. Este submódulo ya se encuentra en el arquetipo de servicio web. WSLibCliente Cada módulo de tipo servicio web debe incluir su correspondiente librería cliente que será un NORMA submódulo de tipo librería con la siguiente nomenclatura: xxxx_ws_<yyyy>_lib donde xxxx se corresponde con el nombre del proyecto (max 4 caracteres) yyyy se corresponde con el nombre descriptivo del servicio web (Este nombre es opcional y debe distinguir a un servicio web de otro) 25 de 198 Framework Atlas Normativa 5.4 MODULO BATCH Si existe la necesidad de que determinada funcionalidad de nuestra aplicación sea ejecute en modo batch se creará un módulo de tipo batch. El framework Atlas incluye un arquetipo de aplicaciones batch que se deberá utilizar para la implementación del mismo. Para obtener más información sobre el arquetipo de batch consultar el manual ATLAS_MUS_Arquetipo_Batch. IMPLBatch Para implementar un batch se creará un módulo partiendo del arquetipo batch y con la siguiente nomenclatura: NORMA xxxx_batch_<yyyy> donde xxxx se corresponde con el nombre del proyecto (max 4 caracteres) yyyy se corresponde con el nombre descriptivo del batch (Este nombre es opcional y debe distinguir a un programa batch de otro) 6 ARQUITECTURA El framework Atlas está basado fundamentalmente en tres tecnologías: JSF, Spring e Hibernate, que dan soporte a la implementación de las distintas capas de la aplicación: · Presentación: Java Server Faces (JSF) · Servicios: Spring · Acceso a datos: Hibernate Es fundamental el conocimiento por parte del desarrollador de estas tres tecnologías para poder llevar a cabo con exito el desarrollo de una aplicación con el framework Atlas. 6.1 CONSIDERACIONES GENERALES A continuación se exponen una serie de normas que son de carácter general para el código Java a desarrollar. 26 de 198 Framework Atlas NORMA REFLEXION NORMA GARBAGE NORMA MULTIHILO NORMA Normativa CLASESIGUALES No está permitido el uso de la Reflectividad (bien sea para buscar e invocar métodos o bien para acceder a atributos de una clase), a no ser que sea previamente autorizada por ICM. No está permitida la invocación directa al garbage collector mediante System.gc(), a no ser que tras consultarlo sea autorizada por ICM. En aplicaciones web o servicios web no pueden utilizarse hilos (threads) de ejecución distintos del hilo principal, a no ser que sea previamente autorizado por ICM. No puede haber dos clases que se llamen igual aunque estén en dos paquetes distintos. 27 de 198 Framework Atlas Normativa 6.2 PRESENTACION La lógica de presentación de la aplicación abarca todos los aspectos relacionados con la presentación de información al usuario final. La arquitectura de Atlas se basa principalmente en el uso de la tecnología Java Server Faces (JSF) para la creación de la lógica de presentación de la aplicación, si bien hay ciertas funcionalidades que son responsabilidad de esta capa y que emplean algún framework o producto adicionales. No obstante para ciertas tipologías de aplicaciones (aplicaciones meramente informativas, esto es, aquellas cuyo principal objetivo es mostrar información al usuario final) el uso de esta tecnología complica la integración con la infraestructura actual de ICM. Tal es el caso de las aplicaciones o sitios Web que dependen de “madrid.org” implementados mediante las herramientas que ofrece el gestor de contenidos corporativo de ICM (Fatwire). Este tipo de aplicaciones están fuera del alcance del presente documento, las cuales están sujetas a una normativa propia. La arquitectura de componentes que proporciona JSF, incluye: · · Un API para representar componentes de interfaz de usuario y gestionar: o Su estado. o Los eventos generados por la interfaz. o La validación y conversión de datos en el lado del servidor. o La definición de las reglas de navegación entre páginas. o Los aspectos relacionados con internacionalización y accesibilidad. o Los puntos de extensión para todas estas características. Librerías de etiquetas personalizadas para implementar la interfaz de las Java Server Faces y para asociar los componentes a los objetos del lado del servidor. Desde el punto de vista del desarrollo, una aplicación JSF es como cualquier otra aplicación web Java. Típicamente, una aplicación JSF incluye las siguientes piezas principales: · Un conjunto de páginas xhtml, que usarán etiquetas especiales definidas por la especificación JSF. · Un conjunto de managed beans, que no son más que JavaBeans que definen propiedades y funciones para los componentes de interfaz de usuario de las páginas. · Archivos de configuración para la aplicación, que definen las reglas de navegación y configuran los beans y los componentes a medida. · Un descriptor de despliegue (el fichero “web.xml” de toda aplicación web). · Los componentes y objetos a medida creados por el desarrollador para ampliar el modelo estándar (nuevos componentes visuales, validadores, conversores, etc.). 28 de 198 Framework Atlas Normativa La siguiente figura muestra el modelo de componentes que propone JSF, además se resumen las principales funcionalidades aportadas por dicha tecnología y que se encuentran incluidas en el presente documento. Funcionalidades Componentes de IU Integración con modelo de objetos Gestión de contexto de usuario Modelo de “renderizado” Manejo de eventos en el servidor Conversión de tipos y validación Navegación Internacionalización Modelo Managed Beans Vista Controlador Componentes UI FacesServlet Una de las mayores ventajas de JSF es que ofrece una clara separación entre presentación y comportamiento. JSF permite hacer un mapeo de las peticiones HTTP a elementos específicos para el manejo de eventos además de manejar los elementos de interfaz de usuario como si fueran objetos con estado en el lado del servidor. Otra ventaja importante de la tecnología JSF es que permite utilizar los componentes de interfaz de usuario sobre cualquier otra tecnología de presentación para otro tipo de dispositivos. Y lo más importante, JSF aporta una arquitectura para manejar el estado de los componentes, el proceso de los datos, la validación de las entradas del usuario y el manejo de eventos. El uso de JSF aporta las siguientes ventajas adicionales: · Es un estándar JEE. Esto asegura que los principales fabricantes de servidores de aplicaciones e IDEs sean compatibles con JSF. · Al ser un modelo basado en componentes, la productividad es mayor y se fomenta la reutilización. · Posibilita el uso de herramientas de diseño visuales. · Ofrece una separación nítida entre presentación y lógica de negocio, y por tanto, de los roles involucrados. · Flexibilidad. Permite a los desarrolladores la ampliación de los componentes de las librerías de etiquetas e incluso la creación de otros nuevos. · Apta para la gestión de clientes heterogéneos (WML, Wap, HTML, XML, etc.). En la actualidad existen un extenso conjunto de librerías de componentes JSF, tanto comerciales como de código abierto. Para el desarrollo de aplicaciones Atlas pueden utilizarse alguna de ellas. NORMA JSFComponentes Para la implementación de la interfaz de usuario de las aplicaciones con JSF, sólo se podrán emplear los componentes propios de Atlas, los de MyFaces, RichFaces y sus extensiones. Las librerías para estos componentes ya se encuentran dentro del repositorio Maven de ICM. 29 de 198 Framework Atlas Normativa 6.2.1 PAGINAS JSF En las páginas JSF se situan los distintos elementos que formaran las páginas a mostrar al usuario final de la aplicación. JSFXHTML Todos los ficheros JSF deberán ser documentos XHTML con extensión “.xhtml”. NORMA Como sistema de codificación se empleará UTF-8. Los componentes Web transmitirán todas las páginas con dicho sistema de codificación (encoding="UTF-8"). Todas las páginas JSF se ubicarán en la carpeta src/main/webapp y subcarpetas. Para distinguir aquellas páginas cuyo acceso esté securizado estas se ubicarán en una carpeta llamada src/main/webapp/secure. Dentro de esta carpeta se podrán crear las subcarpetas necesarias para poder llevar una gestión de perfiles de acceso. JSFPOB NORMA Las páginas deben de ser compatibles con las versiones de Navegador Internet Explorer 7 o superior, Mozilla Firefox 3.6.28 o superior, y Google Chrome 31 o superior. Los módulos que se desarrollen para los usuarios de la Intranet deben funcionar correctamente con el POB (Puesto ofimático básico) que tienen instalado en su PC. A continuación se muestra un ejemplo de página JSF: Ejemplo de página JSF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:atlas="http://atlas.core.componentes/jsf" xmlns:c="http://java.sun.com/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" > <ui:composition template="/WEB-INF/layout/vc.xhtml"> 30 de 198 Framework Atlas Normativa <ui:define name="rastroMigas"> <ui:include src="/secure/rastroMigas/rastro.xhtml" /> </ui:define> <ui:define name="menuVertical"> <ui:include src="/secure/menu/menu.xhtml" /> </ui:define> <ui:define name="content"> <h:form id="mainPanel"> <atlas:guardarEstado id="stateIdCliente" value="#{clientesBean.cliente}" /> <h:panelGroup> <h:panelGrid width="70%" columns="3"> <h:outputLabel id="outputLabelNombre" for="inputTextNombre" styleClass="label" value="#{bundle['inputText.nombre']}" /> <h:panelGroup> <h:inputText id="inputTextNombre" size="50" maxlength="50" styleClass="cajaTextoObligat" value="#{clientesBean.cliente.nombre}" required="true" /> </h:panelGroup> <h:panelGroup> <h:message for="inputTextNombre" styleClass="mensajeERRORtxt" showDetail="true" showSummary="false" /> </h:panelGroup> <h:outputLabel id="outputLabelApellido1" for="inputTextApellido1" styleClass="label" value="#{bundle['inputText.apellido1']}" /> <h:panelGroup> <h:inputText id="inputTextApellido1" size="50" maxlength="50" styleClass="cajaTextoObligat" value="#{clientesBean.cliente.apellido1}" required="true"> </h:inputText> </h:panelGroup> <h:panelGroup> <h:message for="inputTextApellido1" styleClass="mensajeERRORtxt" showDetail="true" showSummary="false"/> </h:panelGroup> ... <h:outputText styleClass="botonAplicacionTXT" value="#{bundle['boton.vuelta_atras']} " /> <h:graphicImage value="img/portal/filtro.jpg" alt="#{bundle['boton.vuelta_atras']}" /> </h:commandLink> <h:commandLink id="guardarLink" action="#{clientesBean.guardarCliente}" styleClass="buttonsRowLeftColumn"> <h:outputText styleClass="botonAplicacionTXT" value="#{bundle['boton.guardar_cliente']} " /> <h:graphicImage value="img/portal/filtro.jpg" alt="#{bundle['boton.guardar_cliente']}" /> </h:commandLink> ... </ui:composition> 31 de 198 Framework Atlas Normativa </html> El acceso a la capa de negocio desde las páginas JSF se hará a través de clases java llamadas managed beans o beans de respaldo. La asociación de datos entre los componentes de las páginas y sus managed beans se puede hacer de dos maneras: · Asociación de valores: permite configurar una propiedad de un componente de la página mediante un atributo de un bean. Ejemplo de asociación de valores <h:inputText id="inputTextNombre" size="50" maxlength="50" styleClass="cajaTextoObligat" value="#{clientesBean.cliente.nombre}" required="true" /> · Asociación a métodos: permite configurar una propiedad de un componente de la página con el resultado de la invocación a un método del bean. Ejemplo de asociación a métodos <h:commandLink id="guardarLink" action="#{clientesBean.guardarCliente}" styleClass="buttonsRowLeftColumn"> <h:outputText styleClass="botonAplicacionTXT" value="#{bundle['boton.guardar_cliente']}" /> <h:graphicImage value="img/portal/filtro.jpg" alt="#{bundle['boton.guardar_cliente']}" /> </h:commandLink> PRACTICA Se recomienda que desde cada página JSF solamente se acceda a un único managed bean que ofrecerá la interfaz necesaria para la invocación de esa página, salvo en el caso de varias páginas que gestionen el mismo tipo de invocaciones. JSFGet CA PRACTI BUENA BUENA JSFManagedBean En la asociación de valores, JSF llama al método get correspondiente del bean para obtener el valor. Se recomienda no poner lógica en estos métodos, ya que pueden ser llamados un 32 de 198 Framework Atlas Normativa número elevado de veces durante el ciclo de vida de una petición. En caso de que el valor a devolver deba calcularse u obtenerse de base de datos debería hacerse en otro método que se ejecute sólo una vez (constructor de la clase, método action del componente que desencadene la acción…). JSFNegocio NORMA Desde las páginas JSF solamente se podrá acceder a managed beans. No está permitido la invocación a los objetos de acceso a datos (DAOs) de la aplicación ni objetos de servicio de negocio. PRACTICA BUENA Tampoco está permitido el uso de código Java directamente en la página JSF. JSFTamano Las páginas JSF se deberán diseñar y modularizar de tal forma que no tomen unas dimensiones excesivas. PRACTICA BUENA JSFEL 6.2.1.1 Se recomienda no utilizar expresiones EL excesivamente complejas en las páginas XHTML, para esos casos es preferible codificar la expresión en una propiedad del managed bean y hacer referencia a dicha propiedad. Manejo de eventos El manejo de eventos debe realizarse mediante acciones siempre que sea posible. En el atributo action se debe indicar el método JSF que será invocado ante el click de un usuario en los elementos commandLink, commandButton o cualquier componente que herede dicho comportamiento. Este método debe ser público, sin parámetros y retornar un String con la dirección que tomarán las reglas de navegación: En la página JSF <h:commandLink id="guardarLink" action="#{clientesBean.guardarCliente}" styleClass="buttonsRowLeftColumn"> <h:outputText styleClass="botonAplicacionTXT" value="#{bundle['boton.guardar_cliente']} " /> 33 de 198 Framework Atlas Normativa <h:graphicImage value="img/portal/filtro.jpg" alt="#{bundle['boton.guardar_cliente']}" /> </h:commandLink> En el managed bean /** * Este metodo inserta o modifica un cliente en el sistema. * * @throws atlas.core.exceptions.ServiceException * Lanza atlas.core.exceptions.ServiceException ante cualquier error * @return <code>java.lang.String</code> Devuelve la regla de navegacion * <code>NavigationResults.VOLVER_LISTADO_CLIENTES</code>. */ public String guardarCliente() throws ServiceException { try { facade.insertOrUpdateCliente(cliente); } catch (ServiceException se) { AtlasFacesUtils.storeOnRequestError(FacesContext.getCurrentInstance(), "error.CLIENTES_MODIFICAR", se); throw se; } return NavigationResults.VOLVER_LISTADO_CLIENTES; } Para más información sobre el uso de NavigationResults ver el apartado de Managed Beans. En caso de existir la necesidad de acceder a elementos de la interfaz de usuario durante la ejecución se puede capturar la llamada mediante un actionListener, esto permite recibir información sobre el estado de los componentes visuales del cliente mediante el parámetro que es enviado: En la JSF <h:commandLink action="#{miBean.accion}" actionListener="#{miBean.escuchadorAccion}"> <h:outputText value="#{bundle['texto_del_link']}"/> </h:commandLink> En el managed bean: accion public String accion() { //Lógica de la accion. return NavigationResults.MOSTRAR_RESULTADO; } En el managed bean: escuchadorAccion public void escuchadorAccion(ActionEvent evento) { 34 de 198 Framework Atlas Normativa //Lógica relacionada con los componentes UI del cliente por ejemplo, //recuperar los hijos y facets del componente: evento.getComponent().getFacetsAndChildren(); } JSFAcciones Como norma general, se empleará el manejo de eventos mediante acciones (en lugar de PRACTICA BUENA ActionListeners) si bien se deberá elegir con cuidado que alternativa de las dos será la óptima en cada caso. En el caso de manejo de eventos mediante actionListeners se recomienda que se realice en conjunción con acciones estándar, incluyendo la lógica de control de aplicación en estas últimas y delegando sólo las tareas relacionadas con manejo avanzado de los componentes de usuario a los actionListeners. Por otro lado, están los escuchadores de propiedades (ValueChangeListener) que permiten ejecutar métodos de un managed bean cuando cambia una propiedad de un componente de interfaz de usuario: En la página JSF <h:selectBooleanCheckbox id="changeColorMode" valueChangeListener="#{resumeBean.changeColorMode}" immediate="true" onchange="submit()" /> En el managed bean public void changeColorMode(ValueChangeEvent event) { boolean flag = ((Boolean) event.getNewValue()).booleanValue(); setUsingColorNames(!flag); } 6.2.1.2 Recuperación de parámetros Como norma general no será necesario enviar parámetros adicionales ya que JSF se encargará de realizar llamadas a los métodos set de los atributos que representan los campos de un formulario, pero habrá casos en los que será necesario el envío de información adicional. Un claro ejemplo es el caso de una funcionalidad maestro-detalle donde se debe enviar un elemento de un listado para poder mostrar posteriormente el detalle del mismo. Para ello disponemos de dos mecanismos: o f:setPropertyActionListener 35 de 198 Framework Atlas Normativa o f:param El primero consiste en el envío del objeto completo al realizar la acción. Anidando el componente setPropertyActionListener dentro de un commandLink o un commandButton conseguimos que JSF actualice los valores de propiedades e incluso objetos completos al realizar una acción: Ejemplo de updateActionListener <atlas:listaPaginada ..............> <h:column .....> <h:commandButton value="#{bundle['texto_del_boton']}" action="#{miBean.mostrarCliente}"> <f:setPropertyActionListener value="#{item}" target="#{miBean.cliente}"/> </h:commandButton> </h:column> </atlas:listaPaginada> En este ejemplo cuando se invoca el método mostrarCliente en el atributo cliente se establece el valor ‘item’. Lamentablemente no siempre es posible hacer uso de esta estrategia, por ejemplo en acciones que tienen el atributo immediate="true". Para estas situaciones disponemos de otro método que nos permite enviar parámetros de tipos de dato primitivos (no objetos o arrays). Cualquier componente de tipo commandButton, commandLink, outputLink o derivados de los mismos acepta componentes anidados de tipo f:param, que envía el valor asociado a una clave como parámetro de la request. Al ser enviado como parámetro de la request podemos recuperar dichos parámetros en cualquier punto del ciclo de vida de JSF, incluso en el constructor del Managed Bean si fuese necesario: En la JSF <atlas:listaPaginada ..............> <h:column .....> <h:commandButton value="#{bundle['texto_del_boton']}" action="#{miBean.mostrarCliente}"> <f:param value="#{item.idCliente}" name ="parametroIdCliente"/> </h:commandButton> </h:column> </atlas:listaPaginada> En el managed bean public String mostrarCliente() { Long idCliente = (Long) FacesSupport.getParameter("parametroIdCliente"); //Cargamos el cliente a partir de su Id llamando a la fachada de 36 de 198 Framework Atlas Normativa //servicios this.cliente = gestionFacade.cargarCliente(idCliente); return NavigationResults.MOSTRAR_CLIENTE; } Mediante estas técnicas y el uso del componente atlas:guardarEstado que se explicará en detalle más adelante podemos reducir al máximo el uso de la sesión. 6.2.1.3 Validadores La arquitectura de JSF ofrece mecanismos para automatizar la validación de los datos de una aplicación. Del mismo modo, ofrece la posibilidad de crear validadores a medida. Las validaciones estándar de JSF se realizan en el servidor, aunque también es posible hacer validaciones en el cliente (mediante javascript). Los errores de validación se pueden mostrar mediante los mensajes de JSF utilizando <h:message/> o <h:messages/>. Ejemplo de uso de un validador standard <h:inputText id="number1" value="#{calcFormBean.number1}" maxlength="2" size="25" required="true"> <f:validateLongRange minimum="1" maximum="10" /> </h:inputText> <h:message id="number1Error" for="form1:number1" styleClass="error" /> Esta validación comprueba que se haya introducido un valor numérico en el campo “number1”, y que su longitud no supere los 2 caracteres. Además se comprueba que el número introducido esté entre el 1 y 10. Si los datos introducidos son erróneos, se mostrará un mensaje de error. También existen validadores estándar asociados a ciertos componentes de entrada de datos. Ejemplo de campo obligatorio <h:outputLabel id="outputLabelNombre" for="inputTextNombre" styleClass="label" value="#{bundle['inputText.nombre']}" /> <h:panelGroup> <h:inputText id="inputTextNombre" size="50" maxlength="50" styleClass="cajaTextoObligat" value="#{clientesBean.cliente.nombre}" required="true" /> </h:panelGroup> <h:panelGroup> <h:message for="inputTextNombre" styleClass="mensajeERRORtxt" showDetail="true" showSummary="false" /> </h:panelGroup> 37 de 198 Framework Atlas Normativa En el ejemplo anterior hacemos uso de dicho componente para mostrar un error cuando el usuario no introduzca nada en el campo “inputTextNombre”. Si deseamos personalizar el mensaje de error a mostrar cuando se produzca un error de PRACTICA BUENA JSFMessages validación, es recomendable el uso del componente de JSF para mostrar mensajes (<h:message/> o <h:messages/>). Para añadir mensajes al contexto se recomienda utilizar los métodos creados a tal efecto en en la clase atlas.componentes.utiles.AtlasFacesUtils. JSF también permite realizar validaciones a nivel de aplicación. Este tipo de validaciones se consideran validaciones de lógica de negocio. Básicamente, la validación a nivel de aplicación conlleva añadir código extra a los métodos de los managed beans, que hacen comprobaciones adicionales sobre los datos obtenidos. Por ejemplo, en una aplicación que implemente un carrito de la compra, la validación a nivel de formulario comprobaría si una cantidad introducida es válida (previa conversión de la cantidad a un objeto java conocido), y la validación a nivel de aplicación podría validar si el usuario ha excedido su límite de crédito. NORMA JSFValidacion Todas las validaciones sobre campos de un formulario se han de implementar en el servidor. Si se desea realizar las validaciones en el cliente, deberá existir una comprobación idéntica en el lado del servidor, ya sea mediante validación estándar de JSF o mediante validación a nivel de aplicación. 38 de 198 Framework Atlas Normativa JSFCustomValidator Cuando sea necesario realizar una validación genérica para la que Atlas no ofrezca un validador estándar, se implementará uno a medida. NORMA Para crear un validador a medida se creará una clase Java que implemente la interfaz Validator, con la siguiente nomenclatura: o <nombre>Validator Donde nombre será sustituido por el nombre del validador. Estas clases se incluirán en el paquete jsf.validators del bloque funcional correspondiente. En el caso de que sean validadores genéricos para todo el proyecto se pueden ponen en un bloque funcional común. 6.2.1.4 Conversores Los datos procedentes de una petición Http son cadenas de caracteres. Por eso es necesario un mecanismo de conversión de dichas cadenas al tipo de datos deseado (el declarado en el managed bean vinculado al campo del formulario). Ejemplo de uso de un conversor <h:outputText value="#{user.dateOfBirth}"> <f:convertDateTime type="both" dateStyle="full" /> </h:outputText> JSFCustomConversor Cuando sea necesario realizar un conversor particular para la que Atlas no ofrezca un conversor estándar, se implementará uno a medida. NORMA Para crear un conversor a medida se creará una clase Java que implemente la interfaz Converter, con la siguiente nomenclatura: o <nombre>Converter Donde nombre será sustituido por el nombre del conversor. Estas clases se incluirán en el paquete jsf.converters del bloque funcional correspondiente. En el caso de que sean conversores genéricos para todo el proyecto se pueden ponen en un bloque funcional común. 6.2.1.5 Internacionalización 39 de 198 Framework Atlas Normativa El conjunto de elementos culturales, políticos y específicos de una región representados en una aplicación se denominan “locale”. Las aplicaciones deberían personalizar la presentación de los datos en función del “locale” preferido del usuario, de esta manera se puede definir el concepto de internacionalización (También conocida como I18n) como el proceso de separar las dependencias “locale” del código fuente de la aplicación. Ejemplos de dependencias “locale” pueden ser el conjunto de caracteres, encoding, moneda, formato de tiempo, calendarios, etc. El concepto de Localización (También conocido como L10n) es el proceso de adaptar una aplicación internacionalizada a un “locale” específico, por lo que las aplicaciones tendrán que estar internacionalizadas de forma previa a ser localizadas. JSF dispone de un potente soporte a la internacionalización y la localización. Para desarrollar una aplicación completamente internacionalizada, todos los literales incluyendo etiquetas, campos de fecha, campos numéricos, campos de texto, mensajes de error y textos mostrados como alternativa a las imágenes se han de externalizar a un archivo de propiedades. El entorno de ejecución de JSF determina el “locale” de un usuario en base a la configuración de su navegador, aunque se puede establecer por configuración el “locale” de la misma. JSF usa la clase ResourceBundle para cargar los mensajes de texto del archivo de propiedades y mostrarlos en los componentes de presentación. JSFInternalizacion En las páginas JSF no puede haber literales de texto en un idioma específico. Las aplicaciones contendrán un fichero para almacenar los mensajes internacionalizados. Este NORMA fichero se ubicará en la carpeta src/main/resources/msg, con la siguiente nomenclatura: o messages_xx.properties Donde xx es el sufijo del locale al que corresponden los ficheros de mensajes. Este fichero contendrá todos los mensajes de la aplicación. El mecanismo de internacionalización no aplica a mensajes incluidos en trazas, al no ser directamente visualizados por los usuarios finales. Al menos se debe de entregar el fichero de mensajes del locale español (es). Los distintos arquetipos ya vienen preparados con estos ficheros de mensajes y la configuración necesaria para trabajar con ellos. Desde la página JSF cuando queramos acceder a los textos del fichero de internacionalización se utilizará el objeto bundle tal y como se muestra en el siguiente ejemplo: 40 de 198 Framework Atlas Normativa Ejemplo de uso de literales internacionalizados PRACTICA BUENA <h:outputLabel id="outputLabelNombre" for="inputTextNombre" styleClass="label" value="#{bundle['inputText.nombre']}" /> 6.2.1.6 JSFAccesoMessages Para acceder a los elementos del fichero de mensajes se recomienda utilizar el método getStringFromBundle de la clase atlas.componentes.utiles.AtlasFacesUtils. Estructura y decoración de la página En muchos casos surge la necesidad de implementar un mecanismo mediante el cual mantengamos una estructura (“layout”) consistente entre todas las páginas que conforman la aplicación Web, lo que implicará tener elementos comunes de página para ser implementados como componentes reutilizables. La tecnología elegida para lograr esto es Facelets, que permite incluir plantillas reutilizables de forma dinámica implementando de forma abstracta el patrón composite view y decorator. Facelets es un lenguaje basado en plantillas que utiliza el concepto de “árbol de componentes” fomentando la reutilización, permitiendo definir componentes como composición de otros componentes. Podemos destacar las siguientes características sobre Facelets: · Trabajo basado en plantillas. · Basado en la composición de componentes. · Creación de etiquetas lógicas a la medida. · Soporte completo a EL, incluyendo funciones. · Desarrollo amigable para el diseñador gráfico gracias al concepto de “decorador”. · Creación de librerías de componentes. · Lenguaje integrado son JSTL. · No son necesarios ficheros de configuración XML. · El API de facelets son totalmente independientes del contenedor. 41 de 198 Framework Atlas Normativa Dentro del framework Atlas se han creado los distintos layouts que tienen que utilizar las aplicaciones desarrolladas con este framework. El uso de estos layouts garantiza la homogeneidad de los desarrollos y facilita el mantenimiento de los mismos. Los layouts que ofrece el framework son: hc.xhtml (Horizontal+Contenido). Incluye un menú horizontal, y en el resto de la página se muestra el contenido. hvc.xhtml: (Horizontal+Vertical+Contenido). Incluye un menú horizontal, uno vertical y en el resto de la página se muestra el contenido. 42 de 198 Framework Atlas Normativa hv.xhtml (Horizontal+Visual). Incluye un menú horizontal, y en el resto de la página se muestra el menú visual. hvv.xhtml (Horizontal+Vertical+Visual). Incluye un menú horizontal, menú vertical y en el resto de la página se muestra el menú visual. vc.xhtml (Vertical + Contenido). Incluye un menú vertical, y en el resto de la página se muestra el contenido. 43 de 198 Framework Atlas Normativa vv.xhtml: (Vertical + Visual). Incluye un menú vertical, y en el resto de la página se muestra el menú visual. c.xhtml (Contenido) Incluye solamente la cabecera y NORMA el pie. JSFLayout El layout de páginas web debe ser alguno de los que ofrece el framework Atlas. Ejemplo de uso de layout con menú vertical <?xml version="1.0" encoding="UTF-8"?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:atlas="http://atlas.core.componentes/jsf" xmlns:c="http://java.sun.com/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:a4j="http://richfaces.org/a4j" 44 de 198 Framework Atlas Normativa xmlns:rich="http://richfaces.org/rich" version="2.0"> <jsp:text> <![CDATA[ <?xml version="1.0" encoding="UTF8" ?> ]]> </jsp:text> <jsp:text> <![CDATA[ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]> </jsp:text> <html xmlns="http://www.w3.org/1999/xhtml"> <ui:composition template="/WEB-INF/layout/vc.xhtml"> <ui:define name="rastroMigas"> <ui:include src="/secure/rastroMigas/rastro.xhtml" /> </ui:define> <ui:define name="menuVertical"> <ui:include src="/secure/menu/menu.xhtml" /> </ui:define> <ui:define name="content"> . . . Aqui se pondría el contenido de nuestra página </ui:define> </ui:composition> </html> </jsp:root> NORMA JSFPanel La ubicación de los distintos elementos que forman la página se realizará con los componentes que JSF ofrece: PanelGrids y PanelGroup. No se utilizarán directamente tablas de html. Los componentes de menús de ATLAS permiten técnicamente la definición de menús personalizados por usuario. Sin embargo, el uso de menús personalizados por usuario puede aumentar el consumo de memoria de la aplicación, ya que dichos menús se almacena en la Sesión del usuario. Por este motivo, se prohíbe el uso de menús personalizados por usuario, en el caso de que se deseen utilizar menús personalizados se debe solicitar la correspondiente autorización a ICM justificando dicha necesidad. 45 de 198 Framework Atlas Normativa NORMA JSFCustomMenu Se prohíbe el uso de menús personalizados por usuario. En el caso de que se deseen utilizar menús personalizados se debe solicitar la correspondiente autorización a ICM justificando dicha necesidad. 6.2.1.7 Uso de javascript JSFJavascript Se debe minimizar el uso de Javascript y el código javascript que se incluya debe ser compatible NORMA con los navegadores. En el caso de utilizar codigo javascript este se implementará mediante funciones que se ubicarán en ficheros xxxx.js. Donde xxxx es el nombre de la aplicación. Los ficheros de javascript deberán ubicarse dentro de la carpeta src/main/webapp/js. Los ficheros js que se incluyen en los arquetipos no pueden ser modificados. jQuery es una biblioteca de JavaScript que permite simplificar la manera de interactuar con los documentos HTML, manipular el árbol DOM, manejar eventos, desarrollar animaciones y agregar interacción con la técnica AJAX a páginas web. Por lo tanto si se requiere realizar algunas de estas operaciones en las aplicaciones Atlas se deberá utilizar este framework. Este framework javascript ya viene incluido en la distribución de RichFaces que viene configurada en los arquetipos de ATLAS, por lo que no será necesario incluir ningún fichero adicional en el proyecto. NORMA JSFJQuery Solo está permitido el uso del framework javascript JQuery que viene incluido en la versión de RichFaces. No se podrán incluir frameworks diferentes a este ni otras versiones que no sea la interna de RichFaces. Para usar JQuery en el proyecto, se han de tener en cuenta las siguientes consideraciones: 6.2.1.7.1 Uso de JQuery en páginas JSF Para usar JQuery en nuestras páginas JSF será necesario incluir esta sentencia en la página “.xhtml”: Sentencia a incluir en la página “.xhtml” para utilizar jQuery <h:outputScript name="jquery.js" target="head" /> De esta forma se estará haciendo uso de la versión interna de Richfaces. 46 de 198 Framework Atlas Normativa 6.2.1.7.2 Uso del objeto JQuery Para usar el objeto JQuery, no se podrá utilizar el alias ‘$’, que es de uso común en este framework, ya que da problemas con las expresiones JSF. A continuación se muestran dos ejemplos uno que NO Funciona y otro que SI funciona: Uso del objeto JQuery en página xhtml <h:outputScript name="jquery.js" target="head" /> <h:outputScript> $('#elementId').text('Nuevo contenido'); // NO funciona jQuery('#elementId').text('Nuevo contenido'); // SI funciona </h:outputScript> 6.2.1.7.3 Uso de ready en sustitución del evento onLoad En ocasiones es necesario realizar acciones una vez se haya cargado la página. Normalmente se hace uso del evento onLoad del tag body que es invocado una vez que se ha cargado toda la página. Se recomienda, en lugar de utilizar ese evento, hacer uso del método ready del objeto JQuery ya que este método se ejecuta una vez inicializado el árbol DOM de la página en el navegador. A continuación se muestra un ejemplo: Sustitución de onLoad por evento ready <h:outputScript name="jquery.js" target="head" /> <h:outputScript> jQuery(document).ready(function() { // Incicializar pagina ... }); </h:outputScript> 6.2.1.7.4 Localización de elementos por Id Cuando se quiere localizar un elemento de la página por su identificador, el carácter de composición usado por JSF ‘:’ genera problemas con JQuery, ya que también es un operador de selección. Por lo tanto para no tener problemas hay que transformarlo para escaparlo antes de pasarlo a JQuery. A continuación se muestra un ejemplo: Escapado para poder localizar elementos por Id <h:outputScript name="jquery.js" target="head" /> <h:form id="formularioDatos"> <f:subview id="vista1"> <h:inputText id="nombre" /> <!-- id='formularioDatos:vista1:nombre' --> </f:subview> 47 de 198 Framework Atlas Normativa </h:form> <h:outputScript> nombreId = '#{rich:clientId(“nombre”)}'.replace(/:/g, '\\:'); jQuery(‘#’ + nombreId).value = ‘ATLAS’; </h:outputScript> La operación marcada en amarillo en el ejemplo anterior obtiene el Id real del elemento ‘nombre’ (formularioDatos:vista1:nombre), mientras que la parte marcada en verde lo modifica para su uso con jQuery (formularioDatos\:vista1\:nombre). 6.2.1.8 Normas de estilo Existe un documento llamado “Atlas Guía de Estilo” que incluye información sobre: o Estilo de las aplicaciones o Accesibilidad o Usabilidad Es necesario leer este documento antes de abordar la implementación de las páginas JSF. NORMA JSFAccesibilidad Las aplicaciones de la Comunidad de Madrid que se publiquen en Internet tendrán que cumplir un Nivel de Conformidad "A" de WCAG, esto implicará que las aplicaciones sean estrictas en el cumplimiento de las normas de prioridad 1 especificadas en el Anexo Guía de Estilo del NORMA framework Atlas. JSFImagenes Las imágenes a utilizar en las aplicaciones del framework Atlas deberán ubicarse dentro de la carpeta src/main/webapp/img 48 de 198 Framework Atlas Normativa JSFCSS Las hojas de estilo se ubicaran en la carpeta src/main/webapp/css. Dentro de esta carpeta se encuenta un fichero llamado atlas.css que incluye los estilos de Atlas. Este fichero no se puede NORMA modificar. En el caso de necesitar nuevos estilos estos se crearán dentro de un fichero con la siguiente nomenclatura xxxx.css Donde xxxx es el nombre de la aplicación. Nunca se podrán definir estilos directamente dentro de una página. NORMA JSFIFRAMES Se prohibe la utilización de IFrames. En el caso de que sea necesario utilizarlos es necesario consultar previamente a su utilización a la Unidad de Arquitectura y Software de Aplicaciones justificando debidamente su necesidad. 6.2.1.9 Interfaces ricas de usuario (RIA) Existen tecnologías que pretenden mejorar las aplicaciones web asemejándolas todo lo posible a las aplicaciones de escritorio tradicionales. La arquitectura de ICM permite crear aplicaciones RIA utilizando AJAX de dos maneras: · Mediante la librería Ajax4JSF · Usando los componentes JSF del framework Atlas que poseen comportamiento asíncrono con AJAX de forma transparente. Ajax4JSF se incluye dentro de los componentes RichFaces. Es una librería open source que se integra totalmente en la arquitectura de JSF y extiende la funcionalidad de sus etiquetas dotándolas con tecnología Ajax de forma limpia y sin añadir código Javascript. Mediante esta librería se puede variar el ciclo de vida de una petición JSF, recargar determinados componentes de la página sin necesidad de recargarla por completo, realizar peticiones al servidor automáticas, control de cualquier evento de usuario, etc. Esta aproximación tiene las siguientes ventajas: 49 de 198 Framework Atlas Normativa · La cantidad de javascript que hay que escribir (y mantener) es mínima. Esto reduce enormemente el tiempo de depuración y pruebas necesarias cuando se trabaja en un entorno multi-navegador. · Fácil integración: Ajax4JSF apenas requiere la modificación del código existente. · Soporte Facelets: Es una solución que se integra a la perfección con la tecnología de decoración y estructura de páginas, es decir, facelets. · Compatibilidad. No es necesario desarrollar otra aplicación para cuando el navegador no soporta AJAX. En este caso, la aplicación se comportará de la forma tradicional, refrescando la página completa. NORMA JSFAjax Si se desea dotar de capacidades AJAX a las páginas JSF se utilizará Ajax4JSF. El uso de cualquier otra tecnología RIA deberá ser consensuado previamente con ICM. El arquetipo web ya viene configurado para trabajar con Ajax4JSF. La forma mas sencilla de incluir ajax4JSF en una página es incluir una región y todo lo que se incluya dentro de esta se refrescará parcialmente. Ejemplo de uso de región ajax <a4j:form id="allRoomsForm2" ajaxSubmit="true" reRender="roomsTable,scroll_1,scroll_2" status="ajaxStatus"> <a4j:region id="region1" selfRendered="true"> ….. </a4j:region> </a4j:form> NORMA JSFAjaxInterac La invocación de funcionalidad AJAX debe ser siempre consecuencia de una interacción con el usuario, por ejemplo, al seleccionar el valor de un combo, se carga de manera dinámica los valores de otro. En concreto, la carga inicial de una página no debe implicar la ejecución de funcionalidad AJAX. 50 de 198 Framework Atlas Normativa JSFAjaxLimite Se recomienda limitar la cantidad de información intercambiada mediante AJAX. PRACTICA BUENA Para esto se recomienda restringir las regiones AJAX de modo que se procese el mínimo número de componentes. Las regiones se pueden anidar y no es necesario que los componentes que se vayan a actualizar estén dentro de la región. También se recomienda el uso del atributo AjaxSingle en aquellas situaciones en las que sólo sea necesario que se procese el componente que desencadena el evento. Por último, en ocasiones es preferible recargar la página de nuevo, a intercambiar mediante AJAX gran cantidad de información, y utilizar componentes estándar a utilizar componentes AJAX si no se va a hacer uso de propiedades específicas del componente. 51 de 198 Framework Atlas Normativa 6.2.1.10 Ayuda contextual La ayuda contextual en una aplicación favorece y mejora la experiencia de usuario facilitando el uso de la aplicación. Para incluir este tipo de ayuda en una página de nuestra aplicación utilizaremos el icono que podemos encontrar en la ruta “src/main/webapp/img ico_ayuda.gif” de los arquetipos. Dentro de los formularios JSF se puede incluir ayuda contextual para cada uno de los elementos mediante el uso de la etiqueta de richfaces rich:toolTip. Mediante esta etiqueta se muestra un pequeño popup no modal en el cual se puede mostrar información adicional. Ejemplo de uso de rich:toolTip en un campo de un formulario <h:panelGrid columns="2" cellpadding="0" cellspacing="0"> <h:inputText id="inputTextClienteNombre" size="50" maxlength="50" styleClass="cajaTexto" required="false" value="#{clienteBean.nombreFilter}" onkeypress="trapEnter(event,'filterPanel:filtrarLink',true);"/> <a4j:outputPanel styleClass="paddingleft5"> <h:graphicImage value="img/ico_ayuda.gif" alt="#{bundle['tooltipFilter.clientenombre']}"/> <rich:tooltip value="#{bundle['tooltipFilter.clientenombre']}"/> </a4j:outputPanel> </h:panelGrid> El mensaje a mostrar dentro del tooltip se ha de obtener del fichero de mensajes de la aplicación tal y como se puede ver en el ejemplo anterior. En los arquetipos de Atlas se han incluido ejemplos de uso de tooltip en los formularios de ejemplo, y la herramienta de generación automática de código también genera estos tooltips en las páginas de listados y detalles de entidades. Si se desea una ayuda contextual más completa a nivel de página se hará utilizando el componente <atlas:panelAyuda> que muestra un icono en la parte superior derecha que enlaza con la página xhtml de ayuda correspondiente a dicha página. Esta página se muestra en un popup no modal para que pueda ser visualizada mientras se está trabajando con la aplicación. Las páginas de ayuda se incluirán en una carpeta llamada help y la nomenclatura de las mismas deberá ser la misma de la página original más un sufijo _help. Para más información consultar el manual de usuario ATLAS_MUS_Componente_Panel_ayuda. 52 de 198 Framework Atlas Normativa En la siguiente página podemos ver el icono que enlaza con la ayuda en la parte superior derecha de la página. Al pulsar sobre el icono nos mostrará el panel de la ayuda de la siguiente forma: PRACTICA BUENA JSFAYUDA 6.2.2 Se recomienda incluir ayuda contextual en las aplicaciones utilizando el componente rich:toolTip para elementos individuales y atlas:panelAyuda para ayudas a nivel de página. MANAGED BEANS 53 de 198 Framework Atlas Normativa Los managed beans o beans de respaldo son las clases que incluyen los atributos y métodos que van a ser invocados desde las páginas JSF. Los distintos métodos que puede tener un managed bean son: 1. Gettter y setter de los atributos 2. Métodos manejadores de eventos de acción 3. Métodos de manejo de eventos de cambio de valor 4. Métodos de acción JSFMBeansImpl Dentro de una aplicación en cada bloque funcional se han de crear los managed beans que darán NORMA cobertura a las peticiones de las páginas JSF. La nomenclatura de estas clases será: <nombre>Bean Donde <nombre> debe ser sustituido por el nombre del Bean. Estas clases Java se crearán en el paquete jsf dentro del bloque funcional correspondiente. A continuación se muestra parte de un ejemplo de managed bean. El ejemplo completo se puede ver dentro del arquetipo de aplicaciones web. ClientesBean.java package ejpl.gestion.jsf; import … /** * Esta clase representa el Backing Bean * para las páginas que hagan uso de la * entidad ejpl.gestion.domain.Cliente . * @author ICM * @version 1.0. */ @Component public class ClientesBean { /** * Identificador del numero de serie para serializacion */ private static final long serialVersionUID = 1L; /** * Servicio de la fachada */ 54 de 198 Framework Atlas Normativa private GestionFacade facade; /** * Cliente actual */ private Cliente cliente = null; /** * Filtro para el nombre del cliente */ private String nombreCliente = null; /** * Constructor por defecto. * <p> * Se realizan las operaciones de * inicialización para los Managed Beans */ public ClientesBean() { this.cliente = new Cliente(); cliente.setEstadoCivil(new EstadoCivil()); } /** * @return <code>ejpl.gestion.domain.Cliente</code> Devuelve el objeto de * dominio cliente asociado al Backing Bean. */ public Cliente getCliente() { return this.cliente; } /** * @param cliente <code>ejpl.gestion.domain.Cliente</code> Modifica el * objeto de dominio asociado al Backing Bean. */ public void setCliente(Cliente cliente) { this.cliente = cliente; } /** * Este metodo obtiene un cliente a partir de un identificador/PK obtenida * de la request. * * @throws atlas.core.exceptions.ServiceException * Lanza atlas.core.exceptions.ServiceException ante cualquier error * @return <code>java.lang.String</code> Devuelve la regla de navegacion * <code>NavigationResults.MODIFICAR_CLIENTE</code>. */ public String cargarCliente() throws ServiceException { String paramIdCliente = AtlasFacesUtils.getFromRequest(FacesContext.getCurrentInstance(), "idCliente"); try { if (paramIdCliente != null) { Integer idCliente = Integer.valueOf(paramIdCliente); this.cliente = facade.obtenerClientePorId(idCliente); } } catch (ServiceException se) { 55 de 198 Framework Atlas Normativa AtlasFacesUtils.storeOnRequestError(FacesContext.getCurrentInstance(), "error.CLIENTES_OBTENER", se); // return NavigationResults.MOSTRAR_ERROR; throw se; } return NavigationResults.MODIFICAR_CLIENTE; } /** * Este metodo inserta o modifica un cliente en el sistema. * * @throws atlas.core.exceptions.ServiceException Lanza * atlas.core.exceptions.ServiceException ante cualquier error * producido. * @return <code>java.lang.String</code> Devuelve la regla de navegacion * <code>NavigationResults.VOLVER_LISTADO_CLIENTES</code>. */ public String guardarCliente() throws ServiceException { try { facade.insertOrUpdateCliente(cliente); } catch (ServiceException se) { AtlasFacesUtils.storeOnRequestError(FacesContext.getCurrentInstance(), "error.CLIENTES_MODIFICAR", se); // return NavigationResults.MOSTRAR_ERROR; throw se; } return NavigationResults.VOLVER_LISTADO_CLIENTES; } ... } NORMA JSFAnotacion Las clases que representan los Managed Beans de JSF deberán tener la anotación “@Component”. NORMA JSFMBAtributos Los atributos de un managed bean se definirán como privados, con métodos get y set para aquellas propiedades que vayan a ser vinculadas a un componente de una página JSF. PRACTICA BUENA JSFMBunico Se recomienda crear un managed bean por cada página JSF, de tal manera que tanto los datos como el comportamiento de esta página sean manejados por el bean en cuestión. Un managed bean no debería mezclar atributos o comportamientos de dos páginas que no estén relacionadas. 56 de 198 Framework Atlas Normativa El acceso a los datos persistentes deberá realizarse a través de la capa de negocio, haciendo uso de la fachada que dicha capa expondrá a tal efecto. Además no está permitida la invocación directa a servicios de negocio sin pasar por la fachada. class j sf ClientesBean Página JSF - cliente: Cliente = null clientesScroller: HtmlDataScroller = new HtmlDataScr... facade: GestionFacade nombreCliente: String = null orderAndFilterClientes: OrderAndFilterBean = null serialVersionUID: long = 1L {readOnly} + + + + + + + + + + + + + + + + + + + + + cargarCliente() : String ClientesBean() filtrar() : String getCliente() : Cliente getClientesScroller() : HtmlDataScroller getFacade() : GestionFacade getNombreCliente() : String getOrderAndFilterClientes() : OrderAndFilterBean getTimeZone() : T imeZone guardarCliente() : String nuevoCliente() : String obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int setCliente(Cliente) : void setClientesScroller(HtmlDataScroller) : void setEstadoCivil(String) : void setFacade(GestionFacade) : void setIdEstadoCivil(String) : void setNombreCliente(String) : void setOrderAndFilterClientes(OrderAndFilterBean) : void volver() : String «interface» facade::GestionFacade + -facade + + + + + + deleteCliente(Cliente) : void insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int updateCliente(Cliente) : void NORMA JSFFacade 6.2.2.1 El acceso a la capa de negocio desde los managed beans siempre se debe hacer a través de la fachada. Esto implica que desde las clases managed beans no se puede invocar ni DAOs ni ningún servicio que no sea la fachada. Manejo de excepciones JSF no ofrece un mecanismo automático para el manejo de las excepciones producidas dentro de los managed beans, aunque si dispone de ciertos elementos que ayudan en la gestión de las mismas. Dentro del API de JSF existe una clase que permite mostrar mensajes genéricos (normalmente mensajes de error) llamada FacesMessage. Añadiendo un objeto de esta clase al contexto de la JSF, este mensaje se puede mostrar en cualquier JSF mediante una etiqueta estándar. Mediante el uso de esta clase, podemos tratar las excepciones de los beans de la aplicación, de forma que cuando se produzcan se almacene uno de estos mensajes: 57 de 198 Framework Atlas Normativa JSFException Todos los métodos de los managed beans que hagan uso de la fachada, tratarán las excepciones que esta pueda lanzar, que siempre serán de tipo “ServiceException” o clases que hereden de esta. La forma de manejar la excepción dependerá del origen de la misma, distinguiendo entre NORMA excepciones de negocio (excepción creada a medida) y excepciones del sistema. o En el primer caso, se atrapará la excepción y se implementará el código que deseemos que se ejecute en base a las reglas de nuestro negocio. Es decir, si por ejemplo se produce una supuesta excepción (creada a medida) “BlockedUserException” indicando que un usuario está bloqueado, se podría implementar una funcionalidad que redirija la petición inicial a otra aplicación externa que permita desbloquear la cuenta del usuario. o En el segundo caso, siempre se redirigirá a una página de error que extraerá la excepción encapsulada dentro del “ServiceException” (como por ejemplo una “DataAccessException”) mostrando un mensaje “amigable” al usuario final en función de la excepción manejada. Los métodos del bean podrían manejar las excepciones de la siguiente forma: Ejemplo de manejo de excepciones /** * Este metodo inserta o modifica un cliente en el sistema. * * @throws atlas.core.exceptions.ServiceException Lanza * atlas.core.exceptions.ServiceException ante cualquier error * producido. * @return <code>java.lang.String</code> Devuelve la regla de navegacion * <code>NavigationResults.VOLVER_LISTADO_CLIENTES</code>. */ public String guardarCliente() throws ServiceException { try { facade.insertOrUpdateCliente(cliente); } catch (ServiceException se) { } AtlasFacesUtils.storeOnRequestError(FacesContext.getCurrentInstance(), "error.CLIENTES_MODIFICAR", se); throw se; } return NavigationResults.VOLVER_LISTADO_CLIENTES; } Cuando se produce una excepción, el método está almacenando un mensaje en el contexto de JSF. Para presentar el error tendríamos que incluir en la página JSF la etiqueta h:message. 58 de 198 Framework Atlas Normativa PRACTICA BUENA JSFStoreError Para enviar el mensaje de error de una excepción a la página jsf se recomienda utilizar el método storeOnRequestError de la clase atlas.componentes.utiles.AtlasFacesUtils. Este metodo deja en el contexto de JSF el mensaje de error para que luego pueda se capturado por la etiqueta h:message. También se manejarán las excepciones que puedan producirse en otros puntos del bean (constructor, método init, listeners, etc.). 6.2.2.2 Navegación JSFNavegacion Los valores posibles para la navegación dinámica de los managed beans se han de almacenar en NORMA una clase aparte, para tenerlos todos localizados en un mismo lugar. Esta clase debe llamarse NavigationsResults y ubicarse en el paquete jsf de cada bloque funcional. En el caso de que se tengan varios bloques funcionales hay que añadir por delante el nombre del bloque funcional para poder distinguir una clase de otra. (Ejemplo <bloquefuncional>NavigationResults). En esta clase se definirán como constantes (public static final String) todos los caminos de la navegación. A continuación se muestra un ejemplo de esta clase NavigationResults.java package ejpl.gestion.jsf; /** * Esta clase representa constantes asociadas * a las reglas de navegacion de la aplicacion. * @author ICM * @version 1.0. * @since Atlas 1.0.0. */ public final class NavigationResults { /** * Constructor para que no se genere el publico por defecto 59 de 198 Framework Atlas Normativa */ protected NavigationResults() { } /** * Operacion de navegacion: Resultado de la operacion correcto. */ public static final String SUCCESS = "success"; /** * Operacion de navegacion: Resultado de la operacion fallido. */ public static final String FAILURE = "failure"; /** * Operacion de navegacion: Salir de la aplicacion. */ public static final String LOGOUT = "logout"; /** * Operacion de navegacion: Nuevo Cliente. */ public static final String NUEVO_CLIENTE = "nuevoCliente"; /** * Operacion de navegacion: Modificar Cliente. */ public static final String MODIFICAR_CLIENTE = "modificarCliente"; /** * Operacion de navegacion: Eliminar Cliente. */ public static final String ELIMINAR_CLIENTE = "eliminarCliente"; /** * Operacion de navegacion: Volver al listado de Clientes. */ public static final String VOLVER_LISTADO_CLIENTES = "volverListadoClientes"; /** * Operacion de navegacion: Mostrar pagina de error. */ public static final String MOSTRAR_ERROR = "mostrarError"; } Los métodos de las clases managed beans deberán utilizar estas variables en la respuesta de los métodos de acción tal y como se puede ver en los ejemplos anteriormente expuestos. Los elementos de navegación indicados en el fichero NavigationResults deberán ser utilizados en el fichero de JSF de configuración de la navegación tal y como se comenta en el apartado 2.1.3.3 facesnavigation.xml. 60 de 198 Framework Atlas Normativa 6.2.2.3 Inicialización de los Beans (@PostContruct) Algunas veces se necesita realizar alguna acción nada más crearse un bean. Por ejemplo el caso que necesitemos recoger en un Bean los parámetros que se pasan por la URL, o por cualquier otra causa. Si se anota un método de un bean con @PostContruct este método se llamará nada más crear el bean. Ejemplo de un método que recoge el parámetro token de la url. Ejemplo de miBean.java @PostConstruct public void inicializarBean() { String token = AtlasFacesUtils.getRequestParameter("token"); setAppToken(token); … } 6.2.3 Configuración de JSF Para realizar la configuración necesaria para los componentes JSF de las aplicaciones del framework Atlas tenemos que tener en cuenta que esta configuración se encuentra dentro de tres ficheros. Estos ficheros los podemos encontrar en el arquetipo web previamente configurados en el directorio src/main/webapp/WEB-INF. Fichero de configuración Descripción faces-config.xml Fichero principal de configuración de JSF. No se puede modificar este fichero. faces-managed-beans.xml Fichero donde se definen los managed beans de la aplicación en caso de no usar anotaciones. faces-navigation.xml Fichero donde se configuran las reglas de navegación de la aplicación. 6.2.3.1 faces-config.xml El fichero de configuración faces-config.xml ya incluye: o Configuración de los resolver de variables y propiedades que permiter inyectar beans de Spring en los managed beans. o Configuración de los ficheros de mensajes y de los locales. 61 de 198 Framework Atlas Normativa NORMA JSFfacesconfigxml La configuración que se encuentra dentro del fichero faces-config.xml del arquetipo no se puede modificar. En el caso de que se desee modificar se debe solicitar la correspondiente autorización a ICM justificando dicha necesidad. 6.2.3.2 faces-managed-beans.xml La definición de los managed beans puede hacerse de dos maneras: mediante un fichero de configuración o con anotaciones, para el primer caso utilizaremos el fichero faces-managed-beans.xml. La forma de añadir managed beans es la siguiente: Ejemplo de configuración de managed bean <managed-bean> <description>Bean de clientes</description> <managed-bean-name>clientesBean</managed-bean-name> <managed-bean-class> ejpl.gestion.jsf.ClientesBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>facade</property-name> <value>#{facade}</value> </managed-property> <managed-property> <property-name>orderAndFilterClientes</property-name> <value>#{orderAndFilterClientes}</value> </managed-property> </managed-bean> Uso del contexto dentro del faces-managed-beans.xml El contexto de una aplicación Web permite el almacenamiento de información relevante a lo largo de la ejecución de diversas operaciones por parte del usuario. Las decisiones sobre el mantenimiento del estado tienen impacto en el rendimiento de la aplicación, así como en la disponibilidad y la escalabilidad. Estas decisiones incluyen elegir la capa de la aplicación donde manejar el estado, el ámbito apropiado para cada elemento a almacenar y como mantener el estado en un entorno distribuido. En las aplicaciones JEE el estado tiene distintos ámbitos, entendiéndose como ámbito a los distintos lugares desde donde ese estado es accesible. Resumiendo, se puede decir que el estado en la capa de presentación se puede mantener en cuatro ámbitos. 62 de 198 Framework Atlas Normativa JSF amplia estos ámbitos, permitiendo guardar y restaurar el estado de los componentes para cada petición tanto en el cliente como en el servidor: Ámbito Descripción Aplicable sólo a páginas JSF contiene datos que solo son válidos en el contexto de una Página página. Cuando una JSF redirige o incluye a otra, cada página define su propio estado. Petición Permite almacenar información que será accesible por todos los componentes Web que intervengan en esa petición hasta que se genere la respuesta al usuario. Sesión Permite almacenar información que será accesible por todos los componentes Web durante la sesión del usuario, que durará desde que el usuario entre en la aplicación hasta que salga de ella o transcurra un tiempo máximo de inactividad. Aplicación Permite almacenar información que será accesible por todos los componentes de la aplicación web en cualquier momento (mientras la aplicación esté activa). Cliente El árbol de componentes JSF se guarda en un campo oculto dentro de la petición Http Servidor El árbol se almacena en la sesión Http NORMA Para definir el contexto de un managed bean se utiliza el atributo managed-bean-scope. JSFRequest Los managed beans deben ser siempre de ámbito request, pudiendo ser de ámbito sesión tan sólo en casos excepcionales y justificados. Atlas amplia este modelo haciendo posible escribir aplicaciones sin necesidad del uso del HttpSession. Toda la información tanto de la vista como del modelo (managed beans) puede ser codificada y enviada al cliente. Esto se lleva a cabo mediante una etiqueta presente en la librería de componentes de Atlas: <atlas:guardarEstado> <atlas:guardarEstado id="save1" value="#{calcForm.number1}" /> El único requisito para poder almacenar un objeto completo, es que el bean implemente el interfaz java.io.Serializable 63 de 198 Framework Atlas Normativa JSFSavestate El problema principal del almacenamiento de información (tanto del árbol de componentes PRACTICA BUENA como de los managed beans) es el rendimiento. El tiempo de serialización y deserialización de los objetos aumenta considerablemente el tiempo de respuesta ante una petición, del mismo modo que el ancho de banda consumido (y por tanto de tiempo de transferencia de las páginas). Por lo tanto se recomienda reducir el uso del componente guardarEstado a casos imprescindibles. 6.2.3.3 faces-navigation.xml El fichero de configuración faces-navigation.xml incluye las reglas de navegación de JSF. Presenta dos tipos de navegación: · Estática: cuando desde una página se va directamente a otra. Esto se hace definiendo las reglas de navegación en el fichero de configuración. · Dinámica: cuando una acción o cierta lógica determina la página a la que navegar. Esto lo soporta permitiendo que los componentes definan como destino de su navegación el resultado de una consulta a un manejador de acciones, donde se codifica la navegación dinámica, frente a la definición de un destino fijo. A continuación se muestra un ejemplo de las reglas de navegación para una aplicación simple: 64 de 198 Framework Atlas Normativa Ejemplo de faces-navigation.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <!-- ============================================================== --> <!-Fichero donde se definen todas --> <!-las reglas de navegación de la aplicación --> <!-- ============================================================== --> <faces-config> <navigation-rule> <description> Reglas de navegacion para la pagina index.xhtml </description> <from-view-id>/secure/index.xhtml</from-view-id> <navigation-case> <from-outcome>nuevoCliente</from-outcome> <to-view-id>/secure/formularioCliente.xhtml</to-view-id> </navigation-case> <navigation-case> <from-outcome>modificarCliente</from-outcome> <to-view-id>/secure/formularioCliente.xhtml</to-view-id> </navigation-case> <navigation-case> <from-outcome>eliminarCliente</from-outcome> <to-view-id>/secure/index.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <description> Reglas de navegacion para la pagina formularioCliente.xhtml </description> <from-view-id>/secure/formularioCliente.xhtml</from-view-id> <navigation-case> <from-outcome>volverListadoClientes</from-outcome> <to-view-id>/secure/index.xhtml</to-view-id> </navigation-case> </navigation-rule> … NORMA </faces-config> JSFNavDes Se ha de ofrecer un comentario explicativo en el atributo description para cada regla de navegación definida en el archivo de configuración navigation-rule.xml Mediante reglas de navegación de JSF se puede hacer uso de patrones, de forma que una serie de páginas lleven a una dada: 65 de 198 Framework Atlas Normativa Ejemplo de regla de navegación con patrones <navigation-rule> <description> Regla de navegación para todas las páginas de la carpeta pages </description> <from-view-id>/pages/*</from-view-id> <navigation-case> <from-outcome>menu</from-outcome> <to-view-id>/menu/main_main.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>info</from-outcome> <to-view-id>/menu/info.jsp</to-view-id> </navigation-case> </navigation-rule> También se pueden especificar destinos “globales” de forma que desde cualquier página se pueda navegar una dada. El siguiente ejemplo muestra como con esta característica se puede implementar una opción de ayuda global para la aplicación: Ejemplo de regla de navegación global <navigation-rule> <navigation-case> <from-outcome>globalhelp</from-outcome> <to-view-id>/menu/generalHelp.jsp</to-view-id> </navigation-case> </navigation-rule> 66 de 198 Framework Atlas Normativa 6.2.3.4 Archivos de configuración adicionales y web.xml JSFConfAdicional Si el tamaño de los ficheros faces-managed-beans.xml o faces-navigation.xml creciese en exceso, se permite crear ficheros adicionales que agrupen los beans/reglas por funcionalidad. NORMA Dichos ficheros deberán denominarse: - faces-managed-beans-yyyy.xml - faces-navigation-yyyy.xml Donde yyyy puede ser cualquier término en minúsculas que sea representativo de la funcionalidad que agrupan los ficheros. Además, en el parámetro javax.config.CONFIG_FILES del archivo web.xml del proyecto deberá añadirse referencias a los nuevos ficheros de configuración. El fichero de configuración web.xml del arquetipo ya viene preconfigurado con todos los parámetros de configuración de JSF. NORMA JSFwebxml La configuración de JSF que se encuentra en el arquetipo dentro del fichero de configuración web.xml no se puede modificar (excepto el parámetro javax.config.CONFIG_FILES si se incluyesen ficheros de configuración adicionales). En el caso de que se desee modificar se debe solicitar la correspondiente autorización a ICM justificando dicha necesidad. 6.2.3.5 Anotaciones Como se ha comentado previamente existe la posibilidad de declarar un managed bean mediante anotaciones. El efecto de declarar un bean con anotaciones o en el faces-managed-beans.xml es el mismo. Para declarar un bean usaremos la anotación @ManagedBean. La anotación tiene un atributo name, pero si no se especifica el nombre por defecto del bean será el de la clase con la primera letra minúscula. Para especificar el ámbito del bean se utilizará la anotación @RequestScoped (@SessionScoped, @ApplicationScoped… para otros ámbitos). 67 de 198 Framework Atlas Normativa Para inicializar propiedades del bean se utiliza la anotación @ManagedProperty en la declaración de la propiedad en el bean. La anotación tiene la propiedad value, que puede tener un valor literal o bien referenciar otro objeto en el contexto. Las anotaciones anteriores están en el paquete javax.faces.bean. A continuación se muestra un ejemplo de anotaciones sobre la clase ClienteBean. ClienteBean.java package ejpl.gestion.jsf; … /** * Bean de cliente */ @ManagedBean @RequestScope public class ClienteBean { /** * Servicio de la fachada */ @ManagedProperty(value=”#{facade}”) private GestionFacade facade; /** * Bean para orden y filtro del listado */ @ManagedProperty(value=”#{orderAndFilterCliente}”) private OrderAndFilterBean orderAndFilter; … } 68 de 198 Framework Atlas Normativa 6.2.4 Uso de la Sesión En el servidor de aplicaciones se crea un objeto sesión por cada usuario que se conecta, y se mantiene allí durante un tiempo. Cuando una aplicación tiene mucha concurrencia, esto puede ser un problema grave en un entorno de producción debido a la cantidad de memoria ocupada por estas sesiones. La situación se complica en un entorno de clúster, en el que la información de sesión tiene que replicarse entre 2 o más instancias del servidor de aplicaciones. JSFSesion NORMA El contenido de la sesión nunca debe exceder los 4 Kbytes de tamaño Cuando sea necesario almacenar una cantidad de información importante (superior a 4Kbytes) durante un tiempo de vida superior a la petición, siempre y cuando haya sido previamente autorizado por ICM, se implementará el mecanismo de persistencia en BBDD indicado por el framework Atlas. En cualquier caso se deben eliminar de la sesión los datos cuando ya no sean necesarios. NORMA JSFHttpSession Se debe minimizar el uso del objeto HttpSession. En caso de que se necesite solamente se podrá utilizar el objeto HttpSesion desde los managed beans. NORMA NORMA JSFTiempoSesion El tiempo de vida de la sesión será establecido a nivel del servidor de aplicaciones, nunca se definirá a nivel de la aplicación. Por tanto las aplicaciones no podrán depender de un valor concreto de dicho tiempo para su correcto funcionamiento. JSFUsoSesion Cada vez que se acceda a un objeto de la sesión se debe comprobar previamente la existencia de dicho objeto y actuar en consecuencia, para prevenir errores ante una pérdida de sesión. 69 de 198 Framework Atlas Normativa NORMA JSFCreacionSesion La sesión será creada automáticamente por el framework por lo tanto las aplicaciones no pueden crearla, esto significa que no se puede obtener el objeto sesión de la siguiente forma: request.getSession(true). 6.3 PRACTICA BUENA JSFAtlasFacesUtils Para obtener o establecer elementos en la sesión utilizar los métodos creados para ellos en la clase atlas.componentes.utiles.AtlasFacesUtils. También hay métodos similares para el ámbito request. SERVICIOS DE NEGOCIO Los servicios de negocio son aquellos que implementan la lógica que complementa las operaciones de acceso a datos para cubrir los requisitos de negocio de una aplicación. La arquitectura de aplicaciones del framework Atlas busca simplificar la creación e integración de aplicaciones de negocio, por lo que está construida en base a una arquitectura orientada a servicios (SOA). En una arquitectura SOA, los servicios de negocio no tienen porqué ser implementados como servicios web. El uso de servicios web debería limitarse a aquellos casos en los que realmente se vaya a sacar provecho a esta aproximación. Como norma general, se expondrán como servicios web aquellos servicios con una funcionalidad de negocio que sea susceptible de ser reutilizada en otras aplicaciones, que ofrezcan una granularidad 1 gruesa e interfaces bien definidos. En este tipo de servicios, los interfaces han de definir el intercambio de datos de negocio, no el intercambio de objetos. Para obtener mas información sobre los servicios web dentro del framework Atlas ir al apartado 8. SERVICIOS WEB. Para el resto de casos se emplearán servicios de negocio implementados como clases Java simples (POJOs) con una clara orientación a servicio, haciendo uso de las funcionalidades que Spring ofrece. 1 Nivel de granularidad en la que el interfaz del servicio define relativamente pocos métodos de servicio para conseguir un objetivo de negocio, mediante parámetros orientados a documento 70 de 198 Framework Atlas Normativa De esta forma en un momento dado uno de estos servicios puede ser expuesto como servicio web para ser empleado por otras aplicaciones. Los beneficios de esta aproximación son los siguientes: · Simplificación en el desarrollo de componentes de negocio. · Simplificación del ensamblaje y despliegue de soluciones de negocio construidas como redes de servicios. · Aumento de la flexibilidad y agilidad. · Protección de la inversión en tecnología y lógica de negocio existente. · Simplificación de las pruebas. Dentro de la capa de servicios vamos a identificar dos tipos de elementos: o Fachada o Servicios La siguiente figura muestra un ejemplo de una parte de la capa de servicios del framework ATLAS: class facade «interface» GestionFacade + + + + + + + serv ices::ClienteServ iceImpl deleteCliente(Cliente) : void insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int updateCliente(Cliente) : void - clienteDAO: ClienteDAO + + + + + + + + + ClienteServiceImpl() deleteCliente(Cliente) : void insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int setClienteDAO(ClienteDAO) : void updateCliente(Cliente) : void GestionFacadeImpl - clienteService: ClienteService + + + + + + + + + deleteCliente(Cliente) : void GestionFacadeImpl() insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int setClienteService(ClienteService) : void updateCliente(Cliente) : void «interface» services::ClienteService + -clienteService + + + + + + deleteCliente(Cliente) : void insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List <Cliente> obtenerTotalClientes(Object) : int updateCliente(Cliente) : void ATENCION Aunque en este ejemplo se muestra solamente un servicio lo normal es que la fachada acceda a varios servicios. Los servicios se separarán en bloques funcionales para facilitar el mantenimiento posterior de la aplicación. Cada bloque funcional estará formado por los objetos de dominio, los DAOs, los servicios y la fachada. 71 de 198 Framework Atlas Normativa 6.3.1 FACHADA En primer lugar nos encontramos con la fachada que será el punto central de acceso a los servicios de negocio de un bloque funcional. Los componentes de la capa de presentación invocarán por tanto a esta fachada. La fachada constituye el lugar idóneo para poder gestionar de forma sencilla los aspectos transversales a la arquitectura, tales como las transacciones, la seguridad, la auditoria de acceso a información protegida y las trazas. SNFacade Dentro de una aplicación en cada bloque funcional se ha de crear un servicio que haga de 2 “fachada” al resto de servicios de negocio. NORMA Las responsabilidades de esta fachada son las siguientes: o Manejar las peticiones de la capa de presentación. o Recuperar los datos (en forma de objetos de dominio) que requiere la capa de presentación. o Usar inyección de dependencias para crear los servicios de negocio. o Delegar la ejecución a los servicios de negocio. Cada bloque funcional deberá tener una fachada y solo puede haber una fachada por cada bloque funcional. De esta manera, para acceder a la lógica de negocio de la aplicación se empleará siempre esta fachada. Esto reduce el número de objetos a usar desde el cliente y el acoplamiento con la capa de servicios de negocio, ya que un servicio puede ser reemplazado o modificado sin afectar a la capa de presentación de la aplicación. De forma general, la fachada delegará la ejecución de los métodos de negocio al correspondiente servicio de negocio (que serán los que gestionen entre otras cosas la transaccionalidad). Aunque no es lo recomendado, en ocasiones especiales se puede definir en la fachada algún método de más alto nivel que implique el uso de varios servicios de negocio. 2 El patrón de diseño Facade (fachada) sirve para proveer de una interfaz unificada sencilla que haga de intermediaria entre un cliente y una interfaz o grupo de interfaces más complejas. 72 de 198 Framework Atlas Normativa PRACTICA BUENA SNFacadeWS En el caso de módulos de tipo servicio web la fachada no tiene sentido. Los que se publican como servicios son los propios servicios de negocio. Si intervienen varios servicios de negocio se puede crear un servicio de alto nivel que contenga la lógica de negocio e invoque al resto de servicios. SNFacadeImpl NORMA Para crear una fachada se crearán dos clases, con la siguiente nomenclatura: o <nombre>Facade (Interfaz de la fachada) o <nombre>FacaceImpl (Implementación de la interfaz) Donde <nombre> debe ser sustituido por el nombre del bloque funcional al que pertenece la fachada. Estas clases se incluirán en el paquete services.facade del bloque funcional correspondiente. class facade «interface» GestionFacade + + + + + + + deleteCliente(Cliente) : void insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int updateCliente(Cliente) : void GestionFacadeImpl - clienteService: ClienteService + + + + + + + + + deleteCliente(Cliente) : void GestionFacadeImpl() insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int setClienteService(ClienteService) : void updateCliente(Cliente) : void Una de las implicaciones más importantes al trabajar con JSF es que de alguna manera lo que se presenta al usuario dentro de un formulario es el propio objeto de dominio, generados por la capa de acceso de datos y obtenidos a través de la fachada. 73 de 198 Framework Atlas Normativa NORMA SNDominio Los métodos de la fachada utilizarán objetos de dominio (esto es, los que representan los datos de la aplicación) cuando sea necesario. No es necesario crear clases adicionales (los viejos DTO, Data Transfer Objects) para enviar este tipo de datos. A continuación se muestra un ejemplo de interfaz e implementación de una fachada. Ejemplo de interfaz de una fachada package ejpl.gestion.services.facade; import java.util.List; import ejpl.gestion.domain.Cliente; import atlas.core.exceptions.ServiceException; /** * Esta interfaz representa las operaciones * de la facacha del sistema. * @author ICM * @version 1.0 * @since ATLAS 1.0.0 */ public interface GestionFacade { /** * Este metodo inserta un nuevo cliente en el sistema. * * @param cliente Cliente a insertar. * @throws atlas.core.exceptions.ServiceException * Lanza atlas.core.exceptions.ServiceException ante cualquier error producido. */ void insertCliente(Cliente cliente) throws ServiceException; /** * Este metodo obtiene un Cliente a partir de la PK. * * @param idCliente PK del cliente. * @throws atlas.core.exceptions.ServiceException * Lanza atlas.core.exceptions.ServiceException ante cualquier error * * @return <code>ejpl.gestion.domain.Cliente</code> que representa el Cliente encontrado o null en caso contrario. */ Cliente obtenerClientePorId(Integer idCliente) throws ServiceException; 74 de 198 Framework Atlas Normativa Ejemplo de implementación de una fachada package ejpl.gestion.services.facade; import import import import import java.util.List; atlas.core.exceptions.ServiceException; org.springframework.stereotype.Service; ejpl.gestion.domain.Cliente; ejpl.gestion.services.ClienteService; /* Esta clase representa la fachada del sistema. * @author ICM * @version 1.0 */ @Service public class GestionFacadeImpl implements GestionFacade { /** * El Servicio de Clientes */ private ClienteService clienteService; /** * Constructor sin argumentos. */ public GestionFacadeImpl() { } /** * Este metodo inyecta el servicio ClienteService. * @param clienteService El servicio a inyectar. */ public void setClienteService(ClienteService clienteService) { this.clienteService = clienteService; } /** * {@inheritDoc} * @see ejpl.gestion.services.facade.GestionFacade#insertCliente(ejpl.gestion.domain.Cliente) */ public void insertCliente(Cliente cliente) throws ServiceException { clienteService.insertCliente(cliente); } /** * {@inheritDoc} * * @see ejpl.gestion.services.facade.GestionFacade#obtenerClientePorId(java.lang. * Integer) */ public Cliente obtenerClientePorId(Integer idCliente) throws ServiceException { return clienteService.obtenerClientePorId(idCliente); } 75 de 198 Framework Atlas Normativa 6.3.2 SERVICIOS Como ya se ha comentado anteriormente los servicios implementarán la lógica de negocio de la aplicación. SNServiceImpl NORMA Para crear un servicio se crearán dos clases, con la siguiente nomenclatura: o <nombre>Service (Interfaz del servicio) o <nombre>ServiceImpl (Implementación del servicio) Donde <nombre> debe ser sustituido por el nombre del servicio. Estas clases se incluirán en el paquete services del bloque funcional correspondiente. class serv ices «interface» ClienteService + + + + + + + deleteCliente(Cliente) : void insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List <Cliente> obtenerTotalClientes(Object) : int updateCliente(Cliente) : void NORMA ClienteServ iceImpl - clienteDAO: ClienteDAO + + + + + + + + + ClienteServiceImpl() deleteCliente(Cliente) : void insertCliente(Cliente) : void insertOrUpdateCliente(Cliente) : void obtenerClientePorId(Integer) : Cliente obtenerClientes(int, int, Object, Object) : List<Cliente> obtenerTotalClientes(Object) : int setClienteDAO(ClienteDAO) : void updateCliente(Cliente) : void SNAnotacion Todos las implementaciones de los servicios deberán ir precedidos de la anotación @Service. 76 de 198 Framework Atlas Normativa SNMVC NORMA La capa de negocio debe ser totalmente independiente de la capa de presentación, es decir nunca se accederá de manera directa desde los servicios de negocio a información de otras capas (por ejemplo, a la sesión Http). Toda la información requerida por los métodos de un servicio se le ha de pasar como parámetro. Hay que tener en cuenta que cualquier servicio de negocio puede ser transformado en un servicio web en un momento dado, y por tanto debe ser independiente. Para facilitar la tarea de implementación de las operaciones CRUD en los Servicios, se proporciona dentro del arquetipo una interfaz llamada BaseService y su correspondiente implementación, con los métodos básicos ya implementados de tal forma que podemos crear nuestros servicios heredando de esta clase e implementando solo aquellos métodos que sean específicos de nuestro servicio. A continuación se muestra la interfaz BaseService: package ejpl.services; import java.io.Serializable; import java.util.List; import java.util.Map; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Order; import atlas.core.exceptions.ServiceException; import ejpl.dao.BaseDAO; /** * Interfaz de servicio genérico con funcionalidad CRUD * * <p>Extiende esta interfaz si se requiere servicios para los objetos de modelo sin * necesidad de realizar cast de conversión de datos. * * @param <T> el tipo de objeto que manejará este servicio. * @param <PK> la clave primaria del objeto de dominio. * @param <D> el dao que maneja el objeto. */ public interface BaseService <T, PK extends Serializable, D extends BaseDAO<T, PK>> { /** * Establece el valor del DAO * @param dao El DAO */ void setDao(D dao); /** * Devuelve el valor del DAO * @return el DAO */ D getDao(); /** * Método genérico usado para obtener todos los objetos de un tipo * particular. Este método es equivalente a obtener todas las filas * de una tabla. * 77 de 198 Framework Atlas Normativa * <p>El número total de elementos que correspondería al método * countAll() se puede obtener a través del método size() del objeto * de lista devuelto.</p> * * @return Lista de los objetos recuperados de BD * @throws ServiceException Error en la invocación */ List<T> findAll() throws ServiceException; /** * Método genérico usado para obtener el total de objetos de un tipo * particular. * @return número de elementos totales en la tabla. * @throws ServiceException Error en la invocación */ Long countAll() throws ServiceException; /** * Obtiene todos los registros sin duplicados. * <p>Si se utiliza este método, es imperativo que las clases de * modelo implementen correctamente los métodos hashcode/equals.</p> * * <p>El número total de elementos que correspondería al método * countAllDistinct() se puede obtener a través del método size() del * objeto de lista devuelto.</p> * * @return Lista de los objetos recuperados de BD * @throws ServiceException Error en la invocación */ List<T> findAllDistinct() throws ServiceException; /** * Obtiene en número total de registros sin duplicados. * @return número de elementos totales sin duplicados. * @throws ServiceException Error en la invocación */ Long countAllDistinct() throws ServiceException; /** * Método genérico para obtener un objeto basado en el tipo de clase * y su identificador único. Si no se encuentra el objeto, este método * devolverá null. * * @param id el identificador (clave primaria) del registro a obtener * @return el objeto de base de datos recuperado * @throws ServiceException Error en la invocación */ T find(PK id) throws ServiceException; /** * Método para obtener una serie de elementos del sistema dados unos ordenes y filtros * @param index Indice de paginacion actual. * @param pageSize Tamaño de pagina. * @param orders Criterios de ordenacion * @param filters Filtros de busqueda. * @return <code>java.util.List</code> La lista de objetos encontrados * @throws ServiceException Error en la invocación */ List<T> find(int index, int pageSize, Order[] orders, Criterion[] filters) throws ServiceException; /** * Método para obtener el numero de elementos dada una serie de filtros * @param filters Filtro de busqueda. * @return <code>int</code> con el numero total de objetos encontrados. * @throws ServiceException Error en la invocación */ int count(Criterion[] filters) throws ServiceException; /** * Comprueba la existencia de un objeto en base a su clave primaria. * * @param id el identificador de la entidad * @return - true si el objeto existe, false en caso contrario * @throws ServiceException Error en la invocación */ 78 de 198 Framework Atlas Normativa boolean exists(PK id) throws ServiceException; /** * Método genérico para grabar un objeto (maneja objetos nuevos y modificados). * Si el objeto es nuevo, este se devolverá con la clave primaria generada para * su inserción en base de datos. * * @param object el objeto a guardar * @return el objeto persistente * @throws ServiceException Error en la invocación */ T insert(T object) throws ServiceException; /** * Método genérico para grabar un objeto (maneja objetos nuevos y modificados). * Si el objeto es nuevo, este se devolverá con la clave primaria generada para * su inserción en base de datos. * * @param object el objeto a guardar * @throws ServiceException Error en la invocación */ void insertOrUpdate(T object) throws ServiceException; /** * Método genérico para grabar actualizar un objeto * * @param object el objeto a guardar * @throws ServiceException Error en la invocación */ void update(T object) throws ServiceException; /** * Método genérico para eliminar un objeto de la base de datos en base a su * clave primaria. * * @param id el identificador (clave primaria) del registro a obtener * @throws ServiceException Error en la invocación */ void delete(PK id) throws ServiceException; /** * Método genérico para eliminar un objeto de la base de datos * * @param object el objeto a eliminar * @throws ServiceException Error en la invocación */ void delete(T object) throws ServiceException; /** * Encuentra una lista de registos usando una 'named query'. * * @param queryName nombre de la consulta a ejecutar * @param queryParams un objeto Map con los nombres de los parámetos y sus valores * @return una lista con los registros encontrados * @throws ServiceException Error en la invocación */ List<T> findByNamedQuery(String queryName, Map<String, Object> queryParams) throws ServiceException; } La implementación de esta clase se puede ver en el paquete dao en la clase BaseServiceImpl. PRACTICA BUENA ADBaseService En el caso de que en el proyecto se identifiquen otros métodos comunes a todos los Servicios estos métodos se incorporaran en la interfaz BaseService y en su correspondiente implementación. 79 de 198 Framework Atlas Normativa La creación de nuevos servicios se realizará utilizando los mecanismos de herencia sobre la clase BaseService. Dentro de los arquetipos se ha incluido un ejemplo de nuevo servicio que accede a la tabla de clientes: ClienteService. A continuación se muestra un posible código de ejemplo para las clases ClienteService y ClienteServiceImpl, que heredan de BaseService y no añaden funcionalidad a la clase padre (pero podrían hacerlo): Ejemplo: ClienteService package ejpl.services; import ejpl.domain.Cliente; import ejpl.dao.ClienteDAO; /** * Interfaz para el Servicio de la clase de dominio Cliente * @see ejpl.Cliente * Fecha: 20-feb-2012 15:43:54 */ public interface ClienteService extends BaseService<Cliente, Integer, ClienteDAO> { } Ejemplo: ClienteServiceImpl package ejpl.services; import import import import import ejpl.domain.Cliente; ejpl.dao.ClienteDAO; org.springframework.stereotype.Service; org.springframework.transaction.annotation.Propagation; org.springframework.transaction.annotation.Transactional; /** * Implementación del servicio para la clase de dominio Cliente * @see ejpl.Cliente * Fecha: 20-feb-2012 15:43:54 */ @Service @Transactional (readOnly = false, propagation = Propagation.REQUIRED) public class ClienteServiceImpl extends BaseServiceImpl<Cliente, Integer, ClienteDAO> implements ClienteService { } Nota Los servicios se deben inyectar en el contexto de Spring en el fichero applicationContext-services.xml 80 de 198 Framework Atlas Normativa 6.3.3 INYECCION DE DEPENDENCIAS La fachada y los servicios se deben incluir en los ficheros de configuración de Spring. Para homogeneizar los desarrollos se establece que los ficheros de configuración de Spring se incluyan en la carpeta NORMA src/main/resources/conf. SNSpring Los ficheros de configuración de Spring se incluirán en la carpeta src/main/resources/conf. A continuación se muestra un ejemplo de ficheros de configuración tal y como los podemos encontrar dentro de alguno de los arquetipos. En el arquetipo de módulos de tipo librería en lugar de todos los ficheros anteriores solamente aparece un fichero de configuración de Spring llamado applicationContext-yyyy.xml donde yyyy se corresponde con el nombre de la librería. Este fichero de contexto irá incluido dentro del jar de la librería y en las aplicaciones que utilicen esta librería, deberán referenciarlo dentro del parámetro contextConfigLocation del fichero web.xml de las aplicaciones en las que se utilice la librería. SNSpringLIB NORMA Cuando se desarrolle un módulo de tipo librería se creará un fichero de contexto con la nomenclatura applicationContext-yyyy.xml donde yyyy se corresponde con el nombre del módulo. Este fichero se situará en el directorio conf de la librería para que se incluya dentro del jar de esta librería. Este fichero será el único de esta librería que se referenciará en el parámetro contextConfigLocation del fichero web.xml de las aplicaciones en las que se utilice la librería. 81 de 198 Framework Atlas Normativa SNDependencias El fichero de configuración de Spring donde se definen los servicios y la fachada se debe llamar NORMA applicationContext-services.xml. En el caso de que este fichero se haga muy grande se podría dividir en varios ficheros con la nomenclatura applicationContext-services-yyyy.xml donde yyyy es un nombre que identifica a este fichero. No se permite instanciar objetos de fachadas o servicios directamente. Los módulos de tipo librería en lugar de esta norma les aplica la norma SNSpringLIB. Los servicios de Spring se pueden construir en base a 5 ámbitos distintos de creación según las propiedades que se le deseen otorgar, dicho ámbitos serían: Ambito Singleton Descripción Solo se creará una instancia del servicio, la cual será compartida por “contenedor Spring”. Éste será el ámbito por defecto que adoptará Spring cuando no se especifique ningún otro. Prototype Este ámbito resulta en la creación de una nueva instancia del servicio cada vez que se realice una petición sobre el mismo. Request El ámbito del servicio es el mismo que el ciclo de vida de una petición HttpRequest. Solo tiene sentido en aplicaciones web. (No se puede utilizar) Session El ámbito del servicio es el mismo que el ciclo de vida de una sesión Http. Solo tiene sentido en aplicaciones web. (No se puede utilizar) Global Session El ámbito del servicio es el mismo que el ciclo de vida de una sesión Http Global (Ámbito de aplicación). Solo tiene sentido en aplicaciones web. (No se puede utilizar) 82 de 198 Framework Atlas Normativa SNAmbitos NORMA El ámbito de creación de los servicios en Spring debe ser Singleton, pudiendo crear servicios de ámbito Prototype única y exclusivamente en ciertos casos excepcionales, totalmente justificados y autorizados previamente por ICM. Completando lo anterior, los ámbitos de creación en Spring denominados request, session y global session no se pueden de utilizar bajo ninguna circunstancia. A continuación se muestra un ejemplo de fichero de configuración de Spring de los servicios y la fachada: applicationContext-services.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- ============================================================= --> <!-Definicion de todos los servicios de la aplicacion --> <!-- ============================================================= --> <bean id="facade" class="ejpl.gestion.services.facade.GestionFacadeImpl" p:clienteService-ref="clienteService"/> <!-- Aqui van los servicios propios del proyecto--> <bean id="clienteService" class="ejpl.gestion.services.ClienteServiceImpl" p:clienteDAO-ref="clienteDAO"/> </beans> PRACTICA BUENA SNAgrupacion Para mejor organización de los servicios dentro del fichero de contexto de Spring se recomienda organizarlos por bloques funcionales. De forma que por cada bloque funcional se incluya en el fichero de configuración de Spring lo siguiente: o Comentario con el nombre del bloque funcional o Definición del bean de la fachada o Definición de los bean de los distintos servicios. Esto facilitará tanto el desarrollo como el posterior mantenimiento de la aplicación. 83 de 198 Framework Atlas Normativa 6.3.4 MANEJO DE EXCEPCIONES Uno de los problemas con el manejo de excepciones es saber cuándo y cómo utilizarlas. En términos generales, las aplicaciones desarrolladas con el framework Atlas tendrán que ser capaces de manejar dos tipos de excepciones: · Excepciones de negocio: Serán aquellas excepciones creadas a medida por el desarrollador. Estas excepciones permiten representar aquellos errores inherentes al negocio. Serán lanzadas y gestionas por el propio programador, indicando así el incumplimiento de una regla del negocio. · Excepciones del sistema: En este grupo se engloban todas aquellas excepciones producidas de forma automática por el entorno. Serán excepciones propietarias del API, como por ejemplo, un fallo en la conexión a una base de datos, fallo de invocación a un servicio web, etc. Dentro de Atlas para normalizar el uso de excepciones se ha creado la clase ServiceException. Con esta clase lo que se pretende es que todas las excepciones que se generen en la capa de negocio y se NORMA propaguen a la capa de presentación sean de tipo ServiceException. SNThrowsException Todos los métodos de los servicios y de la fachada sólo pueden lanzar excepciones del tipo ServiceException o clases que hereden de ella. Ejemplo de excepción devuelta por un método void deleteCliente(Cliente cliente) throws ServiceException; Si en nuestra aplicación queremos crear excepciones propias del negocio las podemos crear heredando de la clase ServiceExcepcion. NORMA SNCustomException Cuando se desee implementar una excepción propia del negocio, esto es a medida, se deberá extender de la clase “ServiceException”. El nombre de la excepción será <nombre>ServiceException y se ubicará en el paquete exceptions del bloque funcional correspondiente. Ejemplo de excepción propia del negocio package ejpl.gestion.exceptions; 84 de 198 Framework Atlas Normativa public class InvalidAccountServiceException extends ServiceException { private static final long serialVersionUID = -3193946292701856020L; public InvalidAccountServiceException() { super(); } public InvalidAccountServiceException(String message) { super(message); } } PRACTICA BUENA SNExcComunes Las excepciones que puedan ser comunes a varios bloques funcionales se pueden ubicar en el paquete exceptions de un bloque funcional común. NORMA Estas excepciones podrán ser utilizadas desde los otros bloques funcionales. SNNegocioException Cuando se lance una excepción propia del negocio, se deberá atrapar en el momento de producirse para encapsularla en otra de tipo “ServiceException”. Ejemplo de relanzado de excepciones de negocio Public void reserveRoom(Integer customerId, String account, Date expDate) throws InvalidAccountServiceException, RoomAvailabilityServiceException if (customerManager.setReserve(customerId, account, expDate) .booleanValue()) { Room room = hotelManager.getFirstAvailableRoom(); if (room != null) { LOG.debug("getFirstAvailableRoom(): " + room.getRoomNumber()); Customer customer = customerManager.getCustomer(customerId); room.setReserveStatus(Room.OCUPPIED); room.setCustomer(customer); ..... } else { throw new RoomAvailabilityServiceException(); } } else { throw new InvalidAccountServiceException(); } } 85 de 198 { Framework Atlas NORMA Normativa SNSystemException Cuando se lance una excepción que no sea del negocio, se deberá atrapar en el momento de producirse para encapsularla en otra de tipo “ServiceException”. Ejemplo de relanzado de excepciones de Sistema Public Boolean setReserve(Integer customerId, String sAccount, Date dExpiredDate) throws ServiceException { Boolean reserve = false; try { reserve = webService.checkAccount(customerId, sAccount, dExpiredDate); } catch (AxisFault axisex) { throw new ServiceException(axisex); } catch (JmsException jmsex) { throw new ServiceException(jmsex); } return reserve; SNDAOException Los servicios que invoquen de forma directa a los componentes de la capa de acceso a datos NORMA (formada por Spring-DAOs), deberán atrapar y gestionar las excepciones del tipo “DataAccessException” que se lancen, con objeto de encapsularlas y relanzarlas como excepciones de tipo “ServiceException”, ya sea a la fachada u otros servicios de más alto nivel. La capa de acceso a datos no hará ningún de tratamiento de las excepciones producidas, simplemente se limitará a lanzarlas a la capa de negocio para que sea esta la encargada de manejarlas. Ejemplo de captura de excepciones de la capa de acceso a datos public void deleteCliente(Cliente cliente) throws ServiceException { try { this.clienteDAO.deleteCliente(cliente); } catch (DataAccessException dae) { throw new ServiceException(dae); } } 86 de 198 Framework Atlas Normativa 6.3.5 TRANSACCIONALIDAD Una de funcionalidades más importantes aportadas por el framework Spring es la gestión de la transaccionalidad proporcionando una capa de abstracción hacia el gestor transaccional utilizado, aportando los siguientes beneficios: · Proporciona un modelo de programación consistente entre diferentes APIs transaccionales tales como JTA, JDBC, Hibernate, JPA y JDO. · Soporte a gestión declarativa de transacción. · Totalmente integrado con la abstracción de acceso a datos de Spring. · Proporciona un API para la gestión programática de transacciones más sencilla que las habituales. · Permite gestión de transacciones mediante anotaciones aplicadas a cualquier clase, y no a clases especiales como EJBs. · Ofrece reglas de rollback mediante anotaciones, de forma que se puede configurar el rollback automático de una transacción en caso de producirse cierto tipo de excepción. Esta característica no existe en el modelo de EJB. Spring permite adaptar el comportamiento de las transacciones, mediante AOP, por ejemplo para insertar un comportamiento personalizado en rollback de transacciones. · A diferencia del modelo de EJB CMT, el cual esta ligado a JTA, la transacción anotacional de Spring trabaja en cualquier entorno. El modelo declarativo de Spring se basa en el soporte de proxies AOP y metadatos (XML o anotaciones solo soportadas por entornos J2SE 5 o superiores). Esta combinación de proxies y metadatos permite tener proxies AOP que usan un TransactionInterceptor en conjunción con el PlatformTransactionManager apropiado y gestionar las transacciones en la ejecución de métodos. El modelo transaccional de Spring se puede resumir en la siguiente figura: 87 de 198 Framework Atlas Normativa El modelo que se deberá seguir es el basado en anotaciones. En los servicios de Spring, se usará @Transaction la cual posee un conjunto de atributos que permitirán definir las reglas y políticas para aplicar sobre métodos. En concreto, podremos tener uno o más parámetros como los siguientes: 6.3.5.1 Propagation: Es utilizado para especificar los límites de una transacción. Gracias a esta característica tendremos bastantes opciones para especificar comportamiento si un método transaccional es ejecutado cuando un contexto transaccional ya existe: Por ejemplo, podríamos ejecutar algo en la transacción en ejecución; suspender la transacción ejecución y crear una nueva transacción, etc. El catálogo de atributos transaccionales disponibles para Spring es: Propagation PROPAGATION_REQUIRED Descripción Se ejecuta en la actual transacción. Si no existe, se crea una nueva. PROPAGATION_REQUIRES_NEW Siempre se crear una transacción nueva. Si existe una transacción previa se suspende. PROPAGATION_SUPPORTS Si existe una transacción se ejecuta en la misma transacción. Si no existe una transacción se ejecutará sin contexto transaccional. PROPAGATION_NOT_SUPPORTED Se ejecuta sin contexto transaccional. Si existe una transacción se detiene. PROPAGATION_MANDATORY Se ejecuta en la actual transacción. Si no existe una transacción previa, se produce una excepción. PROPAGATION_NEVER Se ejecuta sin contexto transaccional. Si existe una transacción previa se produce una excepción. PROPAGATION_NESTED Se ejecuta en una transacción anidada si existe una transacción previa. En caso contrario se comporta exactamente igual que REQUIRED. Se debe tener cuidado al utilizar este atributo transaccional, debido a q solo es soportado por algunos gestores de transacciones. 6.3.5.2 Isolation Level: Con este atributo podremos indicar el control de concurrencia. Cuando múltiples transacciones se están ejecutando en paralelo se pueden dar “dirty reads”, “non repeateable reads” y “phantom reads”. 88 de 198 Framework Atlas Normativa El estándar ANSI/ISO SQL define cuatro niveles de aislamiento transaccional en función de tres hechos que deben ser tenidos en cuenta entre transacciones concurrentes. Estos hechos no deseados son: · Dirty read (lecturas sucias): Una transacción lee datos escritos por una transacción no esperada y no cursada (no ha hecho todavía el commit). · Non-repeateable read (lecturas no repetibles): Una transacción vuelve a leer datos que previamente había leído y encuentra que han sido modificados por una transacción cursada. · Phantom read (lectura fantasma): Una transacción vuelve a ejecutar una consulta, devolviendo un conjuto de filas que satisfacen una condición de búsqueda y encuentra que otras filas que satisfacen la condición han sido insertadas por otra transacción cursada. Así, el framework Spring nos proporciona un conjunto de niveles de aislamiento que podremos usar en base a la tolerancia del sistema: Isolation level Descripción Usa la política de aislamiento por defecto del ISOLATION_DEFAULT sistema persistente. ISOLATION_READ_UNCOMMITTED Permite leer datos incluso cuando existan filas sin commit, esto podría causar dirty read, non repeteable read o phantom reads. Previenen lecturas dirty pero todavía se pueden dar ISOLATION_READ_COMMITTED lecturas non-repeateable o lecturas phantom. ISOLATION_REPEATABLE_READ Previene lecturas dirty y non-repeateable pero se pueden dar lecturas phantom. Este nivel consigue ACID (Atomicity, concurrancy, ISOLATION_SERIALIZABLE isolation and durability). Pero al ser tan estricto puede causar problemas de rendimiento. 6.3.5.3 Read Only: En algunas ocasiones hay un requerimiento que es solo leer datos de la base de datos, en dichos casos utilizar este atributo puede proporcionar un buen rendimiento ya que la base de datos aplicará algunas optimizaciones. Esto solo puede ser hecho cuando una nueva transacción es arrancada en operaciones de tipo “select”, así este atributo solo tomará sentido si la propiedad de propagación PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW, o PROPAGATION_NESTED. 89 de 198 es Framework Atlas Normativa 6.3.5.4 TimeOut: Se utiliza para prevenir deadlocks o recursos bloqueados en el sistema. Permite especificar un timeout que “matará” la transacción después del periodo especificado. Al igual que en el caso anterior este atributo solo tomará sentido si la propiedad de propagación es PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW, o PROPAGATION_NESTED. A continuación se muestra un ejemplo que muestra como se deben implementar las transacciones mediante anotaciones. El servicio que se desea hacer transaccional: Ejemplo de servicio transaccional // La implementación del servicio transaccional package ejpl.gestion.services; @Transactional(readOnly = true, propagation = Propagation.SUPPORTS) public class RoomServiceImpl implements RoomService { public Room getRoom(String roomName) { throw new ServiceException(); } public Room getRoom(String roomName, Integer idRoom) { throw new ServiceException(); } @Transactional(readOnly = false, propagation = Propagation.REQUIRED) public void insertRoom(Room room) { throw new ServiceException(); } @Transactional(readOnly = false) public void updateRoom(Room room) { throw new ServiceException(); } } Según el ejemplo anterior se puede definir atributos transaccionales a nivel de clase, de esta manera modelamos el comportamiento transaccional que por defecto tendrá cada uno de los métodos de la misma. A partir de ahí, se podrá sobrescribir dicho comportamiento transaccional por defecto, utilizando la anotación @Transaction sobre el método que se desee modificar. Los métodos getRoom se ejecutarán en un contexto de solo lectura con soporte a transacción, el método insertRoom en un contexto de lecturaescritura con transacción requerida y el método updateRoom en un contexto de lectura-escritura con soporte a transacción. 90 de 198 Framework Atlas Normativa PRACTICA BUENA SNGenericTransaction Si bien es cierto que el manejo de transacciones dependerá del negocio, en la mayoría de los casos las transacciones se podrán configurar tal y como se han expuesto en el ejemplo anterior por lo que se recomienda utilizar esta configuración por defecto a la hora de gestionar transacciones en los servicios de negocio. La gestión de las transacciones siempre deberá realizarse a nivel de la capa de servicios, nunca a nivel de la capa DAO. Se recomienda gestionar transacciones en la fachada por ser el punto de control de la capa de servicios. Desde un punto vista de la configuración, lo primero que se debe hacer es indicar el gestor transaccional que se quiere utilizar, en el caso del framework Atlas lo configuramos para utilizar Hibernate como gestor transaccional. Esta configuración ya viene preconfigurada en los arquetipos en el fichero applicationContext-database.xml y no se debe modificar. A continuación se muestra como se ha configurado el gestor de transacciones en los arquetipos: Configuración del gestor de transacciones en applicationContext-database.xml <!-- ========= CONFIGURACION DEL TRANSACTION MANAGER ===================== --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory" p:entityInterceptor-ref="atlasInterceptor"/> NORMA NORMA <!-- ==== GESTION DE TRANSACCIONES MEDIANTE ANOTACIONES ============== --> <tx:annotation-driven transaction-manager="transactionManager"/> SNTransactionAnnotated Para el manejo de transacciones se empleará el modelo de anotaciones propuesto por Spring. SNTransactionDefault No esta permitido modificar los atributos “Isolation Level” y “TimeOut” respecto a sus valores por defecto. En caso de tener que alterarlo solo se podrá hacer previa autorización por parte de ICM. 91 de 198 Framework Atlas Normativa La manera más sencilla de indicar a Spring que una transacción necesita hacer rollback será lanzar una excepción desde el código que se está ejecutando dentro del contexto transaccional. Spring atrapará cualquier excepción no manejada y marcará la transacción para rollback. SNTransactionRollback NORMA Se utilizará el mecanismo de rollback de transacción basado en anotaciones. Esto se conseguirá mediante la anotación @Transaction y los atributos “rollbackFor”, “rollbackForClassName”, “noRollbackFor”, “noRollbackForClassName”. Esto solo tendrá sentido para las excepciones de negocio gestionadas en la capa de servicios ya que las excepciones de tipo “DataAccessException” a nivel de DAO o “RuntimeException” se traducirán en un rollback automático. Por ejemplo, el código necesario para realizar un rollback de una transacción cuando se lance una excepción de negocio de tipo “NotRoomFoundServiceException” podría ser algo como: Ejemplo de definición de rollback @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackForClassName = {"NotRoomFoundServiceException"}) Atención Si desde un método de un Servicio se invoca a otro método del mismo Servicio el contexto transaccional será el de la anotación transaccional del primero, y la anotación transaccional del segundo método será ignorada. Por lo tanto la invocación del segundo método siempre participará en la transacción del primero, y en ningún caso se creará una nueva transacción aunque se le indique mediante una anotación. 6.3.6 . FICHEROS TEMPORALES En algunas aplicaciones es necesario generar ficheros temporales en un directorio del entorno. Actualmente todos los entornos ya tienen preparados estos directorios y están compartidos por NFS entre las distintas máquinas del cluster. Las aplicaciones podrán acceder a estos directorios para dejar y eliminar ficheros pero no podrán crear carpetas dentro de estos directorios. Existen jobs periódicos que se encargan de limpiar estos directorios, para eliminar los ficheros temporales obsoletos. La ruta de los directorios temporales en los entornos de ICM está configurada utilizando la propiedad del sistema java.io.tmpdir. El framework Atlas ya establece el valor para esta propiedad dependiendo del 92 de 198 Framework Atlas Normativa entorno en el que nos encontremos (no es responsabilidad de la aplicación). En entornos locales (la máquina local del desarrollador) la ruta será la que esté establecida por defecto en el sistema operativo. A continuación se muestran dos ejemplos de creación de ficheros temporales: Creación de un fichero temporal a partir de un byte[] public File guardarFicheroTemporal(byte[] b) throws ServiceException { File temp = null; try { temp = File.createTempFile("EJPL_", ".txt"); temp.deleteOnExit(); //Eliminar fichero al finalizar la ejecución de la JVM. if (b != null) { FileOutputStream fout = new FileOutputStream(temp); fout.write(b); fout.flush(); fout.close(); } logger.info("--- Nombre fichero: " + temp.getName()); } catch (IOException e) { logger.error("Error al crear el fichero"); throw new ServiceException(e); } return temp; } Creación de un fichero temporal rellenando su contenido //crear fichero en el directorio temporal try { //Creacion de fichero temporal // mas info: http://download.oracle.com/javase/1,5.0/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String) File temp = File.createTempFile("EJPL_", ".txt"); temp.deleteOnExit(); //Eliminar fichero al finalizar la ejecución de la JVM. FileOutputStream fout = new FileOutputStream(temp); PrintStream out = new PrintStream(fout); out.println("Ejemplo fichero en el directorio temporal."); //Escribimos dentro del fichero logger.info("--- Nombre fichero: " + temp.getName()); } catch (IOException e) { logger.error("Error al crear el fichero"); throw new ServiceException(e); } 93 de 198 Framework Atlas Normativa SNFicherosTemporales Si se necesita crear un fichero temporal, se utilizarán los métodos que proporciona la clase NORMA java.io.File para ello (File.createTempFile). Al utilizar estos métodos, los ficheros temporales se crearán en el directorio definido por la propiedad del sistema java.io.tmpdir. El valor de esta propiedad ya está preestablecido en el framework Atlas dependiendo del entorno en el que se encuentre desplegada la aplicación, por lo que no se debe modificar su valor desde el código fuente de ninguna aplicación. PRACTICA BUENA SNNomFicheroTemporal En aquellos casos en los que los ficheros se generan en cada petición es necesario crear un nombre aleatorio para el nombre del fichero para evitar que una petición sobreescriba el fichero generado por otra. Dado que el directorio temporal es compartido por todas las aplicaciones se recomienda que el nombre del fichero comience por el nombre del proyecto. Ejemplo; EJPL_<nombrealeatorio>. 6.4 ACCESO A DATOS El acceso a datos es una de las partes con mayor índice de criticidad que pueda existir en cualquier aplicación web. Para el acceso a los distintos sistemas relacionales la tecnología seleccionada es Hibernate. A continuación se muestra un diagrama general de la capa de acceso a datos desde el punto de vista de arquitectura del sistema. Fachada POJO Services POJOs Capa de Acceso a Datos POJO Services POJOs Capa de Acceso a Datos SPRING HibernateDaoSupport SPRING SPRING Hibernate SPRING HibernateDaoSupport DAO Hibernate BD Template SPRING Hibernate Template Arquitectura de la capa de Acceso a Datos 94 de 198 HIBERNATE HIBERNATE (Oracle, etc) Framework Atlas Normativa Para el acceso a la información se utilizará la solución ORM (Object-Relational Mapping) de Hibernate, la cual se erige como un potente mapeador objeto/relacional y servicio de consultas para Java. Hibernate permite desarrollar clases persistentes a partir de clases comunes, incluyendo asociación, herencia, polimorfismo, composición y colecciones de objetos. El lenguaje de consultas de Hibernate HQL (Hibernate Query Language), diseñado como una mínima extensión orientada a objetos de SQL, proporciona un puente elegante entre los mundos de objetos y relacional. Hibernate también permite expresar consultas utilizando SQL nativo o consultas basadas en criterios. Soporta todos los sistemas gestores de bases de datos SQL y se integra de manera sencilla y sin restricciones con prácticamente la totalidad de servidores de aplicaciones JEE y contenedores web, además de poder utilizarse en aplicaciones standalone. Se pueden enumerar las siguientes características clave: o Persistencia transparente: Hibernate puede operar proporcionando persistencia de una manera transparente para el desarrollador. o Modelo de programación natural: Hibernate soporta el paradigma de orientación a objetos de una manera natural: herencia, polimorfismo, composición y el framework de colecciones de Java. o Soporte para modelos de objetos con una granularidad muy fina: Permite una gran variedad de mapeos para colecciones y objetos dependientes. o Sin necesidad de mejorar el código compilado (bytecode): No es necesaria la generación de código ni el procesamiento del bytecode en el proceso de compilación. o Escalabilidad extrema: Hibernate posee un alto rendimiento, tiene una caché de dos niveles y puede ser usado en un cluster. Permite inicialización perezosa (lazy) de objetos y colecciones. o Lenguaje de consultas HQL: Este lenguaje proporciona una independencia del SQL de cada base de datos, tanto para el almacenamiento de objetos como para su recuperación. o Soporte para transacciones de aplicación: Hibernate soporta transacciones largas (aquellas que requieren la interacción con el usuario durante su ejecución) y gestiona la política optimistic locking automáticamente. o Generación automática de claves primarias: Soporta los diversos tipos de generación de identificadores que proporcionan los sistemas gestores de bases de datos (secuencias, columnas autoincrementales,...) así como generación independiente de la base de datos, incluyendo identificadores asignados por la aplicación o claves compuestas. 95 de 198 Framework Atlas Normativa ADHibernate La gestión de persistencia sobre los datos almacenados en bases de datos relacionales se realizará utilizando el motor de persistencia Hibernate. NORMA El mecanismo elegido para realizar el mapeo de clases java a tablas de la base de datos será el basado en anotaciones, dichas anotaciones proporcionarán a Hibernate la información suficiente para saber cómo cargar y almacenar clases persistentes y se marcarán a nivel de atributo. Se deberán utilizar aquellas anotaciones proporcionadas por Hibernate y que formen parte del estándar JPA. En ocasiones es posible que sea necesario utilizar anotaciones propias de Hibernate no correspondientes al estándar JPA. Sólo se podrán utilizar si se ha consensuado previamente con ICM y se ha otorgado una autorización excepcional para ello. 96 de 198 Framework Atlas Normativa 6.4.1 Datasource y Sesiones de Hibernate Todas las aplicaciones definirán un datasource para conectarse con la base de datos. NORMA DAODatasource En los arquetipos ya viene configurado el datasource de acceso a base de datos. Deberá utilizarse dicho datasource y nunca obtener directamente las conexiones jdbc. El acceso al datasource siempre se realizará a través de la sesión de Hibernate. La sesión en Hibernate representa la interfaz entre la aplicación Java e Hibernate. Dicha sesión permitirá realizar operaciones de creación, modificación, lectura y eliminación de instaciones mapeadas con la base de datos. Históricamente, la gestión de sesiones en Hibernate se ha considerado uno de los problemas más comunes que se encuentran en aplicaciones Web, para evitar esto han surgido un conjunto de buenas prácticas y/o patrones que nos indican como trabajar de forma optima, en base al entorno de trabajo establecido. De tal forma para entornos Web el modelo recomendado siempre será el patrón session-perview (Sesión por vista). En una sesión por vista, la sesión de Hibernate se mantiene abierta mientras dura el ciclo de vida de una petición Http. NORMA DAOSession En las aplicaciones Web se deberá utilizar el patrón session-per-view, para ello Spring proporciona un filtro que se encargará de tratar toda la problemática asociada a la gestión de sesiones Hibernate en cada petición. Este filtro ya se encuentra definido en el fichero web.xml y no se puede modificar. DAOFlushing Se deberá usar el mecanismo de flushing por defecto en Hibernate sobre las sesiones, esto es NORMA el denominado FlushMode.AUTO. Este valor por defecto deberán ser válidos para cualquier entorno. Solo se podrá optar por otra estrategia, previo consenso con ICM. Se deberá usar el mecanismo de fetching por defecto en Hibernate, este es lazy select fetching para colecciones y lazy proxy fetching para asociaciones single-valued. Estos valores por defecto deberán ser válidos para cualquier entorno. Solo se podrá optar por otra estrategia, previo consenso con ICM. 97 de 198 Framework Atlas Normativa 6.4.2 Configuración A continuación se muestran los distintos ficheros donde se encuentra la configuración de la capa de acceso a datos. 6.4.2.1 enviroment.properties El fichero enviroment.properties contiene las variables que dependen del entorno por lo tanto aquí es donde se tiene que configurar el datasource. A continuación se muestra la configuración del datasource que viene configurada en los arquetipos. environment.properties ###################################################### # Fichero de variables de configuración específicas # # para el entorno LOCAL # ###################################################### # Configuracion para acceso a base de datos dataSourceName=${artifactId}-webDS jdbc.driverClassName=oracle.jdbc.OracleDriver jdbc.url=jdbc:oracle:thin:@icm21.icm.es:1521:denivel2 jdbc.username=dba_ejpl jdbc.password=sis hibernate.dialect=org.hibernate.dialect.Oracle9iDialect Nota Para más información sobre el fichero de configuración environment.properties consultar el manual de arquetipos. 6.4.2.2 applicationContext-database.xml El fichero applicationContext-database.xml que incorpora el arquetipo contiene la configuración de todos los parámetros de conexión a base de datos, incluyendo el sessionFactory y el transactionManager. En este fichero solamente se puede modificar la propiedad packagesToScan para incorporar los paquetes donde residen las distintas clases de dominio que sea necesario crear (solo es necesario incluir los paquetes raíz, los subpaquetes serán escaneados automáticamente). applicationContext-database.xml <?xml version="1.0" encoding="UTF-8"?> <!-- ============================================================== --> <!-En este fichero se configuran todos los --> <!-parametros de conexion a la base de datos --> <!-incluyendo el sessionFactory y el transactionManager --> <!-- ============================================================== --> <beans xmlns="http://www.springframework.org/schema/beans" 98 de 198 Framework Atlas Normativa xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- =========== CONFIGURACION DE CONEXIONES PARA ACCESO A DATOS =========== --> <!-- DataSource Definition --> <!-- via JNDI definido en el contenedor de aplicaciones --> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="jdbc/${dataSourceName}" /> </bean> <!-- ============ CONFIGURACION DEL SESSIONFACTORY DE HIBERNATE ======== --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <description> Bean que representa a la factoria de hibernate para crear sesiones con base de datos </description> <!-- Descomentar para auditoria <property name="configurationClass" value="atlas.audit.hibernate.cfg.AnnotationConfiguration" /> --> <property name="schemaUpdate" value="false"/> <property name="packagesToScan"> <list> <!-- ======== INCLUIR AQUI TODOS LOS PAQUETES DE CLASES ANOTADAS ===== --> <value>ejpl.bloquefuncionaln.domain</value> <!-- Necesario si se quiere utilizar el componente de calendario --> <value>atlas.componentes.domain</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">false</prop> <prop key="hibernate.use_sql_comments">false</prop> <!-- La No se permite el uso de cachés de segundo nivel en Hibernate. En el caso de que se justifique su uso se solicitará una autorización excepcional a ICM. --> <prop key="hibernate.cache.use_second_level_cache">false</prop> <!-- Descomentar para auditoria <prop key="atlas.audit.triggers">false</prop> <prop key="atlas.audit.console_output">false</prop> --> 99 de 198 Framework Atlas Normativa </props> </property> <property name="dataSource" ref="dataSource" /> </bean> <!-- ============ CONFIGURACION DEL TRANSACTION MANAGER =========== --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory" p:entityInterceptorref="atlasInterceptor"/> <!-- ========== GESTION DE TRANSACCIONES MEDIANTE ANOTACIONES ============ --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- ========== TRADUCTOR DE EXCEPCIONES DE SPRING ============ --> <bean id="jdbcExceptionTranslator" class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator"> <description> Bean que representa al traductor de codigos de error SQL a excepciones JAVA </description> <property name="dataSource" ref="dataSource" /> </bean> <!-- ======== DEFINICION DE HIBERNATETEMPLATE CON PROPIEDADES ========= --> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <description> Bean que representa la plantilla de hibernate. A este bean se le inyectan la factoria de sesiones y el traductor de sesiones JDBC </description> <property name="sessionFactory" ref="sessionFactory" /> <property name="jdbcExceptionTranslator" ref="jdbcExceptionTranslator" /> </bean> <!-- ===== DEFINICION DE BEAN auditConstants NECESARIO PARA AUDITORIA ===== --> <!-- Descomentar para auditoria <bean id="auditConstants" class="atlas.audit.properties.AuditConstants"> <property name="codAplicacion" value="ejpl"/> <property name="cdtpaccesoLogico" value="I"/> </bean> --> </beans> 6.4.2.3 applicationContext-dao.xml El fichero applicationContext-dao.xml contiene la definición de los bean de los distintos DAOs en el contexto de Spring. applicationContext-dao.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 100 de 198 Framework Atlas Normativa xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- ============================================================ --> <!-Definicion de todos los DAO`s de la aplicacion --> <!-- ============================================================ --> <bean id="clienteDAO" class="ejpl.gestion.dao.ClienteDAOImpl" p:sessionFactory-ref="sessionFactory"/> </beans> El ámbito de creación de los DAOs será siempre el que adopta Spring por defecto, es decir Singleton. (por defecto si no se indica en el fichero de configuración) DAODependencias El fichero de configuración de Spring donde se definen los daos se debe llamar NORMA applicationContext-dao.xml. En el caso de que este fichero se haga muy grande se podría dividir en varios ficheros con la nomenclatura applicationContext-dao-yyyy.xml donde yyyy es un nombre que identifica a este fichero. No se permite instanciar objetos de daos directamente. Los módulos de tipo librería en lugar de esta norma les aplica la norma SNSpringLIB. 101 de 198 Framework Atlas Normativa 6.4.3 Entidades de dominio Las entidades de dominio son las clases Java que tienen una correspondencia con tablas del modelo de datos relacional. ADEntityImpl Las clases de dominio se incluirán en el paquete domain del bloque funcional correspondiente. No tendrán una nomenclatura específica ya que su nombre debe representar al objeto de dominio que implemente. NORMA Las clases de dominio deben: o Incluir la anotación @Entity o Implementar la interface Serializable. o Incluir atributos privados y sus correspondientes setter y getter o Incluir un constructor sin argumentos o Implementar los métodos equals y hashcode para las entidades persistentes, ya que dichos métodos se harán indispensables en casos como: o Se necesitan almacenar instancias en un conjunto (Asociaciones 1-n). o Se quieren utilizar las instancias como keys para un map. o Se quieren usar métodos de colecciones como contains(), remove(), etc… PRACTICA . BUENA ADRendimiento Hibernate puede ser una herramienta muy potente pero a su vez su utilización sin tener en cuenta la forma en la que trabaja Hibernate puede provocar problemas de rendimiento. Se debe evitar que el acceso a determinados datos suponga la carga en memoria de estructuras complejas o de demasiada información que en la mayoría de los casos no se va a necesitar. A continuación se muestra un fragmento de la clase denominada “Cliente”, la cual representa una entidad persistente gestionada por el motor de Hibernate: Cliente.java package ejpl.gestion.domain; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; 102 de 198 Framework Atlas Normativa import import import import import import import import import javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.JoinColumn; javax.persistence.ManyToOne; javax.persistence.SequenceGenerator; javax.persistence.Table; javax.persistence.Temporal; javax.persistence.TemporalType; javax.persistence.GeneratedValue; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; /** * Cliente * @author ICM * @version 1.0. */ @Entity @Table(name = "EJPL_CLIENTES") public class Cliente implements java.io.Serializable { /** * Identificador del numero de serie para serializacion */ private static final long serialVersionUID = 1L; /** * Representa el identificador/PK del cliente. */ private Integer idCliente; /** * Representa el nombre del cliente. */ private String nombre; /** * Representa el primer apellido del cliente. */ private String apellido1; /** * Representa el segundo apellido del cliente. */ private String apellido2; /** * Representa la direccion del cliente. */ private String direccion; /** * Representa el telefono del cliente. */ private String telefono; /** * Representa la fecha de nacimiento del cliente. 103 de 198 Framework Atlas Normativa */ private Date fechaNacimiento; /** * Representa el estado civil del cliente. */ private EstadoCivil estadoCivil; /** * Constructor sin argumentos. */ public Cliente() { } /** * Constructor para la entidad Cliente con los parametros minimos. * @param idCliente Identificador * @param nombre Nombre * @param apellido1 Primer Apellido * @param apellido2 Segundo Apelillido */ public Cliente(Integer idCliente, String nombre, String apellido1, String apellido2) { this.idCliente = idCliente; this.nombre = nombre; this.apellido1 = apellido1; this.apellido2 = apellido2; } /** * Constructor para la entidad Cliente con los todos parametros posibles. * @param idCliente Identificador * @param nombre Nombre * @param apellido1 Primer Apellido * @param apellido2 Segundo Apelillido * @param direccion Direccion * @param telefono Telefono * @param fechaNacimiento Fecha de Nacimiento * @param estadoCivil Estado Civil */ public Cliente(Integer idCliente, String nombre, String apellido1, String apellido2, String direccion, String telefono, Date fechaNacimiento, EstadoCivil estadoCivil) { this.idCliente = idCliente; this.nombre = nombre; this.apellido1 = apellido1; this.apellido2 = apellido2; this.direccion = direccion; this.telefono = telefono; this.fechaNacimiento = fechaNacimiento; this.estadoCivil = estadoCivil; } /** * @return <code>java.lang.Integer</code> Devuelve el identificador/PK de la entidad Cliente. */ @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "EJPL_SECUENCIA_ID_CLIENTE") @SequenceGenerator(name = "EJPL_SECUENCIA_ID_CLIENTE", sequenceName = "EJPL_SECUENCIA_ID_CLIENTE") 104 de 198 Framework Atlas Normativa @Column(name = "ID_CLIENTE", unique = true, nullable = false, precision = 9, scale = 0) public Integer getIdCliente() { return this.idCliente; } /** * @param idCliente Modifica el identificador/PK del cliente. */ public void setIdCliente(Integer idCliente) { this.idCliente = idCliente; } /** * @return <code>java.lang.String</code> Devuelve el nombre del cliente. */ @Column(name = "NOMBRE", nullable = false, length = 50) public String getNombre() { return this.nombre; } /** * @param nombre Modifica el nombre del cliente. */ public void setNombre(String nombre) { this.nombre = nombre; } /** * @return <code>java.lang.String</code> Devuelve el primer apellido del cliente. */ @Column(name = "APELLIDO1", nullable = false, length = 50) public String getApellido1() { return this.apellido1; } /** * @param apellido1 Modifica el primer apellido del cliente. */ public void setApellido1(String apellido1) { this.apellido1 = apellido1; } /** * @return <code>java.lang.String</code> Devuelve el segundo apellido del cliente. */ @Column(name = "APELLIDO2", nullable = false, length = 50) public String getApellido2() { return this.apellido2; } /** * @param apellido2 Modifica el segundo apellido del cliente. */ public void setApellido2(String apellido2) { this.apellido2 = apellido2; } /** 105 de 198 Framework Atlas Normativa * @return <code>java.lang.String</code> Devuelve la direccion del cliente. */ @Column(name = "DIRECCION", length = 100) public String getDireccion() { return this.direccion; } /** * @param direccion Modifica la direccion del cliente. */ public void setDireccion(String direccion) { this.direccion = direccion; } /** * @return <code>java.lang.String</code> Devuelve el telefono del cliente. */ @Column(name = "TELEFONO", length = 15) public String getTelefono() { return this.telefono; } /** * @param telefono Modifica el telefono del cliente. */ public void setTelefono(String telefono) { this.telefono = telefono; } /** * @return <code>java.lang.String</code> Devuelve el estado civil del cliente. */ @ManyToOne @JoinColumn(name = "FK_ESTADO_CIVIL") public EstadoCivil getEstadoCivil() { return this.estadoCivil; } /** * @param estadoCivil Modifica el estado civil del cliente. */ public void setEstadoCivil(EstadoCivil estadoCivil) { this.estadoCivil = estadoCivil; } /** * @return <code>java.util.Date</code> Devuelve la fecha de nacimiento del cliente. */ @Temporal(TemporalType.DATE) @Column(name = "FC_NACIMIENTO", length = 7) public Date getFechaNacimiento() { return this.fechaNacimiento; } /** * @param fechaNacimiento Modifica la fecha de nacimiento del cliente. */ public void setFechaNacimiento(Date fechaNacimiento) { 106 de 198 Framework Atlas Normativa this.fechaNacimiento = fechaNacimiento; } /** * Implementación de hashCode para uso de Hibernate. La 'business key' en * este caso se compondrá por [nombre, apellido1, apellido2 y * fechaNacimiento]. * * <p>Más info en: {@link http://community.jboss.org/docs/DOC-13933} */ @Override public int hashCode() { return new HashCodeBuilder() .append(this.nombre) .append(this.apellido1) .append(this.apellido2) .append(this.fechaNacimiento) .toHashCode(); } /** * Implementación de método equals para uso con Hibernate. Se ha definido * la clave de negocio o 'business key' como * [nombre, apellido1, apellido2, fechaNacimiento] * * <p>Más info en: {@link http://community.jboss.org/docs/DOC-13933} * * @param obj objeto a comparar con esta instancia. * @return true si el objeto pasado es igual a este; * false en caso contrario */ @Override public boolean equals(Object obj) { // Si el objeto a comparar es nulo o no pertenece a la // misma clase, la igualdad no se cumple if (obj == null || obj.getClass() != getClass()) { return false; } // si el objeto pasado es este objeto, la igualdad se cumple if (obj == this) { return true; } // comparación en base a la 'business key' Cliente rhs = (Cliente) obj; return new EqualsBuilder() .append(this.nombre, rhs.nombre) .append(this.apellido1, rhs.apellido1) .append(this.apellido2, rhs.apellido2) .append(this.fechaNacimiento, rhs.fechaNacimiento) .isEquals(); } /** * Implementación de toString() pare este objeto de modelo. * Se ha utilizado la clase StringBuilder como base de implementación. * * NOTA: Hay que tener mucho cuidado con volcar en este método * relaciones con otros objetos (EstadoCivil en este caso) 107 de 198 Framework Atlas Normativa * porque una linea de log puede provocar la carga de muchos * objetos de base de datos, dependiendo del grado de * enlazamiento entre los objetos de dominio. */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Cliente [idCliente=").append(idCliente) .append(", nombre=").append(nombre) .append(", apellido1=").append(apellido1) .append(", apellido2=").append(apellido2) .append(", direccion=").append(direccion) .append(", fechaNacimiento=").append(fechaNacimiento) .append(", telefono=").append(telefono) .append(", estadoCivil=").append(estadoCivil) // relación 1-1 .append("]"); return builder.toString(); } PRACTICA . BUENA } ADEqualsHashcode La implementación de equals y hashcode se debe realizar utilizando EqualsBuilder y HashCodeBuilder tal y como se puede ver en el ejemplo de la clase cliente. Es recomendable que el índice de granularidad de las entidades persistentes sea el adecuado, intentando representar de forma estricta las entidades de negocio. 6.4.3.1 Mapeo relacional Las clases de dominio se mapearán mediante las correspondientes anotaciones de Hibernate. A continuación se muestra una tabla con algunas de las anotaciones de Hibernate más utilizadas. Aunque aquí solamente se muestran las más utilizadas se podrán utilizar todas las anotaciones proporcionadas por Hibernate que cumplen con el estándar JPA. @Table Indica la tabla con la que se va a mapear @Id Indica que este campo es identificador de la tabla @GeneratedValue Indica que este campo va a ser generado automáticamente @SequenceGenerator Indica la secuencia a utilizar para este campo 108 de 198 Framework Atlas Normativa NORMA @Column Indica el campo con el que se va a mapear este atributo ADMapeoTabla Cada clase de dominio será mapeada a una tabla de la base de datos, esto se hará con la anotación @Table. Ejemplo de mapeo a tabla @Entity @Table(name = "EJPL_CLIENTES") public class Cliente implements java.io.Serializable { Nota No hay que olvidarse de que cada clase de domino anotada se debe incluir en el fichero de configuración applicationContext-database.xml. ADIdentificador Todas las entidades persistentes deberán tener un atributo a modo de identificador único que permita distinguir un objeto de otro de forma unívoca. Este atributo será de tipo Integer y estará obligatoriamente generado por una secuencia. NORMA En el caso de que el modelo de datos ya exista en producción y no sea posible cumplir esta norma se utilizará la anotación @AtlasLegacy en la clase de dominio. Este atributo se anotará con la anotación @Id. Al margen de este atributo se podrán crear otros identificadores únicos propios de la gestión funcional de la tabla que no serán anotados con @Id. Sólo existe una excepción en la cuál una primary key deberá estar compuesta por más de un campo, y es en aquellas tablas que sirven para representar relaciones muchos a muchos NORMA entre otras tablas. ADUsoAtlasLegacy Se requiere una autorización excepcional por parte de ICM para el uso de la anotación @AtlasLegacy en las clases de dominio de las entidades de modelos de datos heredados. 109 de 198 Framework Atlas Normativa Ejemplo de campo Id @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "EJPL_SECUENCIA_ID_CLIENTE") @SequenceGenerator(name = "EJPL_SECUENCIA_ID_CLIENTE", sequenceName = "EJPL_SECUENCIA_ID_CLIENTE") @Column(name = "ID_CLIENTE", unique = true, nullable = false, precision = 9, scale = 0) public Integer getIdCliente() { return this.idCliente; } NORMA ADRelaciones No se permite el uso de relaciones muchos-a-muchos. Se deberán sustituir, siempre que sea posible, por relaciones uno-a-muchos y/o muchos-a-uno. En caso de no poder hacer dicha sustitución, se deberá consultar a ICM el uso de la posible NORMA relación muchos-a-muchos. 6.4.3.2 ADDinamicos No se permite el uso de modelos dinámicos de Hibernate como sustitutivo de las entidades POJOs de persistencia. Tipos de datos BLOB y CLOB (LOB) Los tipos de datos BLOB y CLOB hacen referencia a aquellos elementos utilizados en una bases de datos para almacenar entidades de gran tamaño que puedan cambiar de forma dinámica, estando los primeros enfocados a datos binarios (por ejemplo una imagen) y los segundos a datos de tipo carácter (por ejemplo NORMA un párrafo de texto con un tamaño considerable). ADLobAnot Los atributos de tipo Lob se anotarán con la anotación @Lob y se le indicará que se traiga bajo demanda con la anotación @Basic(fetch=FetchType.LAZY) 110 de 198 Framework Atlas Normativa Ejemplo de definición de campo LOB /** * * @return Devuelve el contenido del ficherote un campo LOB */ @Lob @Column(name = "CONTENIDO") @Basic(fetch=FetchType.LAZY) public Blob getContenido() { return contenido; } 111 de 198 Framework Atlas Normativa 6.4.4 Data Access Objects En una arquitectura Java Enterprise Edition (JEE) es fundamental contar con un elemento propio de acceso a datos que permita a las aplicaciones obtener y manipular los datos de la organización de una manera estandarizada y óptima que ofrezca a los desarrolladores una interfaz sencilla y homogénea que facilite los desarrollos aumentando la productividad y mejorando los tiempos de mantenimiento, a la vez que ofrezca unas elevadas prestaciones de rendimiento en tiempo de ejecución. El patrón DAO es uno de los patrones de diseño estándar de JEE. DAO permite encapsular el acceso y manipulación de datos en una capa separada. Esta capa gestiona la conexión con la fuente de datos (bases de datos relacionales, ficheros planos, sistema de ficheros remotos, etc.) para obtener y almacenar dichos datos, ya que implementa el mecanismo de acceso necesario. Independientemente del tipo de fuente de datos empleada, la capa DAO siempre proporciona un API uniforme a sus clientes, ocultando los detalles de implementación. La capa DAO se implementa sin estado. No almacena en caché resultados de ninguna consulta, ni datos que el cliente pueda necesitar posteriormente. Esto provoca que los objetos DAO sean simples y evita problemas potenciales de concurrencia Diagrama de clases (extraído de “Core J2EE Patterns, Best Practices and Design Strategies” por Deepak Alur, John Crupi y Dan Malks): Spring proporciona un mecanismo adicional que permite integrar herramientas ORM en objetos DAO de una forma mucho más sencilla, haciendo uso del componente Spring DAO. Los DAOs pueden ser configurados a través de la inyección de dependencias así como participar de los recursos y la gestión automática de transacciones que aporta Spring. La norma habitual en los desarrollos será hacer uso de Hibernate Spring DAO, proporcionando funcionalidades adicionales que harán más sencillo el uso de Hibernate. Las ventajas obtenidas al hacer uso de Spring DAO con Hibernate: · Fácil de testear: La aproximación de inyección de dependencias aportada por Spring hace sencillo cambiar implementaciones y configurar la localización de instancias del objeto SessionFactory de 112 de 198 Framework Atlas Normativa Hibernate, recursos JDBC, gestores de transacciones, etc. Esto hace sencillo aislar y testear cada pieza relacionada con la persistencia de forma independiente. · Acceso común a excepciones: Spring puede mapear las excepciones producidas por la Hibernate, convirtiéndolas de propietarias a una jerarquía común de manejo de excepciones DataAccessException, permitiendo manejar excepciones no recuperables solo en las capas apropiadas. · Gestión general de recursos: Spring maneja de forma automática la localización y configuración de instancias SessionFactory, Datasources, etc., por lo que Spring ofrece una manera sencilla y segura de poder acceder a los recursos. Por ejemplo, generalmente Hibernate necesita utilizar la misma sesión para hacer un manejo eficiente de las transacciones, Spring de forma transparente crea y enlaza sesiones al actual hilo de ejecución, etc. ADHibernateDAOImpl En cada bloque funcional de una aplicación se han de crear los DAOs que darán cobertura a los accesos a la base de datos. NORMA Para crear un DAO se crearán dos clases, con la siguiente nomenclatura: o <nombre>DAO (Interfaz del DAO) o <nombre>DAOImpl (Implementación del DAO) Donde <nombre> debe ser sustituido por el nombre del DAO. Estas clases se incluirán en el paquete dao del bloque funcional correspondiente. Las clases de implementación deben heredar de la clase HibernateDaoSupport, de esta forma NORMA se utiliza el modelo de DAO’s proporcionado por Spring. ADDAOAnotacion Las clases de implementación de DAO tienen que tener la anotación @Repository. (No incluir la anotación en las interfaces) 113 de 198 Framework Atlas Normativa ADDAONomenclatura Cuando los DAOs tengan operaciones de modificacion o alteración de datos seguirán la siguiente nomenclatura: o Inserción: insertXXX, donde XXX será un nombre autodescriptivo, generalmente el NORMA nombre del objeto de domino. o Actualización: updateXXX, donde XXX será un nombre autodescriptivo, generalmente el nombre del objeto de domino. o Eliminación: deleteXXX, donde XXX será un nombre autodescriptivo, generalmente el nombre del objeto de domino. o Consultas: findXXX, donde XXX será un nombre autodescriptivo sobre la consulta a realizar. El nombre descriptivo XXX siempre será opcional. NORMA ADDAOHibernateTemplate Todas las operaciones sobre la base de datos como insert, delete, select (equivalente a find en Hibernate), etc…se deben realizar a través de la clase HibernateTemplate proporcionada por Spring, evitando el uso directo de la sesión de Hibernate. Ejemplo de uso de HibernateTemplate /** * {@inheritDoc} * * @param cliente El cliente * @see ejpl.gestion.dao.ClienteDAO#insertCliente(ejpl.gestion.domain * .Cliente) */ @Transactional(readOnly = false) public void insertCliente(Cliente cliente) { this.getHibernateTemplate().save(cliente); } Para facilitar la tarea de implementación de las operaciones CRUD en los DAOs, se proporciona dentro del arquetipo una interfaz llamada BaseDAO y su correspondiente implementación, con los métodos básicos ya implementados de tal forma que podemos crear nuestros DAOs heredando de esta clase DAO e implementando solo aquellos métodos que sean específicos de nuestro DAO. A continuación se muestra la interfaz BaseDAO: 114 de 198 Framework Atlas Normativa package ejpl.dao; import java.io.Serializable; import java.util.List; import java.util.Map; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Order; /** * DAO genérico con funcionalidad CRUD * * <p>Extiende esta interfaz si se requiere DAOs para los objetos de modelo sin * necesidad de realizar cast de conversión de datos. * * @param <T> el tipo de objeto que manejará este DAO. * @param <PK> la clave primaria del objeto de dominio. */ public interface BaseDAO <T, PK extends Serializable> { /** * Método genérico usado para obtener todos los objetos de un tipo * particular. Este método es equivalente a obtener todas las filas * de una tabla. * * <p>El número total de elementos que correspondería al método * countAll() se puede obtener a través del método size() del objeto * de lista devuelto.</p> * * @return Lista de los objetos recuperados de BD */ List<T> findAll(); /** * Método genérico usado para obtener el total de objetos de un tipo * particular. * @return número de elementos totales en la tabla. */ Long countAll(); /** * Obtiene todos los registros sin duplicados. * <p>Si se utiliza este método, es imperativo que las clases de * modelo implementen correctamente los métodos hashcode/equals.</p> * * <p>El número total de elementos que correspondería al método * countAllDistinct() se puede obtener a través del método size() del * objeto de lista devuelto.</p> * * @return Lista de los objetos recuperados de BD */ List<T> findAllDistinct(); /** * Obtiene en número total de registros sin duplicados. * @return número de elementos totales sin duplicados. */ Long countAllDistinct(); /** * Método genérico para obtener un objeto basado en el tipo de clase * y su identificador único. Si no se encuentra el objeto, este método * devolverá null. * * @param id el identificador (clave primaria) del registro a obtener * @return el objeto de base de datos recuperado */ T find(PK id); /** * Método para obtener una serie de elementos del sistema dados unos ordenes y filtros * @param index Indice de paginacion actual. 115 de 198 Framework Atlas Normativa * @param pageSize Tamaño de pagina. * @param orders Criterios de ordenacion * @param filters Filtros de busqueda. * @return <code>java.util.List</code> La lista de objetos encontrados */ List<T> find(int index, int pageSize, Order[] orders, Criterion[] filters); /** * Método para obtener el numero de elementos dada una serie de filtros * @param filters Filtro de busqueda. * @return <code>int</code> con el numero total de objetos encontrados. */ int count(Criterion[] filters); /** * Comprueba la existencia de un objeto en base a su clave primaria. * * @param id el identificador de la entidad * @return - true si el objeto existe, false en caso contrario */ boolean exists(PK id); /** * Método genérico para grabar un objeto (maneja objetos nuevos y modificados). * Si el objeto es nuevo, este se devolverá con la clave primaria generada para * su inserción en base de datos. * * @param object el objeto a guardar * @return el objeto persistente */ T insert(T object); /** * Método genérico para grabar un objeto (maneja objetos nuevos y modificados). * Si el objeto es nuevo, este se devolverá con la clave primaria generada para * su inserción en base de datos. * * @param object el objeto a guardar */ void insertOrUpdate(T object); /** * Método genérico para grabar actualizar un objeto * * @param object el objeto a guardar */ void update(T object); /** * Método genérico para eliminar un objeto de la base de datos en base a su * clave primaria. * * @param id el identificador (clave primaria) del registro a obtener */ void delete(PK id); /** * Método genérico para eliminar un objeto de la base de datos * * @param object el objeto a eliminar */ void delete(T object); /** * Encuentra una lista de registos usando una 'named query'. * * @param queryName nombre de la consulta a ejecutar * @param queryParams un objeto Map con los nombres de los parámetos y sus valores * @return una lista con los registros encontrados */ List<T> findByNamedQuery(String queryName, Map<String, Object> queryParams); } La implementación de esta clase se puede ver en el paquete dao en la clase BaseDAOImpl. 116 de 198 Framework Atlas Normativa PRACTICA BUENA ADBaseDAO En el caso de que en el proyecto se identifiquen otros métodos comunes a todos los DAOs estos métodos se incorporaran en la interfaz BaseDAO y en su correspondiente implementación. La creación de nuevos DAOS se realizará utilizando los mecanismos de herencia sobre la clase BaseDAO. Dentro de los arquetipos se ha incluido un ejemplo de nuevo DAO que accede a la tabla de clientes: ClienteDAO. El siguiente diagrama muestra el diagrama de clases con las dependencias de la implementación de este nuevo DAO. class dao «interface» BaseDAO + + + + + + + + + + countAll() : Integer countAllDistinct() : Integer delete(PK) : void exists(PK) : boolean findAll() : List<T> findAllDistinct() : List<T> findByNamedQuery(String, Map<String, Object>) : List<T> get(PK) : T insert(T) : T saveOrUpdate(T) : void T PK:extends Serializable HibernateDaoSupport BaseDAOImpl «interface» ClienteDAO + + findClientes(int, int, Object, Object) : List<Cliente> findClientesTotal(Object) : int - log: Log = LogFactory.getL... {readOnly} persistentClass: Class<T> + + + + + + + + + + # + + BaseDAOImpl(Class<T>) BaseDAOImpl(Class<T>, SessionFactory) countAll() : Integer countAllDistinct() : Integer delete(PK) : void exists(PK) : boolean findAll() : List<T> findAllDistinct() : List<T> findByNamedQuery(String, Map<String, Object>) : List<T> get(PK) : T getLog() : Log insert(T) : T saveOrUpdate(T) : void ClienteDAOImpl + + + ClienteDAOImpl() findClientes(int, int, Object, Object) : List<Cliente> findClientesInternal(int, int, Object, Object, String) : Query findClientesTotal(Object) : int 117 de 198 Framework Atlas Normativa A continuación se muestra un posible código de ejemplo para las clases ClienteDAO y ClienteDAOImpl, que heredan de BaseDAO y añaden dos métodos que no existen en la clase padre. Ejemplo: ClienteDAO package ejpl2.dao; import java.util.List; import ejpl2.domain.Cliente; /** * <p>Clase que extiende el CRUD básico proporcionado por Atlas. Esta clase es * una demostración de como usar BaseDAO y completar con más métodos de * acceso a BBDD.</p> * * <p>Si no hiciesen falta más métodos, no sería necesario crear ninguna clase, * simplemente definir ClienteDAO en el contexto de Spring como sigue: * * <pre> * &lt;bean id="clienteDAO" class="ejpl2.dao.BaseDAOImpl"&gt; * &lt;constructor-arg value="ejpl2.domain.Cliente"/&gt; * &lt;/bean&gt; * </pre> * * </p> * * @author ICM * */ public interface ClienteDAO extends BaseDAO<Cliente, Integer> { /** * Este metodo recupera todos los clientes del sistema. * * @param index Indice de paginacion actual. * @param pageSize Tamaño de pagina. * @param order Criterio de ordenacion. * @param filter Filtro de busqueda. * * @return <code>java.util.List</code> objecto que representa la lista de clientes. */ List<Cliente> findClientes(int index, int pageSize, Object order, Object filter); /** * Este metodo obtiene el numero total de clientes del sistema. * * @param filter Filtro de busqueda. * * @return <code>int</code> con el numero total de cliente encontrados. */ int findClientesTotal(Object filter); } 118 de 198 Framework Atlas Normativa Ejemplo: ClienteDAOImpl package ejpl2.dao; import java.util.HashMap; import java.util.List; import java.util.Map; import import import import org.hibernate.Query; org.springframework.stereotype.Repository; org.springframework.transaction.annotation.Propagation; org.springframework.transaction.annotation.Transactional; import ejpl2.domain.Cliente; /** * Objeto DAO de tratamiento en base de datos de la clase Cliente. * * @author ICM */ @Repository @Transactional(readOnly = true, propagation = Propagation.SUPPORTS) public class ClienteDAOImpl extends BaseDAOImpl<Cliente, Integer> implements ClienteDAO { /** * Constructor por defecto. Pasa a BaseDAO el objeto Class de * parametrización de la clase. */ public ClienteDAOImpl() { super(Cliente.class); } /** * {@inheritDoc} * * @see ejpl2.dao.ClienteDAO#findClientes(int, int, java.lang.Object, * java.lang.Object) */ @SuppressWarnings("unchecked") public List<Cliente> findClientes(int index, int pageSize, Object order, Object filter) { null); Query query = findClientesInternal(index, pageSize, order, filter, // Ejecuta la query return query.setFirstResult(index).setMaxResults(pageSize).list(); } /** * {@inheritDoc} * * @see ejpl2.dao.ClienteDAO#findClientesTotal(java.lang.Object) */ public int findClientesTotal(Object filter) { Query query = findClientesInternal(0, 0, null, filter, "Select count(c)"); 119 de 198 Framework Atlas Normativa // Ejecuta la query return ((Long) query.uniqueResult()).intValue(); } /** * Método interno para buscar clientes * * @param index Indice de paginacion actual. * @param pageSize Tamaño de pagina. * @param order Criterio de ordenacion. * @param filter Filtro de busqueda. * @param select clausula select para retornar distintos valores * @return objeto Query para entregar a Hibernate */ private Query findClientesInternal(int index, int pageSize, Object order, Object filter, String select) { StringBuffer strQuery = new StringBuffer(); Map<String, String> params = new HashMap<String, String>(); if (select != null) { strQuery.append(select); } strQuery.append(" from Cliente c"); // Concatena la clausula where al filtro si es necesario String strFiltro = (filter == null) ? null : filter.toString(); if (strFiltro != null && !strFiltro.equals("")) { strQuery.append(" where c.nombre like :filtro "); params.put("filtro", "%" + strFiltro + "%"); } // Concatena la clausula order al filtro si es necesario String strOrder = (order == null) ? null : order.toString(); if (strOrder != null && !strOrder.equals("")) { strQuery.append(" order by c.").append(strOrder); } // Selecciona el parámetro del filtro si es necesario Query query = getSession().createQuery(strQuery.toString()); // Incluimos los parametros for (String key : params.keySet()) { query.setString(key, params.get(key)); } // Devolver el objeto query return query; } } 120 de 198 Framework Atlas Normativa Atención Puede ocurrir que un DAO no necesite ningún método adicional a los del BaseDAO, en ese caso no es necesario crear ninguna clase, simplemente definir un objeto en el contexto de Spring (applicationContextdao.xml) de la siguiente forma: <bean id="miDAO" class="ejpl.dao.BaseDAOImpl"> <constructor-arg value="ejpl.domain.Cliente"/> <constructor-arg ref=”sessionFactory”/> </bean> Nota NORMA NORMA Los daos se deben inyectar en el contexto de Spring en el fichero applicationContext-dao.xml ADCatalogos No se permiten realizar actualizaciones en tablas de catálogos generales (SUCA, CATA, etc). Tampoco se podrán realizar borrados en cascada sobre tablas de catálogos. ADRemoto El acceso a tablas remotas se debe hacer mediante sinónimos remotos y no por database link. ADHQL PRACTICA BUENA Se deberá utilizar en la medida de lo posible el lenguaje de acceso a datos HQL, por ser un lenguaje más enfocado a objetos que el propio SQL. Aún así se podrá extender este modelo haciendo uso del lenguaje SQL siempre y cuando sea necesario. Esto será necesario en casos de querer usar querys SQL no ANSI-Estándar, querys que por su complejidad sea más adecuado SQL en lugar del mapeo objeto-relacional, operaciones de larga duración del tipo batch, streaming de BLOBs, operaciones de tipo “select” complejas, etc. 121 de 198 Framework Atlas NORMA Normativa ADSQL En el caso de utilizar SQL se implementará mediante los mecanimos que proporciona Hibernate para la ejecución de queries SQL nativas. (createSQLQuery) Ejemplo de uso de SQL public List getQueryData() { SQLQuery query = getHibernateTemplate().getSession().createSQLQuery(sql); query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); return query.list(); } ADSQLUso En el caso de utilizar SQL se deberan tener en cuenta las siguientes restricciones: NORMA · No se podrán utilizar sentencias SQL-DDL desde el código ni utilizar los mecanismos de Hibernate que permitan realizar ese tipo de operaciones desde el código. · No se deben utilizar las sentencias SELECT * en su lugar se incluirán los nombre de los campos que en realidad se van a consultar. · En el caso de utilizar una sentencia SELECT FOR UPDATE se hará con la clausula NO WAIT. 6.4.4.1 Ejecución de consultas Es normal en todos los DAOs la ejecución de consultas en la base de datos. Por motivos de optimización de las consultas es necesario que los parámetros utilizados como criterios no se adjunten en el String de la consulta y sean pasados como ‘named parameters’. A continuación se muestra un ejemplo incorrecto y otro correcto de creación de consultas: Creación INCORRECTA de consultas String strQuery = "from Cliente where nombre = '" + nombre + "'"; // MAL Query query = getSession().createQuery(strQuery); return query.list(); Creación CORRECTA de consultas String strQuery = "from Cliente where nombre = :nombre"; // BIEN Query query = getSession().createQuery(strQuery); query.setString("nombre", nombre); return query.list(); 122 de 198 Framework Atlas NORMA Normativa ADNamedParameter El uso de criterios en las consultas de los DAOs ha de hacerse siempre a través de ‘named parameters’. 123 de 198 Framework Atlas Normativa 6.4.4.2 Manejo de excepciones Un DAO deberá esforzarse en aislar el manejo de excepciones gracias a Spring, por lo que solo podrá lanzar DataAccessException, de manera que el tratamiento de las excepciones que se pudiesen provocar a este nivel seria gestionadas en capas superiores (capa de negocio). Esto se justifica ya que por ejemplo carece de sentido lanzar java.lang.Exception, ya que es demasiado genérica y no transmite ninguna información acerca de la raíz del problema. Tampoco tendrá sentido NORMA lanzar excepciones de tipo java.sql.SQLException, ya que es una excepción JDBC de bajo nivel. 6.4.4.3 DAOExcepciones Todos los métodos de los DAOs sólo podrán lanzar excepciones de tipo DataAccessException. Transaccionalidad El uso del modelo de anotaciones que propone Spring permite gestionar de forma automática y sencilla la semántica transaccional, esto se pronuncia en un código portable con respecto al gestor transaccional utilizado, por ejemplo se podría alterar el uso del gestor transaccional de Hibernate por el de otro sistema de persistencia que soporte el estándar JTA. ADTransaccion La gestión de las transacciones se hará mediante anotaciones. Los DAOs tendrán por defecto todos los métodos como de lectura y propagación supports, esto se definirá con una anotación @Transaction a nivel de clase. (@Transactional(readOnly = NORMA true, propagation = Propagation.SUPPORTS) Los método de los DAOs que alteren datos (insert, update, delete) modificarán el comportamiento por defecto, mediante el atributo “readOnly=false”. (@Transactional(readOnly = false)) De forma excepcional, se permite modificar el comportamiento por defecto de un método con respecto al atributo propagación “Propagation.SUPPORTS” por uno de tipo “Propagation.REQUIRES_NEW”. El uso de cualquier atributo de propagación que no sea “Propagation.SUPPORTS “ o “Propagation.REQUIRES_NEW” deberá de justificarse y consesuarse con ICM. En el ejemplo de implementación de un DAO que podemos ver mas arriba podemos observar el uso de las anotaciones tal y como se indica en la norma. 124 de 198 Framework Atlas Normativa Aunque se comentó en la sección de servicios, recalcar que serán las capas superiores (servicios) la encargadas de gestionar el contexto transaccional y no la capa de acceso a datos, por lo que los DAOs se limitarán a ejecutar un método en un contexto transaccional (si al invocar dicho método el contexto ya está creado), o a ejecutar el método sin transacción (en caso de invocar al DAO sin un contexto transaccional). Esto se cumplirá en la mayoría de los casos, ya que al permitir (eventualmente) Propagation.REQUIRES_NEW, se permite que el propio DAO cree un contexto transaccional solo para la ejecución de un método concreto. ADRollback NORMA Un DAO no puede gestionar rollback de transacción, es decir, se prohíbe el uso de o “rollbackFor = xxxException.class”, o “rollbackForClassName = {"xxxException"}”, o “noRollbackFor = xxxException.class” , o “noRollbackForClassName = {"xxxException"}”. Cuando los DAOs generen un error de tipo “DataAccessException” o “RuntimeException” se traducirá en un rollback automático. Según se comenta en el apartado de servicios de negocio, los atributos “rollbackFor”, “rollbackForClassName”,”noRollbackFor” y “noRollbackForClassName” solo tendrán sentido en la capa de servicios con objeto de poder realizar rollback para las excepciones de negocio. 125 de 198 Framework Atlas Normativa 6.4.5 Llamada a Procedimientos Almacenados La llamada a procedimientos almacenados de Oracle desde Hibernate se puede de dos formas distintas, dependiendo de si el procedimiento devuelve un cursor y si tiene parámetros de salida o no: ADStoredProc NORMA La llamada a procedimientos almacenados de Oracle se realizará de la siguiente forma: 1) Si el procedimiento almacenado devuelve un cursor y no tiene parámetros de salida: Mediante Hibernate utilizando Named Queries 2) Si el procedimiento almacenado no devuelve un cursor o tiene parámetros de salida: Se hará mediante un CallableStatement En los siguientes sub-apartados se muestra la forma de invocarlos en cada uno de estos dos casos. 6.4.5.1 Llamada a procedimientos almacenados mediante Hibernate utilizando Named Queries A continuación se muestra un ejemplo de procedimiento almacenado que devuelve un cliente (el ejemplo puede implementarse en un arquetipo recien creado). 1) Creación de procedimiento almacenado: Ejemplo de procedimiento almacenado create or replace procedure EJPL_PROC_BUSCAR_POR_ID ( z_resultado out SYS_REFCURSOR, w_id IN integer) is begin OPEN z_resultado FOR SELECT ID_CLIENTE,NOMBRE,APELLIDO1,APELLIDO2, DIRECCION,TELEFONO,FC_NACIMIENTO,FK_ESTADO_CIVIL FROM EJPL_CLIENTES WHERE ID_CLIENTE = w_id; end EJPL_PROC_BUSCAR_POR_ID; 2) Modificación de la entidad de dominio para incluir la named query (Cliente.java): Ejemplo de entidad que define la Named Query @Entity @org.hibernate.annotations.NamedNativeQuery(name = "buscarClientePorId", query = "call EJPL_PROC_BUSCAR_POR_ID(?,:w_id)", callable = true, resultClass = Cliente.class) @Table(name = "EJPL_CLIENTES") public class Cliente implements java.io.Serializable { … } 126 de 198 Framework Atlas Normativa 3) Modificación del DAO de Clientes para obtener un cliente por su identificador utilizando el procedimiento almacenado creado (ClienteDAOImpl): Ejemplo de DAO que utiliza la Named Query … public Cliente findById(final Integer idCliente) { // Implementación de ejemplo utilizando procedimiento almacenado List<Cliente> clientes = (List<Cliente>) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(final Session session) throws HibernateException, SQLException { return session.getNamedQuery("buscarClientePorId") // .setParameter("w_id", idCliente) // .list(); } }); if(clientes != null && clientes.size() > 0) { return clientes.get(0); } return null; // Implementación sin utilizar procedimiento almacenado // return (Cliente) getHibernateTemplate().get( // "xxxx.bloquefuncionaln.domain.Cliente", idCliente); } … 6.4.5.2 Llamada a procedimientos almacenados mediante CallableStatement A continuación se muestra un ejemplo de invocación a un procedimiento almacenado que no devuelve un cursor, y/o que tiene parámetros de salida: 1) Creación de procedimiento almacenado: Procedimiento almacenado sis_proc_ident_cod create or replace procedure SIS_PROC_IDENT_COD ( wcodigo in out varchar2, wtexto out varchar2) is begin … end EJPL_PROC_BUSCAR_POR_ID; 2) Modificación del DAO de Clientes para obtener un cliente por su identificador utilizando el procedimiento almacenado creado (ClienteDAOImpl): EjemploDAO.java 127 de 198 Framework Atlas Normativa public String validaDocumento(String documento) throws DataAccessException { Connection con = getSessionFactory().getCurrentSession(). connection(); CallableStatement cst = null; String resultadoCodigo = null; try { cst = con.prepareCall("{call sis_proc_ident_cod(?, ?)}"); cst.setString(1, documento.toUpperCase()); cst.registerOutParameter(1, java.sql.Types.VARCHAR); cst.registerOutParameter(2, java.sql.Types.VARCHAR); // Llamada al procedimiento almacenado cst.execute(); resultadoCodigo = cst.getString(1); } catch (SQLException e) { throw new DataAccessException("Error validando documento", e); } finally { cst.close(); } return resultadoCodigo; } 128 de 198 Framework Atlas Normativa 6.4.6 Cachés en Hibernate El uso adecuado de mecanismos de caché permitirá aumentar el rendimiento de aplicaciones que accedan a entornos persistentes de información al almacenar las estructuras de objetos en memoria, evitando volver a buscar dichos objetos en bases de datos, ahorrando multitud de accesos y por consiguiente grandes cantidades de tiempo. Los pasos comunes que se siguen en el acceso a datos mediante caches podrían resumirse como: · Se realiza una consulta de acceso a datos. · Se comprueba si los objetos requeridos se encuentran en caché. Si los objetos están en caché se devuelven directamente. · Si los objetos no se encuentran en caché, se recuperan desde un almacén de datos persistente y se almacenan en caché para un uso futuro. 6.4.6.1 Las cachés de primer y segundo nivel Hibernate cuenta con dos tipos de cachés, la denominada caché de primer nivel y la de segundo nivel: Figura 1 : Caché de primer y segundo nivel en Hibernate La cache de primer nivel se corresponde al objeto sesión que se obtiene de la factoría de sesiones de Hibernate. Esta caché de primer nivel se encargará de almacenar los objetos que se recuperan de la base de datos. Otra ventaja obtenida en paralelo es que el objeto sesión actúa como fachada y situaciones como accesos, lazos circulares, etc. solo afecta a la propia sesión sin causar efectos colaterales al resto de sesiones abiertas. 129 de 198 Framework Atlas Normativa Una norma fundamental cuando se utilizan cachés, es almacenar sólo lo que estamos seguros que se reutilizará. En otro caso, lo mejor es no utilizar la caché. Cuando se trabaje con una sesión y se mantenga activa en memoria, se debe tener en cuenta que es una caché de primer nivel, y se debe eliminar todo aquello que carezca de sentido su almacenaje en la misma. Se recomienda que cuando se desee eliminar objetos de la caché se invoque al método evict() para que se elimine de caché el objeto pasado como parámetro. Existe también un método clear() que permite eliminar todos los objetos que se encuentren en ese momento en la caché, limpiándola así por completo. Ambos métodos, son útiles para políticas de sincronización entre cachés. La caché de segundo nivel se acoplará a la sesión de Hibernate absorbiendo todos los fallos que se produzcan en ésta. La gran ventaja de utilizar una caché de segundo nivel es que desaparecen los problemas de actualizaciones concurrentes entre sesiones. La caché de segundo nivel se sitúa al mismo nivel que el objeto SessionFactory de Hibernate, recogiendo y coordinando los objetos con los que trabajan las diferentes sesiones. El problema de las actualizaciones concurrentes supone un grave quebradero de cabeza para cualquier sistema de caché. Sea cual sea el modelo que se desee utilizar siempre se tendrá algún problema en relación con las actualizaciones concurrentes, ya sea en mayor o menor medida. La gran ventaja de una caché de segundo nivel, es que ayuda a mitigar estos problemas, al tiempo que alivia de la responsabilidad de almacenar datos temporales, a la caché de primer nivel. La recomendación general con una caché de segundo nivel es utilizar una aproximación de sesión por transacción de aplicación (Sesión por vista). Con una caché de segundo nivel, el gran problema de no aprovechamiento de la caché de primer nivel del que adolecen algunos modelos, desaparece parcialmente. Si un objeto no se encuentra en la caché de primer nivel, Hibernate tratará de obtenerlo de la caché de segundo nivel, de modo que en caso de encontrarse ahí se consigue el ahorro de un hit en la base de datos. Cerrar las sesiones pues, ya no es un problema tan grave (a nivel de rendimiento), ya que aunque se tengan que realizar cientos y cientos de consultas recurrentes, los datos estarán en la caché de segundo nivel, y la pérdida de rendimiento ya no será tan grande. Hibernate permite habilitar individualmente la caché para cada una las entidades. De este modo, se podrá indicar que clases se beneficiarán del uso de una caché, ya que como según lo comentado anteriormente, puede que no todas las clases del sistema se beneficien. Además de esto, al habilitar la caché es necesario establecer la estrategia de concurrencia que Hibernate utilizará para sincronizar la caché de primer nivel con la caché de segundo nivel, y ésta última con la base de datos. Hay cuatro estrategias de concurrencia predefinidas. A continuación aparecen listadas por orden en base a restricciones expresadas en términos de aislamiento transaccional: 130 de 198 Framework Atlas Normativa Transactional: Garantiza un nivel de aislamiento hasta repeatable read, si se necesita. Es el nivel más estricto. Se recomienda su uso cuando no se pueda permitir datos que queden desfasados. Esta estrategia sólo se puede utilizar en entornos basados en clusters, es decir, con cachés distribuidas. Read-write: Mantiene un aislamiento hasta el nivel de commited, utilizando un sistema de marcas de tiempo (timestamps). El caso de uso recomendable es el mismo que para la estrategia transactional pero con la diferencia de que esta estrategia no se puede utilizar en entornos basados en clusters. Nonstrict read-write: No ofrece ninguna garantía de consistencia entre la caché y la base de datos. Para sincronizar los objetos de la caché con la base de datos se utilizan timeouts, de modo que cuando caduca el timeout se recargan los datos. Con esta estrategia se tiene un intervalo en el cual existe el riesgo de obtener objetos desfasados. Cuando Hibernate realiza una operación de flush() en una sesión, se invalidan los objetos de la caché de segundo nivel. Aún así, esta es una operación asíncrona y nunca se tienen garantías de que otro usuario no pueda leer datos erróneos. A pesar de todo esto, esta estrategia es ideal para almacenar datos que no sean demasiado críticos. Read-only: Es la estrategia de concurrencia menos estricta. Ideal para datos que nunca cambian. NORMA ADCache2nivel No se permite el uso de cachés de segundo nivel en Hibernate. En el caso de que se justifique su uso se solicitará una autorización excepcional a ICM. 6.4.6.2 Las cachés distribuidas Las aplicaciones con decenas de miles de usuarios probablemente necesiten ejecutarse en un entorno distribuido, es decir, en cluster. Llegado este momento, el único elemento de Hibernate que necesitaría configurarse es la caché de segundo nivel. Hay dos modos de configurar una caché de segundo nivel de Hibernate en un cluster: · El más sencillo, sin ninguna duda, es colocar en cada nodo del cluster una instancia del proveedor de caché, por ejemplo EHCache, y confiar en los timeout para la sincronización de los proveedores de caché de los diferentes nodos. Este sistema es muy simple, y no presenta retardos de sincronización entre los nodos, ya que no existe sincronización alguna. · El segundo modo, es instalar un proveedor de caché más avanzado que soporte la sincronización de las cachés de los diferentes nodos. El proveedor recomendado por Hibernate para esta tarea es JBossCache, un proveedor totalmente transaccional basado en la librería de multicasting, JGroups, si bien no deja de ser una recomendación por lo que llegado el caso podrá optarse por otro proveedor certificado en Hibernate. 131 de 198 Framework Atlas Normativa DAOCacheDistribuida En concordancia con el apartado anterior, se debe justificar el uso de cachés distribuidas en NORMA entornos basados en cluster, especificando que ventajas aporta con respecto a otro tipo de soluciones que nos proporcione el entorno ya sea a nivel de bases de datos, servidores de aplicaciones, etc. Además el volumen de información a manejar crecerá sustancialmente (replicación) por lo que se tendrá que justificar su uso en contraposición con otros requisitos no funcionales (como alta disponibilidad), ausentes en el entorno de desarrollo/preproducción. 6.4.6.3 La caché de consultas La caché de consultas de Hibernate permite almacenar las consultas realizadas recientemente, de modo que si se vuelven a realizar posteriormente, se recuperen los resultados de un modo mucho más ágil (sin PRACTICA BUENA volver a ejecutar la select a base de datos). ADRendimiento Se desaconseja el uso de la caché de consultas de hibernate, excepto en aplicaciones que sólo realicen consultas (no realicen operación de inserción/borrado/actualización), y realmente hagan uso intensivo de esta caché. 132 de 198 Framework Atlas Normativa 7 CONFIGURACION En todas las aplicaciones es necesario establecer ciertos parámetros que permitan modificar el estado o la configuración del sistema. Así, por ejemplo, a la hora de desarrollar una aplicación se suelen definir constantes y valores predeterminados que quizás interese cambiar a lo largo del tiempo, por lo que incluirlos en el código sería un grave error ya que cada modificación implicaría una recompilación del código. Dentro de la configuración de una aplicación vamos a distinguir distintos tipos de configuraciones: o Configuración particular de la aplicación o Configuración de componentes comunes del framework Además dentro de estas configuraciones nos podemos encontrar con configuración que depende del entorno en el que se ejecute la aplicación (local, desarrollo, validación y producción) y la que no depende de dicho entorno. Las variables de configuración de una aplicación pueden estar situadas en distinto lugar, en función de la naturaleza de la variable: · Librería de configuración común por entorno: Toda la configuración de componentes comunes del framework que es dependiente del entorno y no se necesita personalizar en las aplicaciones (por tanto sólo depende del entorno y no de la aplicación) se ubica en la librería atlascomunes-configuracion-lib. En los entornos de ICM (desarrollo, validación y producción) esta librería ya se encuentra configurada para dicho entorno y publicada en el servidor de aplicaciones para que todas las aplicaciones puedan acceder a ella, de manera que el proveedor no necesita realizar ninguna acción con esta librería. o Un ejemplo de configuración de este tipo podría ser las políticas de seguridad aplicadas en cada entorno, o la configuración del servidor de planificación ControlM. · Fichero application.properties: Este fichero de configuración se encuentra incluido en el directorio src/main/resources/conf de las aplicaciones. En él se deben incluir todas las variables de configuración de la aplicación que NO dependan del entorno en el que esté desplegada (no dependen de que la aplicación se desplegue en local, desarrollo, validación o producción). o Un ejemplo de variable de configuración de este tipo es la que indica el nombre del fichero de menús de la aplicación (menu.xml). Si se trata de variables de configuración referentes a queries (tanto las queries del componente de lista de valores, como queries para la integración con documentum), estas variables se incluirán en el fichero queries.properties. · Fichero environment.properties: Este fichero de configuración se encuentra incluido en el directorio src/main/resources de las aplicaciones. En él se deben incluir todas las variables de 133 de 198 Framework Atlas Normativa configuración de la aplicación SI no dependan del entorno en el que esté desplegada (dependen de que la aplicación se desplegue en local, desarrollo, validación o producción). Durante el despliegue de una aplicación en los entornos de ICM, este fichero será sustituido por su homólogo correspondiente al entorno en el que se desea desplegar. o Un ejemplo de variable de configuración de este tipo es la que indica la ubicación física del fichero de log de la aplicación. CONFEntorno NORMA El fichero enviroment.properties deberá incluir todas las variables que son dependientes del entorno y que se definan a nivel de aplicación. Este es el único fichero que se actualizará a sus valores correspondientes en el despliegue del aplicativo a los distintos entornos. (local, desarrollo, validación, producción, etc). Por lo tanto cada vez que se incluya una variable en el fichero enviroment.properties de la carpeta src/main/resources se debe incluir dicha variable en todos los ficheros enviromnet.properties de todos los entornos. CONFParticular El fichero application.properties deberá incluir las variables que se definan a nivel de aplicación y que no dependan el entorno en el que está desplegada (local, desarrollo, validación, producción, etc.). También deberá incluir aquellas variables de componentes o servicios del NORMA framework que se necesite personalizar para la aplicación y que no dependan del entorno. Si se trata de variables de configuración referentes a queries (tanto las queries SQL/HQL del componente de lista de valores, como queries para la integración con documentum en DQL), estas variables se incluirán en el fichero queries.properties. Las variables de este fichero deberán empezar por “queryCode.” y estarán agrupadas dentro del fichero de manera que se facilite su lectura. Los módulos de tipo librería en lugar de esta norma les aplica la norma CONFLIB. Los módulos de tipo librería han de definir su configuración de forma distinta para que puedan convivir varias librerías y sus configuraciones dentro de un proyecto. Por ello han de seguirse las siguientes instrucciones: · Fichero application-yyyy.properties: En el caso de que una librería incluya variables de configuración cuyos valores son los mismos para todos los proyectos que usen estas librerías y estos valores no dependan del entorno se creará un fichero llamado application-yyyy.properties 134 de 198 Framework Atlas Normativa ,donde yyyy es el nombre de la librería, Este fichero se situará en el directorio src/main/resources/conf de la librería para que se incluya dentro del jar de la misma. Si se trata de variables de configuración referentes a queries, estas variables se incluirán en el fichero queries-yyyy.properties donde yyyy es el nombre de la librería. El fichero irá situado en el mismo directorio que el anterior. Las aplicaciones que utilicen la librería deberán referenciar estos ficheros de configuración dentro del fichero de contexto de Spring applicationContext-general.xml en el bean propertyConfigurer. · Fichero environment.properties: Las librerías NO pueden incluir este fichero de configuración ya que sino sería necesario generar distintas versiones de la librería una por cada entorno. Cuando una librería requiera de variables de configuración que dependen del entorno estas se incluirán en el fichero de configuración de la aplicación que use esta librería (nunca dentro de la librería). Es muy importante que las variables sigan la nomenclatura adecuada para reconocer dentro de una aplicación a quién pertenecen esas variables de configuración. CONFParticularLIB En los módulos de tipo librería el fichero de configuración se llamará applicationyyyy.properties donde yyyy se corresponde con el nombre de la librería. Este fichero deberá NORMA incluir las variables que se definan a nivel de aplicación y que no dependan el entorno en el que está desplegada (local, desarrollo, validación, producción, etc.). Este fichero irá incluido dentro del jar de la librería. Si se trata de variables de configuración referentes a queries estas variables se incluirán en el fichero queries-yyyy.properties donde yyyy se correponde con el nombre de la librería. Las variables de este fichero deberán empezar por “queryCode.” y estarán agrupadas dentro del fichero de manera que se facilite su lectura. NORMA CONFEntornoLIB Los módulos de tipo librería NO pueden incluir el fichero enviroment.properties en el directorio src/main/resources. En el caso de que la librería necesite variables que son dependientes del entorno, estas se incluirán en el fichero enviroment.properties de la aplicación que utilice la librería. 135 de 198 Framework Atlas Normativa CONFNomenclatura La nomenclatura de las variables propias de la aplicación será: xxxx.nombre NORMA Donde xxxx es el nombre del módulo y nombre el nombre de la variable. Estas variables deberán incluir un comentario con la descripción de las mismas. Los comentarios deben aportar claridad, no abusar de ellos intentando que el propio fichero sea autodescriptivo. Para ello ayudará la selección adecuada de los nombres de los parámetros. Los parámetros que hacen referencia a una misma funcionalidad deben ser incluidas en un grupo de elementos adecuadamente comentados. Cuando existan grupos funcionales deben indicarse introduciendo un nivel de anidamiento más en esa estructura para agrupar claramente los valores propios para cada instancia. Esta situación se puede presentar cuando por ejemplo se trabaje con servidores de correo electrónico, donde los datos de conexión y cuentas pueden ser diferentes. NORMA CONFSEG Los ficheros de configuración no contendrán información que supongan riesgo de seguridad según lo establecido por la LOPD, como por ejemplo contraseñas no cifradas. A continuación se muestra un ejemplo de cómo obtener el valor de una variable de configuración definida en el fichero application.properites o environment.properties, desde un fichero de Spring: Ejemplo de fichero application.properties ó environment.properties politicas.url=http://localhost:9080/index.jsf Ejemplo de cómo obtener el valor de una variable de configuración desde Spring <bean id="miBean" class="paquete.MiClase"> <property name="url" value="${politicas.url}"/> </bean> Para obtener el valor de una variable de configuración desde Java, se recomienda inyectar el valor en la clase Java a través de un bean de Spring (según se muestra en el ejemplo anterior). Aunque menos recomendada para los casos habituales, existe otra forma alternativa que consiste en cargar el fichero de propiedades del que se desea obtener la variable y obteniendo su valor de este, según se muestra en el siguiente ejemplo: 136 de 198 Framework Atlas Normativa Ejemplo de cómo obtener el valor de una variable de configuración desde Java import java.util.Properties; import atlas.core.general.PropertiesLoader; public class EjemploProperties { /** singleton para cargar properties de fichero */ private static final Properties PROPS = PropertiesLoader.getInstance( new String[] {"conf/application.properties"}).getProperties(); /** Variable obtenida del fichero application.properties */ public static final String POLITICAS_URL = PROPS.getProperty("politicas.url"); /** * Devuelve el valor de la URL * @return El valor de la URL leída del fichero application.properties */ public String getURLPoliticas() { return POLITICAS_URL; } } 137 de 198 Framework Atlas Normativa 8 SERVICIOS BASICOS El framework Atlas ofrece un conjunto de servicios básicos para cubrir aquellos requisitos comunes a la mayoría de las aplicaciones. Los arquetipos ya vienen preconfigurados para poder utilizar estos servicios básicos. A continuación se muestran con más detalle cada uno de estos servicios básicos. 8.1 SERVICIO DE AUTENTICACION Y AUTORIZACION La Comunidad de Madrid dispone de aplicaciones de carácter público y privado, dependiendo, tanto del tipo de función que desempeñan como del tipo de usuarios al que van dirigidas. En el framework Atlas se ha desarrollado el Servicio de Autenticación y Autorización para cubrir este requisito de gestión de accesos. Las aplicaciones de carácter privado limitaran su acceso a determinados usuarios. La forma de acceder a este tipo de aplicaciones puede ser mediante dos mecanismos: certificado digital y/o login/password. Los usuarios que tienen su acceso permitido a determinadas aplicaciones estarán dados de alta en alguno de los repositorios que la Comunidad de Madrid dispone. En estos repositorios de usuarios se encuentra toda la información de los usuarios y sus perfiles o roles de trabajo para cada aplicación. Estos repositorios son los que se muestran a continuación: Política Repositorio a validar y acciones LDAP Almacena los datos de login de los usuarios de la intranet. Se utiliza para la autenticación de los usuarios. USU Repositorio de usuarios y perfiles de la Comunidad de Madrid. Se utiliza para la autorización de los usuarios. USUI Repositorio de usuarios y perfiles de la Comunidad de Madrid con acceso desde Internet. Se utiliza para la autenticación y autorización de los usuarios. USUJ Repositorio de usuarios y perfiles de la Comunidad de Madrid para aplicaciones de Justicia. Se utiliza para la autenticación y autorización de los usuarios. 138 de 198 Framework Atlas Normativa Para el framework Atlas se han definido unas “políticas de acceso” para las aplicaciones que consisten en la definición de unas reglas de validación de acceso de los usuarios. Estas políticas indican cual es el mecanismo de acceso, contra que repositorios se deben llevar a cabo el proceso de autenticación, así como otras medidas a adoptar. A continuación se muestra una tabla con la lista de políticas de acceso que se han definido para Atlas y que se pueden utilizar en las aplicaciones web. Política Repositorio a validar y acciones Público (no se realizará ninguna acción) Público Certificado Validar Certificado contra la plataforma multipki de ASF Usuario Intranet Validar el usuario contra LDAP y recoger el rol de USU Usuario Internet Validar Certificado (multiPKI) o validar el usuario y recoger su rol en USUI Usuario Justicia Validar Certificado (multiPKI) o validar el usuario y recoger su rol en USUJ Demo Política para desarrollo en la cual no es necesario disponer de ningún repositorio. Los usuarios de pruebas se definen en un fichero xml. 139 de 198 Framework Atlas Normativa En algunas aplicaciones se puede dar el caso de que, dependiendo del entorno desde donde se acceda a la aplicación, la forma de autenticación sea distinta. Por ejemplo: una autenticación con certificado si la aplicación es accedida desde internet y permitir acceso mediante usuario/contraseña para los accesos desde la intranet. El Servicio de Autenticación y Autorización de usuarios permite que dependiendo del dominio/host al que se conecte el usuario se presente una política de acceso u otra, según se haya definido en la aplicación a la que se está accediendo. NORMA SBAutenAuto Aquellas aplicaciones web que tengan que restringir el acceso a determinados usuarios deberán utilizar el Servicio de Autenticación y Autorización del framework Atlas y siempre utilizando alguna de las políticas ya definidas en el mismo. Por otra parte dentro de una aplicación determinados usuarios tendrán acceso a unas opciones y otros usuarios a otras opciones. Esto se va a gestionar creando distintos perfiles o roles según el tipo de usuarios y limitando el acceso a las opciones de menú y a las rutas de acceso según los perfiles creados. NORMA SBAutoPerfiles Si la aplicación tiene distintos perfiles de acceso, la seguridad se debe implementar a nivel de menú y a nivel de urls de acceso. Para más información sobre el Servicio de Autenticación y Autorización consultar el manual ATLAS_MUS_Servicio_Autenticacion_y_Autorizacion. El Real Decreto 3/2010, 8 de enero, por el que se regula el Esquema Nacional de Seguridad en el ámbito de Administración Electrónica, previsto en el artículo 42 de la Ley 11/2007, establece la política de seguridad en la utilización de medios electrónicos por las Administraciones Públicas y estás constituido por principos básicos y requisitos mínimos que permitan una protección adecuada en la información. Para asegurar estos requisitos mínimos del Esquema Nacional de Seguridad en las aplicaciones desarrolladas con el framework Atlas se han implementado los siguientes mecanismos: · En la pantalla de acceso al sistema, se informa, mediante un enlace a las condiciones de acceso, al usuario de las obligaciones que implica la tenencia de un autenticador, en particular el deber de custodia diligente, protección de su confidencialidad e información inmediata en caso de pérdida y ha de indicar que ha leido y acepta las condiciones de acceso. 140 de 198 Framework Atlas Normativa · No se ofrecen mensajes de ayuda en la ventana de conexión al sistema o durante la conexión que den ‘pistas’. Por ejemplo: “Password incorrecta”. El mensaje cuando el usuario no existe, la password es incorrecta o no está asociado a la aplicación es: “Las credenciales introducidas son erróneas”. · No se autorellena el identificador de usuario en el sistema · La información de logín se validará sólo tras rellenar todos los datos de entrada · El sistema presenta al usuario el último acceso realizado con su identidad. 141 de 198 Framework Atlas Normativa · El sistema registra los intentos de acceso exitosos y erróneos al sistema (Fecha, hora e identificador de usuario) en un modelo de datos centralizado que permita su posterior explotación. · Una vez que se ha obtenido el acceso al sistema en la zona de información sobre el usuario se muestra un enlace a un Aviso de Seguridad a partir del cual se muestra una ventana informativa con sus obligaciones principales tras obtener el acceso (uso permitido, uso no permitido, supervisión de la actividad, etc.) No se pueden realizar modificaciones en las aplicaciones que impliquen la modificación o anulación de estos mecanismos. NORMA SBENS No se pueden realizar modificaciones en el control de acceso que impliquen las modificación o anulación de los mecanismos implementados para cubrir los requisitos mínimos del Esquema Nacional de Seguridad. 142 de 198 Framework Atlas Normativa 8.2 COMPONENTES DE PRESENTACION El framework Atlas ofrece un conjunto de componentes visuales para el desarrollo de las interfaces gráficas de usuario de las aplicaciones web. Estos componentes están basados en los siguientes productos: · JSF estándar · RichFaces · Ajax4JSF · Facelets Los componentes que ofrece el framework Atlas son: Componente Descripción Layouts Plantillas para organizar la información dentro de la página Componentes de Menú Componentes para la construcción de menús en una aplicación. Existen 3 tipos de menús: · Menú Vertical · Menú Horizontal · Menú Visual Rastro de Migas Indicador de navegación para situar al usuario en la estructura de contenidos Calendario Facilita al usuario introducir una fecha en un formulario mostrando en un panel emergente un calendario mensual. Lista de Valores Facilita al usuario la introducción de un valor que está asociado a un catálogo Lista Paginada Muestra una lista de datos de forma tabulada en una serie de páginas Mensaje de Error Panel para mostrar un mensaje de error Captcha Ofrece el mecanismo de prueba necesario para determinar cuando un usuario es humano o no. La prueba consiste en introducir por parte del usuario una serie de caracteres los cuales son mostrados de forma distorsionada por pantalla. Número de documento Tiene por objetivo el validar identificadores legales (DNI, CIF, Pasaporte y Tarjeta de Residencia). Código de Barras Permite incrustar en una página un código de barras en diferentes formatos. Arbol Jerárquico Permite mostrar un conjunto de datos organizados jerárquicamente en forma de árbol Arbol Accesible Permite mostrar un conjunto de datos organizados jerárquicamente en forma de árbol cumpliendo con la accesibilidad de las aplicaciones Solapas Permite mostrar una barra de solapas para organizar formularios que incluyen muchos datos 143 de 198 Framework Atlas Normativa Para más información se puede consultar cada uno de los manuales de cada componente. Estos manuales se llaman ATLAS_MUS_Componente_xxxxx 8.3 SERVICIO DE TRAZAS El Servicio de Trazas de Atlas proporciona a todas las aplicaciones una serie de logs automáticos (Inicio /Fin de métodos que deban ser traceados, Transacciones, SQL de las consultas, etc…) durante la ejecución de la aplicación además de formatear todos los logs (tanto generados automáticamente por el componente como los definidos por la propia aplicación) para su posterior uso en la Herramienta de Monitorización. SBTrazas Las aplicaciones deberán generar un único log de aplicación utilizando el Servicio de Trazas que el framework Atlas ofrece. Se deberá hacer un uso adecuado de los niveles de prioridad para los mensajes de logs. Las prioridades predefinidas ofrecidas son (ordenadas de mayor a menor detalle): DEBUG > INFO > WARN > ERROR > FATAL. Estableceremos los siguientes criterios para la explotación de los niveles de log desde nuestro código: · DEBUG: Mensajes de depuración. Se puede utilizar para mostrar el valor de variables, NORMA parámetros de configuración, etc. Son mensajes que deberían ser entendidos y tratados por alguien que conoce el código de la aplicación. Incorporarán información sobre checkpoints que ayudarán a seguir el curso de la ejecución del algoritmo implementado. · INFO: Mensajes de información. Se utilizan para anunciar el progreso en el flujo de la aplicación. Marcarán inicios y finalización de bloques de actividades con cómputos de tiempo empleado en realizarlas, etc. · WARN: Mensajes de advertencia, usado dentro de la aplicación para dar aviso de excepciones esperadas y que nuestro código sepa tratarlas para evitar que la aplicación se interrumpa. · ERROR: Mensajes de error, para dar aviso de errores inesperados que no lleguen a detener o afectar la ejecución de la aplicación, como por ejemplo que algún parámetro de configuración no sea correcto y se cargue el valor por defecto del mismo. · FATAL: Mensajes de error, para dar aviso de errores inesperados que afectan o detienen la ejecución de la aplicación. 144 de 198 Framework Atlas Normativa A continuación se muestra una figura que representa de forma piramidal la jerarquía de niveles de trazas así como la información a mostrar. INFO: Mensajes de información FATAL: Mensajes de error críticos ERROR: Mensajes de error ØInicio-fin de acciones y uso de componentes/servicios. ØImplementar un sistema de alertas que avise de la caída del sistema y dejar notificación del envío en el fichero de log. ØAñadirá un indicador de prioridad junto a información relevante que ayude a comprender el alcance del error: ØFecha, Hora, Nombre de clase, Nombre de método, tiempo de ejecución del método. ØSi la clase o el método accede a base de datos : ØSentencia HQL/SQL con sus parámetros . ØSiempre que sea posible, almacenar información detallada sobre el error producido. ØDeberá integrarse con los sistemas de alertas ICM ØTiempos de preparación y/o ejecución de las consultas. ØNivel 1 : El proceso puede finalizar correctamente a pesar de las inconsistencias producidas. ØNivel 2: Se desconoce si la finalización del proceso puede darse por válida. ØNivel 3: El carácter del error es severo. ØCiclo de vida de las transacciones: inicio y fin (commit y rollback), etc. ØActividad del pool de conexiones WARN: Mensajes de advertencia ØNombre del usuario que invoca al método. ØVolcado de errores con nivel, número y descripción. ØVolcado de los parámetros de configuración (al arrancar) ØPunto del sistema donde se produzca. FATAL ØInformación relacionada sobre el posible impacto ØLas trazas deberán reflejar los datos de la operación que ha generado la excepción. ØValores del fichero de configuración con la que se está realizando la operación. ERROR NIVEL MÍNIMO DE TRAZAS DEBUG: Mensajes de depuración WARN ØInformación detallada de la ejecución de métodos: ØEntrada y salida de un método ØValor de parámetros INFO ØHechos relevantes producidos dentro de un método: ØConstrucción y destrucción de objetos relevantes ØAccesos a objetos locales y remotos DEBUG ØCualquier otra información que permita determinar que se esta realizando en un instante determinado ØEl proceso detallado del flujo de invocaciones sobre toda la infraestructura ØInformación de llamadas entre distintas capas y componentes del sistema Figura 2 : Niveles de trazas NORMA SBTrazasSeg El fichero de log no contendrá información que suponga riesgo de seguridad según lo establecido por la LOPD, como por ejemplo contraseñas no cifradas, datos que identifiquen a menores, minusvalías, etc. 145 de 198 Framework Atlas Normativa 8.4 SERVICIO DE AUDITORIA DE SEGURIDAD Los Sistemas de Información de la Comunidad de Madrid en algunos casos tratan datos personales de nivel alto que son especialmente protegidos según el Real Decreto 1720/2007 - Reglamento desarrollo de la LOPD. Algunos ejemplos de datos personales de nivel alto son: § Ideología, afiliación sindical, religión, creencias, origen racial, salud o vida sexual. § Recabados con fines policiales sin consentimiento. § Derivados de actos de violencia de género. § Tráfico y localización en operadores que prestan servicios de comunicaciones electrónicas. En estos casos es obligado que se recoja información sobre los accesos realizados a dichos datos. El Servicio de Auditoria de Atlas se encarga de auditar los accesos mencionados anteriormente. Para ello es necesario que la aplicación indique cuáles son aquellos datos susceptibles de ser auditados, basándose en los mecanismos que ofrecen los framework’s Spring e Hibernate. El Servicio de Auditoria intercepta todas las operaciones de base de datos que se realizan a través de Hibernate y deja el registro de la auditoria en el esquema TRAZ a través del paquete de base de datos ATLAS.PACK.LOG. Para más información sobre la utilización de este servicio consultar el manual NORMA ATLAS_MUS_Servicio_Auditoria. SBAudit Las aplicaciones que precisen auditar los accesos a los datos protegidos lo harán a través del Servicio de Auditoria del framework Atlas. 146 de 198 Framework Atlas Normativa 9 INTEGRACION El framework Atlas para cubrir los requisitos de integración con otros productos ofrece una serie de servicios adicionales que vamos a denominar servicios de integración. A continuación se muestran los distintos servicios que ofrece el framework. En el caso de que un proyecto tenga un requisito de integración con otro producto o tecnología se debe comunicar al Area de Aplicaciones Especiales y Arquitectura de Software para que se valore la mejor forma de realizar dicha integración. 147 de 198 Framework Atlas Normativa 9.1 SERVICIO DE GESTIÓN DOCUMENTAL La solución de gestión documental para las aplicaciones de la Comunidad de Madrid es el gestor de documental de EMC Documentum. La plataforma EMC Documentum es una extensa suite de productos para la gestión documental que proporciona servicios para la creación, gestión, distribución y archivo de cualquier tipo de contenido documental. Sobre este producto se ha construido un servicio dentro del framework Atlas que permite un acceso a la plataforma de gestión documental independiente de la solución elegida. La integración con el gestor documental se realiza en dos ambitos: · Acceso al core de documentum mediante programación · Componentes visuales que acceden al gestor documental Para facilitar la configuración y uso de este servicio se ha creado el arquetipo web documental por lo tanto los módulos web que necesiten acceder a este servicio deberían partir de este arquetipo. Por otra parte en los proyectos que incluyen gestión documental es necesario crear un módulo que las definiciones de los tipos documentales y demás elementos necesarios. Para más información sobre este tipo de módulos consultar el manual ATLAS_MUS_Servicio_Gestion_Documental, y ATLAS_MUS_Arquetipo_Web_Documentum. NORMA SIGDOC Las aplicaciones que necesiten acceder a un gestor documental lo harán a través del Servicio de Gestión Documental y accediendo a través de los servicios web implementados dentro de este servicio. Actualmente este Servicio de Gestión Documental se ha implementado sobre Documentum. 148 de 198 Framework Atlas Normativa 9.2 SERVICIO DE PLANIFICACION En ocasiones es necesario ejecutar ciertas tareas a una hora concreta, en base a una planificación preestablecida. Tal es el caso de la ejecución de informes periódicos, o la generación de estadísticas. Este tipo de tareas suele conllevar una carga importante para la base de datos, cosa que puede empeorar el rendimiento de la aplicación (y de otros sistemas). Para este tipo de tareas normalmente pesadas, existe una solución simple: planificar la creación del informe para las horas cuando el sistema tiene menor carga de trabajo. La solución elegida para realizar la planificación de las tareas mencionadas anteriormente es el producto de BMC CONTROL-M. Figura 3 : Planificación de tareas con Control-M Para poder invocar a este tipo de tareas necesitamos crear un módulo batch que implementa la tarea a ejecutar y utilizar el Servicio de planificación para ejecutar o planificar la tarea. NORMA El Servicio de Planificación ofrece os siguientes elementos: · Acceso al api de ControlM mediante programación · Componentes visuales que muestran información obtenida de ControlM SIPLAN Las aplicaciones que necesiten invocar una tarea batch lo harán a través del Servicio de Planificación del framework Atlas. 149 de 198 Framework Atlas Normativa 9.3 SERVICIO DE CRIPTOGRAFIA Las aplicaciones de la Comunidad de Madrid muchas veces requieren de la utilización de certificados digitales y/o operaciones criptográficas que posibilitan la tramitación electrónica. NORMA El Servicio de Critografía, provee las siguientes funcionalidades: · Cifrado y descifrado de datos · Firma electrónica en servidor · Verificación de firmas electrónicas · Validación de certificados digitales · Obtención de datos de un certificado SICert Las aplicaciones que necesiten realizar operaciones con certificados digitales y/o criptográficas lo harán a través del Servicio de Criptografía que ofrece el framework Atlas. Para más información sobre el uso del servicio de certificados digitales consultar el manual ATLAS_MUS_Servicio_Criptografia. 150 de 198 Framework Atlas Normativa 9.4 SERVICIO DE BUSSINESS INTELLIGENT La solución de Bussiness Intelligent para los proyectos de la Comunidad de Madrid es Bussiness Objects de SAP. Sobre este producto se han definido dentro del framework Atlas una serie de componentes visuales que permite un acceso directo a la plataforma de Bussiness Objects. Business Objects XI ofrece, en una única solución, funciones de gestión de rendimiento, generación de informes, consulta y análisis e integración de datos, apoyando a una correcta toma de decisiones tanto a nivel ejecutivo y directivo como a nivel estratégico. Integra distintas fuentes de datos, abstrayendo dichas fuentes, así como los modelos subyacentes, creando una capa semántica con entidades entendibles para el usuario ejecutor y consumidor de los informes, sin necesidad de conocer los modelos de datos relacionales. Esta capa semántica es lo que se conoce en Business Objects XI por el concepto de Universo. Business Objects XI es un producto completamente autónomo y completo que unifica todo el ciclo de gestión y producción de informes. Las principales características aportadas por Business Objects XI son: l Acceso y presentación de datos en diversos formatos. l Integración de múltiples fuentes de datos. l Abstracción de las fuentes de datos en un conjunto de entidades entendibles por parte del usuario que realiza los informes. Esta abstracción permite que los usuarios que realmente tienen necesidad de extraer información, puedan realizar informes sin necesidad de tener los conocimientos técnicos necesarios para comprender el modelo de datos subyacentes. l Modificación y creación de reportes en tiempo de ejecución. l Gestión eficiente y segura de reportes críticos para el negocio. l Entrega de la información requerida a la gente adecuada en un momento determinado. l Basado en un tecnología fuertemente probada. l Escalabilidad y rendimiento adaptables en base al crecimiento del negocio. l Soporte a distintos lenguajes de programación. l Gestión de la seguridad en todos los niveles. Las siguientes tareas del ciclo de vida de generación de informes se deben realizar con las aplicaciones aportadas por el producto Business Objects XI: l Tareas de extracción, transformación y carga (ETL). l Definición de Universos. l Organización en carpetas y subcarpetas. l Definición de usuarios y permisos a nivel de datos, de carpetas y de informes. l Creación de informes. l Planificicación de informes. La integración con Business Objects XI de las aplicaciones desarrolladas con Atlas se limitará a las siguientes tareas: 151 de 198 Framework Atlas Normativa l Conexión al servidor Business Objects XI con las credenciales definidas en la implantación BO. l Recorrido de carpetas autorizadas. l Visionado de los informes de esas carpetas. l Planificación de informes En proyectos que integren una solución completa de Business Objects XI, el ciclo de vida de la extracción de información se gestionará por medio de las aplicaciones que proporciona la plataforma Business Objects XI, y no desde la integración con Atlas. La integración con Atlas se limitará a la presentación, NORMA visionado y planificación de los informes generados por la plataforma Business Objects XI. SIBI Las aplicaciones que necesiten acceder a la plataforma de Bussiness Objects lo harán a través de los componentes establecidos en el framework Atlas. 152 de 198 Framework Atlas Normativa 9.5 SERVICIO DE INVOCACIÓN DE SERVICIOS WEB Muchas de las aplicaciones que se desarrollan para la Comunidad de Madrid necesitan acceder a servicios web tanto servicios que se han desarrollado específicamente para la tramitación electrónica como otros servicios web que incluso pueden estar fuera de nuestros entornos. Dada la amplia variedad de tipos de servicios web que nos podemos encontrar y los distintos tipos de seguridad que nos pueden requerir los citados servicios web se ha desarrollado el Servicio Invocador de Servicios. En el caso de que el servicio a utilizar se haya desarrollado con Atlas se ha de acceder utilizar el cliente Atlas que proporciene el servicio web. NORMA NORMA Para más información sobre este servicio consultar el manual ATLAS_MUS_Servicios_Web. INTWS Para invocar a un servicio web se hará mediante la utilización del Servicio de Invocación de Servicios Web de Atlas. INTNomClient Para facilitar su localización el nombre del paquete donde se incluyan las clases generadas por el invocador de servicios debe contener la palabra client. 153 de 198 Framework Atlas Normativa 9.6 SERVICIO DE PROCESOS DE NEGOCIO Un proceso de negocio es la representación del trabajo realizado por las personas y los sistemas de una organización, con el objetivo de ofrecer un servicio a sus clientes. Business Process Management (BPM) es el arte de formalizar la automatización de los procesos de negocio. Un BPM simplifica el desarrollo de aplicaciones que tengan alguno de los siguientes requerimientos: · Orquestación de servicios de negocio: es la secuenciación de las diferentes tareas y servicios que forman parte de un proceso. La orquestación permite crear lógica dentro del proceso, ofreciendo funcionalidades tales como: o Invocación sincrónica y asincrónica a servicios. o Manejo de transacciones. o Mecanismos de compensación y manejo de excepciones. o Transformación de mensajes para adaptar la salida de un servicio a la entrada de otro (mapeo de datos). o Manejo de condicionales, loops, etc. o Orientación a flujos de trabajo: los BPM ofrecen herramientas para definir los procesos de negocio que comprenden un sistema. Los procesos de negocio pueden comprender tareas desempeñadas por personas, y tareas que se ejecutan de forma automática. · Integración de personas dentro de los flujos de trabajo: cuando la ejecución de un proceso requiere que ciertas personas en la organización realicen funciones relacionadas con el proceso (aprobaciones, revisiones, etc.), el uso de un BPM simplifica la interacción con las mismas. · Necesidades de integración con diferentes sistemas y fuentes de datos: los BPM disponen de conectores para acceder a diferentes sistemas comerciales existentes en grandes organizaciones (SAP, PeopleSoft, CICS, etc.), de forma que la creación de tareas en las que intervenga este tipo de productos se simplifica enormemente. · Capacidades de seguimiento y gestión de las tareas definidas en los procesos de negocio: un BPM ofrece herramientas administrativas que permiten a ciertas personas poder hacer un seguimiento de los procesos y tareas que los comprenden. · Medición, auditoría, control y reportes: asociado a un producto de este tipo se ofrecen herramientas para realizar métricas y análisis del funcionamiento global del sistema. · Aplicación de reglas de negocio. · Ejecución de procesos con estado. 154 de 198 Framework Atlas Normativa La solución de BPM (procesos de negocio) para las aplicaciones de la Comunidad de Madrid es producto Oracle BPM. Sobre este producto se ha construido un servicio dentro del framework Atlas que permite un acceso a la plataforma de BPM independiente de la solución elegida, este servicio se denomina Servicio de Procesos de Negocio. La integración con el motor de procesos se realiza en dos ambitos: · Acceso al core de Oracle BPM mediante programación · Componentes visuales que muestran información obtenida del motor de procesos NORMA SIBPM 9.7 Las aplicaciones que necesiten acceder a un motor de procesos lo harán a través del Servicio de Procesos de Negocio de Atlas. Actualmente este Servicio de Procesos de Negocio se ha implementado sobre el producto Oracle BPM. OTRAS SOLUCIONES Por otra parte dentro del framework Atlas se ha seleccionado una serie de soluciones o librerías de terceros que nos cubren otras funcionalidades o requisitos que podamos tener a la hora de desarrollar NORMA nuestra aplicación. SOLLIB El uso de cualquier librería, producto de terceros o tecnología no incluido dentro del framework deberá ser previamente consensuado y autorizado por ICM. 155 de 198 Framework Atlas Normativa 9.7.1 REPORTING La solución de generación de listados e informes para las aplicaciones de la Comunidad de Madrid es Crystal Reports 2008. Para utilizar informes de Crystal Reports 2008 en las distintas aplicaciones de la Comunidad de Madrid, se ha optado por una solución centralizada que libera a la aplicación que va a utilizar los informes de la complejidad de su generación e interpretación. Para obtener más información sobre el uso de informes con Crystal Reports consultar el manual ATLAS_MUS_Arquetipo_Web. Para incluir informes en nuestra aplicación en primer lugar debemos diseñar o crear dichos informes con la herramienta Crystal Reports 2008. SOLRpt NORMA La herramienta de creación de los informes de las aplicaciones será Crystal Reports 2008. El nombre del informe tendrá la siguiente nomenclatura: XXXXNombreDelInforme.rpt Donde xxxx es el nombre del proyecto y NombreDelInforme el nombre del informe que debe estar escrito en minúsculas, excepto la primera letra de cada palabra que estará en mayúsculas. Este nombre no puede contener espacios en blanco. La extensión debe ser rpt. La conexión con la base de datos deberá ser JDBC y desde la propia herramienta se puede ejecutar el informe para ver el resultado del mismo. SOLRptConex El tipo de conexión con la base de datos debe ser JDBC. NORMA Los informes se desarrollarán integrando las sentencias SQL dentro del informe, no estando permitidas las opciones de ResultSet, RecordSet ni colecciones de objetos, a no ser que así se acuerde explícitamente con ICM. El nombre de las tablas de base de datos dentro del informe rpt desarrollado no deberán incluir el nombre de la instancia de base de datos. De esta forma será posible ejecutar los informes sobre distintas instancias (desarrollo, test, producción...) sin necesidad de modificar el fichero rpt. Una vez que tengamos los informes completados se deberán publicar en la plataforma de BO. En la entrega se agruparan los distintos informes dentro de un nuevo módulo de tipo reports. 156 de 198 Framework Atlas Normativa NORMA SOLRptModulo Todos los informes se entregaran en un módulo con la siguiente nomenclatura: xxxx_crbo Donde xxxx es el nombre del proyecto. Dentro se creará una carpeta llamada reports donde se incluirán todos los reports. SOLRptConf NORMA El fichero de configuración environment.properties debe incluir las siguientes variables: · bo_ws.webservice – Apunta a la url del servicio web bo_ws para autenticación · bo_ws.rutabo – Servidor de la plataforma BO (Ej: http://icmdesbi01:8080) · bo_ws.usuario – Usuario con el que nos conectaremos a la plataforma de Bussiness Objects. · bo_ws.clave – Clave del usuario encriptada. 157 de 198 Framework Atlas Normativa 9.7.2 COMPOSICION DE DOCUMENTOS Este punto tiene por objetivo explicar como se realizará la generación dinámica de documentos Word y RTF, a partir de plantillas previamente definidas en este mismo formato. Para el relleno de las plantillas así como la transformación dinámica de las mismas se utilizará Velocity. Velocity es un motor de plantillas basado en Java que incluye un lenguaje de script, el Lenguaje de Plantillas de Velocity (VTL por sus siglas en inglés). El Lenguaje de Plantillas de Velocity (VTL) nos permite incorporar contenido dinámico dentro de un documento de tipo texto de una manera fácil y sencilla. Este lenguaje se utilizará para la creación de las plantillas. Desde la parte del negocio de la aplicación es dónde se va a realizar la fusión de las plantillas utilizando el API Java de Velocity. Se trata de que la fusión del documento se realice en el lado del servidor. El uso del API en java básicamente consiste en definir un contexto con las variables a mapear en el documento, aplicar este contexto a la plantilla y generar el nuevo documento. Documentos RTF Contenedor Web .doc, .rtf Petición JSF Documento generado Documento generado Plantilla Velocity VTL .html, txt, etc Documento origen Respuesta JSF DOCUMENTUM .doc, .rtf Motor de plantillas velocity Figura 4 : Generación de documentos RTF NORMA SOLCompositor Para la composición de documentos en Atlas se utilizará la solución de Velocity. Las plantillas se crearán en formato RTF y los documentos generados tendrán también formato RTF. Las plantillas se incluirán en la carpeta “plantillas” del proyecto. BUENAS PRACTICAS SOLCompositor · Se recomienda utilizar nombres significativos en las variables, y notaciones sencillas al hacer uso de las etiquetas que dote de claridad a la plantilla y sea fácilmente inteligible mediante una lectura rápida. Esto ayudará a realizar un buen mantenimiento de la misma cuando sea necesario aplicarla modificaciones. · Se recomienda utilizar sintaxis de etiquetas simple, escapando de notaciones más complejas a no ser que esté justificada claramente su utilización. · Se recomienda no anidar bucles en la medida de lo posible. Estos procesos interactivos 158 de 198 Framework Atlas Normativa complican los procesos de renderizado. · Se recomienda hacer uso de las estructura de datos estándar: string, list y map. Su procesado es rápido y eficaz. · Se recomienda incorporar macros a las plantillas cuando se prevea una reutilización del mismo en varios puntos del documento o cuando la operación de renderizado se presuponga compleja. En este último caso el macro deberá mostrar una interfaz clara en su llamada que aporte la máxima claridad a la plantilla. · Se recomienda escapar de utilizar llamadas a macros de manera recursiva. · Se recomienda delegar el menor trabajo posible al generador de documentos. A pesar de que incorporan cierta potencia de calculo, operaciones y operadores, manejo avanzado de estructuras de datos, etc… prescindir cuando sea posible de ello, delegando esos cálculos a nuestra aplicación y dejando que el compositor de documentos sólo realice la tarea de renderizado, la de “dibujar” el documento, es decir los datos que alimentan la plantilla, deben de ir adecuadamente tratados y formateados. 159 de 198 Framework Atlas Normativa 9.7.3 GESTION DE DOCUMENTOS EXCEL NORMA La solución del framework Atlas para la generación o modificación de ficheros Excel es Jakarta POI. SOLExcel Para la gestión de documentos Excel en las aplicaciones del framework Atlas se utilizará la librería Jakarta POI. Desde las aplicaciones se usuará directamente este API desde la capa de negocio. 160 de 198 Framework Atlas Normativa 9.7.4 GESTION DE DOCUMENTOS PDF Para la generación y manipulación dinámica de PDFs se deberá utilizar la librería iText. Se debería utilizar esta librería en casos como: · Generación dinámica de documentos PDF mediante APIs de desarrollo en base a varias NORMA alternativas de fuentes de datos como bases de datos, ficheros XML, etc. · Crear mapas, libros electrónicos, dotar de interactividad a documentos PDF. · Añadir bookmarks, números de página, filigranas, etc. · Dividir y concatenar documentos pdf. SOLPDF Para la generación de documentos PDF desde las aplicaciones del framework Atlas se utilizará la librería IText. A pesar de que iText permite la generación de documento RTF, para esta finalidad ha de emplearse Velocity, ya que es un mecanismo más flexible y potente. 161 de 198 Framework Atlas Normativa 9.7.5 GENERACION DE GRAFICOS Para la generación de gráficos se utilizará la librería JFreeChart, una librería 100% Java que permite desarrollar gráficos, para poder incluirlos en aplicaciones, documentos e informes. Con JFreeChart podremos hacer diferentes tipos de gráficos que van desde los tipos comunes tales como gráficos circulares , gráficos de barras , áreas , gráficos de línea , histogramas , diagramas de Gantt y más específicos y menos frecuentemente utilizados como tipos Candlestick, Viento y Wafer Map. También se puede usar la familia Chart de Jenia4faces, que ofrece componentes JSF para la inclusión de gráficas realizadas mediante JFreeChart en una aplicación JSF. NORMA SOLGraficos La generación de gráficos de las aplicaciones del framework Atlas se hará con la librería JFreeChart y los componentes visuales Jenia4Faces. PRACTICA BUENA SOLGraficosGrandes Como norma general se recomienda tener especial cuidado con imágenes de JFreeChart que ocupen mucho espacio y puedan saturar el ancho de banda en aplicaciones con interfaz Web. 162 de 198 Framework Atlas Normativa 9.7.6 MANIPULACION DE ARCHIVOS MULTIMEDIA En muchas ocasiones surge la necesidad de utilizar un API que permita la incorporación de archivos audio, video, sonido u otro tipo de archivos multimedia en aplicaciones Java, extendiendo las capacidades multimedia por defecto de la plataforma Java 2 Standard Edition. La tecnología Java Media FrameWork API (JMF) permite manipular y gestionar ficheros de audio, video u otros archivos multimedia que formen parte integral de aplicaciones y applets. Este paquete opcional actúa sobre múltiples formatos, proporcionando a desarrolladores un control adicional escalable e independiente de la plataforma de proceso y renderizado de archivos multimedia. JMF esta diseñada en base a plugins proporcionando acceso directo a recursos multimedia y aportando a JMF las caracteríticas necesarias para personalizarlo y extenderlo en base a necesidades específicas. SOLMultimedia El API JMF 2.X será la tecnología a utilizar para cualquier manipulación sobre archivos NORMA multimedia. Este API no esta incluida por defecto en la plataforma Java 2 Standard Edition. Cuando se necesite extender las capacidades de la tecnología JMF en referencia a la manipulación de ficheros de imagen se podrá recurrir a las API’s Java 2D, Java advanced Image (JAI) y JAI Image I/O. Se deberá utilizar el API Java 3D cuando se requieran capacidades adicionales sobre manipulaciones y renderizados de imágenes en tres dimensiones. 163 de 198 Framework Atlas Normativa 9.7.7 Acceso a plataforma y dispositivos locales La plataforma local define los elementos, herramientas, servicios y productos residentes en la máquina de cada usuario para dar soporte a la ejecución de las aplicaciones de la organización cubriendo la extensión de las aplicaciones web de cara a interactuar con elementos residentes en la plataforma local, como NORMA pueden ser dispositivos y aplicaciones. SOLAccesoLocal Para la integración con los dispositivos y aplicaciones de la plataforma local se utilizarán y desarrollarán componentes de tipo Applet. 164 de 198 Framework Atlas Normativa 9.7.8 XML Sólo lectura Si una aplicación necesita leer ficheros XML (sólo leer) se podrá usar la librería XPath del paquete javax.xml.xpath La clase de ayuda de Altas atlas.core.seguridad.util.XmlUtil tiene varias funciones para ayudar a leer ficheros XML con unas pocas instrucciones. Ejemplo de lectura de XML String xml = "..."; Document xmlDocument = XmlUtil.toDomDocument(xml); String cdDocumento = XmlUtil.evaluateXpathToString("/salida/codigoDocumento", xmlDocument); NodeList listaNodos = XmlUtil.evaluateXpathToNodeList( "/salida/listado_interesados//interesado", xmlDocument); 9.7.9 XML Lectura y Escritura Algunas aplicaciones necesitan gestionar ficheros XML. Para facilitar la gestión de los mismos se utilizará la librería JAXB. JAXB aporta una forma sencilla de asociar un esquema XML a su representación en código Java. Esto hace simple el manejo de datos XML desde Java, sin necesidad de conocer mucho acerca de XML. JAXB consta de 3 componentes principales: · El compilador de esquema, que transforma el esquema en una serie de elementos requeridos para el proceso de lectura (unmarshalling) y escritura (marshalling) de un XML. · El generador de esquema, que convierte estos elementos (descritos mediante anotaciones Java) a un esquema XML. · El framework de asociación (binding), que ofrece las operaciones de lectura (unmarshalling) y escritura (marshalling) para el acceso, manipulación y validación de contenido XML usando los elementos generados mediante las herramientas anteriores. El siguiente esquema muestra un diagrama de funcionamiento de estos elementos: 165 de 198 Framework Atlas Normativa NORMA SOLXML Cuando las aplicaciones necesiten generar ficheros XML, se utilizará la implementación de referencia de JAXB (Java Architecture for XML Binding). Para facilitar su localización y que la herramienta de validación no de errores las clases generadas por jaxb se incluirán en un subpaquete llamado “jaxb”. Los pasos para realizar la asociación entre un documento XML y un objeto Java con JAXB son los siguientes: 1. Generar las clases Java (a partir del esquema XML). Recordar que se deben incluir en un subpaquete llamado “jaxb” de alguno de los paquetes de nuestra aplicación. 2. Compilar las clases. 3. Leer el documento origen (unmarshall). 4. Generar el árbol de contenido. El proceso de lectura genera un árbol de contenido a partir de las clases generadas. 5. Validar: antes de generar el árbol de contenido a partir del XML origen se puede validar dicho documento. También se puede validar el documento a generar (cuando sea el caso). 6. Procesar el contenido. La aplicación cliente puede modificar los datos del documento XML que representa el árbol de contenido a través de los interfaces generados por el compilador 7. Escritura (marshall), esto es, generar uno o más documentos XML a partir del árbol de contenidos. Como se dijo anteriormente, el contenido puede ser validado antes de este proceso. La siguiente imagen muestra de forma gráfica el proceso descrito: 166 de 198 Framework Atlas Normativa Figura 5 : Asociación de un documento XML con un objeto Java 167 de 198 Framework Atlas Normativa 9.7.10 ENVIO DE CORREO El framework Spring ofrece una librería de utilidad para enviar correos electrónicos abstrayendo al usuario de la configuración específica para cada sistema de mensajería, responsable del manejo de recursos a bajo nivel que normalmente ha de implementar el cliente. NORMA SOLCorreo Para el envío de correo desde las aplicaciones se empleará la utilidad de envío de correo que aporta el framework de Spring. Dicha utilidad permite el envío de correo de una forma sencilla mediante JavaMail, realizando la configuración mediante inyección de dependencias. En primer lugar hay definir los parámetros de configuración del environment.properties. Los parámteros host, user y pass son obligatorios, el resto son opcionales y se usan para las plantillas de los correos. environment.properties # correo electronico email.smtp.host=mail.madrid.org email.smtp.user=PENDIENTE email.smtp.pass=PENDIENTE # plantilla email email.from=icm_dga_soporte_arquitectura@madrid.org email.subject=Ejemplo de correo para cursos Seguidamente hay definir y configurar el bean de Spring para enviar correos. Bean encargado del envio de correos <!-- Bean para el envio de correos --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host"><value>${email.smtp.host}</value></property> <property name="username"><value>${email.smtp.user}</value></property> <property name="password"><value>${email.smtp.pass}</value></property> </bean> Se crearán plantillas para las distintas tipologías de correo electrónico que la aplicación envíe. De esta forma no será necesario escribir en el código aspectos como el destinatario, el asunto, etc. Ejemplo de bean de mensaje <!-- Plantilla para enviar correo de ejemplo --> 168 de 198 Framework Atlas Normativa <bean id="plantillaCorreoCursos" class="org.springframework.mail.SimpleMailMessage"> <property name="from"><value>${email.from}</value></property> <property name="subject"><value>${email.subject}</value></property> </bean> Para hacer uso de los beans inyectados anteriormente, simplemente se declararán los atributos respectivos en el servicio, con sus métodos set correspondientes. Ejemplo de bean de servicio que envía correo <bean id="cursosService" class="ejpl.gestion.services.CursosServiceImpl"> <property name="mailSender"><ref bean="mailSender"/></property> <property name="message"><ref bean="plantillaCorreoCursos"/></property> <bean> Ejemplo de envio de correo ..... private MailSender mailSender; private SimpleMailMessage mailMessage; public void setMailSender(MailSender mailSender) { this.mailSender = mailSender; } public void setMailMessage(SimpleMailMessage mailMessage) { this.mailMessage = mailMessage; } public void sendCourseEnrollmentReport() { Set courseList = courseDao.findAll(); SimpleMailMessage message = new SimpleMailMessage(this.mailMessage); StringBuffer messageText = new StringBuffer(); messageText.append("Los cursos son los siguientes:\n\n"); for(Iterator iter = courseList.iterator(); iter.hasNext(); ) { Course course = (Course) iter.next(); messageText.append(course.getId() + " "); messageText.append(course.getName() + " "); int enrollment = courseDao.getEnrollment(course); messageText.append(enrollment); } message.setText(messageText.toString()); 169 de 198 Framework Atlas Normativa msg.setTo(…); try { mailSender.send(message); } catch (MailException e) { …. } } ..... Cuando el contenido de los correos electrónicos manejados por la aplicación sea complejo, se empleará el mecanismo de plantillas que ofrece Velocity para crear plantillas avanzadas para envío de correo electrónico. Estas plantillas se podrán crear en formato HTML y se almacenaran en la carpeta “src/main/resources/plantillas”. Ejemplo de plantilla de correo <html> <body> <h3>Hi ${user.userName}, welcome to the Chipping Sodbury On-the-Hill message boards!</h3> <div>Your email address is <a href="mailto:${user.emailAddress}">${user.emailAddress}</a>. </div> </body> </html> De esta forma se pueden crear plantillas de correo mediante cualquier editor (por ejemplo, con un editor de HTML), y definir variables que se establecerán en tiempo de ejecución para el mensaje de correo. Para usar Velocity desde un servicio Spring, simplemente se le ha de pasar mediante inyección de control el bean de Spring que maneja el motor de Velocity, y usarlo en el código de envío de correo de la forma tradicional: Bean de Spring para Velocity <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> <property name="velocityProperties"> <value>resource.loader=class 170 de 198 Framework Atlas Normativa class.resource.loader.class= org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader </value> </property> </bean> Para enviar el mensaje, ahora es necesario hacer uso de un mensaje MIME (estamos enviando un mail en HTML), para lo cual usamos el interfaz de MimeMessagePreparator de Spring: Ejemplo de envio de correo con plantilla personalizada private void sendConfirmationEmail(final User user) { MimeMessagePreparator preparator = new MimeMessagePreparator() { public void prepare(MimeMessage mimeMessage) throws Exception { MimeMessageHelper message = new MimeMessageHelper(mimeMessage); message.setTo(user.getEmailAddress()); message.setFrom("from@email.com"); // Se establecen los campos a mapear en el correo Map model = new HashMap(); model.put("user", user); String text = VelocityEngineUtils.mergeTemplateIntoString( velocityEngine, "plantillas/correo.vm", model); message.setText(text, true); } }; this.mailSender.send(preparator); } } NOTA Para una explicación más detallada de integración del servicio de correo de Spring en Atlas consulte el Manual de Usuario de Envío de Correos Electrónicos. 171 de 198 Framework Atlas Normativa 9.7.11 ENVIO DE SMS La Comunidad de Madrid dispone de una plataforma desarrollada por Telefónica Soluciones para el envío y recepción de mensajes SMS, que recibe el nombre de MenTeS (Mensajería de Telefónica Soluciones). Sobre esta plataforma se ha desarrollado un servicio web que ofrecerá una interfaz estándar para el acceso a estas funcionalidades desde cualquier tipo de aplicativo. El siguiente diagrama muestra la arquitectura del sistema: Figura 6 : Arquitectura de la plataforma de SMS Para el envío de mensajes SMS se utilizará el servicio de envío de SMS que invoca a los servicios web . Para más información consultar el manual ATLAS_MUS_Servicio_Envio_SMS. 172 de 198 Framework Atlas Normativa 9.7.12 VISOR DE MAPAS Dentro del framework Atlas se ha incorporado un componente visor de mapas permite mostrar mapas de GIS y operar con ellos en aplicaciones Atlas. Tiene las siguientes características: · Permite personalizar el tamaño del marco en el que se muestra el mapa. · Dos modos de renderizado: en un marco en pantalla o en un panel popup. · Personalización del mapa y los componentes que lo forman mediante la modificación de los ficheros de configuración de GIS. A continuación se muestra un ejemplo del componente en modo popup: Para más información consultar el manual ATLAS_MUS_Componente_Visor_Mapas. 173 de 198 Framework Atlas Normativa 9.7.13 SERVICIOS WEB La invocación y generación de servicios web de ATLAS se basa en los siguientes elementos: · Axis2 · Módulo de seguridad Rampart · Módulo de seguridad para webservices de ATLAS · Plataforma multipki ASF Para la creación de nuevos servicios web se partirá de un arquetipo específico para servicios web. Los servicios web desarrollados implementaran además del propio servicio web una librería cliente para dicho servicio que facilitará la integración de este servicio web en otros proyectos Atlas. Para más información consultar el manual ATLAS_MUS_Servicios_Web.doc. Los servicios web que tengan que implementar seguridad lo harán según el estandar de WS Security que incluye la seguridad en el propio mensaje SOAP. Dentro de este modelo de seguridad existen las siguientes posibilidades: - Firmado digital del mensaje SOAP – Garantiza la procedencia del mensaje, integridad de los datos y no repudio. - Cifrado del mensaje SOAP – Garantiza la confidencialidad del mensaje. Ambas posibilidades se pueden combinar. Se puede realizar el control de acceso sobre el cliente que ha firmado el mensaje. Al cifrar el mensaje no es necesario cifrar el canal de comunicación. NORMA WSSECURITY Cuando el servicio web que se desarrolle tengan que implementar seguridad lo hará con WS Security con los mecanismos de firma y/o cifrado de mensaje SOAP. Cualquier otro tipo de seguridad ha de ser autorizado previamente por la Unidad de Arquitectura de Aplicaciones. 174 de 198 Framework Atlas Normativa 10 HERRAMIENTAS El framework ATLAS ofrece principalmente dos herramientas de apoyo al desarrollo de aplicaciones que aseguran la calidad de los desarrollos realizados, y que se describen en los siguientes apartados. 10.1 VALIDACION DE NORMATIVA La comprobación del cumplimiento de la normativa ATLAS en un módulo técnico se realiza a través del servicio SAVT y tiene como objetivo principal la comprobación del cumplimiento de la normativa Atlas sobre un proyecto o módulo. Este servicio realiza las siguientes comprobaciones sobre los tipos de recurso de un proyecto: · Valida las clases java. · Valida los ficheros de configuración. · Valida la estructura de directorios. Dicha herramienta está implementada como un plugin que ya viene preinstalado y correctamente configurado con los arquetipos de Atlas para su ejecución directa a través de ciertas etiquetas de Maven. PRACTICA BUENA VALFrecuente Se deberá ejecutar la revisión de codigo semanalmente desde el inicio del proyecto (no sólo al final del proyecto) con el fin de evitar que los incumplimientos de la normativa se vayan acumulando a lo largo del desarrollo y esto suponga carga adicional de trabajo. No es posible automatizar la comprobación de todas las normas, lo que no significa que el proveedor no deba cumplirlas. Por lo tanto es posible que durante el desarrollo de la aplicación aparezcan nuevas versiones de la herramienta de validación. Estas nuevas versiones en ningún caso incluirán validación de nuevas normas sino que podrán validar normas ya definidas en la versión del framework pero que anteriormente no se estaban validando (y por tanto el proveedor ya debería estar cumpliendo, independientemente de que anteriormente la herramienta las validase o no). Por todo lo anteriormente indicado, el hecho de que el servicio SAVT no indique errores en un proyecto no implica que dicho proyecto cumpla al 100% con todas las normas de la normativa del framework, aunque sí asegura un porcentaje alto de cumplimiento. Existen casos excepcionales en los que ICM autoriza previamente que no se le aplique alguna de las normas. Estos casos deben ser autorizados utilizando la solicitud correspondiente que firmará el Área de 175 de 198 Framework Atlas Normativa Aplicaciones Especiales y Arquitectura de software. Esta autorización deberá ser incluida en la solicitud de revisión de codigo. VALEXCLUDE NORMA Toda autorización excepcional a alguna norma de la normativa debe estar previamente autorizada por ICM. La solicitud de autorización se hará mediante el formulario de autorización correspondiente y una vez firmado por el Área de Aplicaciones Especiales y Arquitectura de Software será incluido en la documentación del proyecto. En las entregas se deberá informar en la ficha de entrega sobre la autorización. Para más información sobre el uso del servicio SAVT consultar la Guía de Calidad en: http://intranet.madrid.org/arquitecturasw/calidad/servicios 10.2 REVISION DE CODIGO ESTATICO Un estándar de codificación adecuado y buen diseño orientado a objetos son prácticas que deben estar presentes en todos los proyectos. Es necesario imponer una normalización a la hora de desarrollar código debido a diferentes factores que facilitarán el mantenimiento posterior y costes económicos derivados de tal actividad. • Un porcentaje elevado del coste del software va asociado a su mantenimiento. • Las aplicaciones son dinámicas, crecen y se modifican, requieren de mantenimiento y evolución. • Las convenciones de código nos facilitarán la interpretación fácil de nuestro código, más rápida y más clara. • Debemos pues garantizar el cumplimiento con estas convenciones. Para todos los desarrollos en Java con el framework Atlas se deben utilizar las convenciones de código para el lenguaje de programación Java de SUN Microsystems. Estas convenciones están disponibles en la url: http://java.sun.com/docs/codeconv/ El uso de convenciones de código se debe realizar desde la primera linea de código que se implemente y no esperar a que se haya finalizado el desarrollo ya que en este caso el coste del cambio es muy elevado. La herramienta Eclipse nos permite mediante determinados plugins validar que se estan cumpliendo estas convenciones. Dentro del framework Atlas se han personalizado los ficheros de reglas para que se realicen las validaciones que el framework requiere. 176 de 198 Framework Atlas Normativa La validación se debe realizar según se van codificando las clases. En el caso de que ya tengamos código desarrollado y queramos ajustarlo a esta codificación Eclipse dispone de utilidades que nos permiten formatear el código para que se cumplan muchas de las reglas que se validan. Las herramientas que se van a utilizar para la validación son: Herramientas URL Code Style Formatter de Eclipse Incluido en eclipse Code Style Clean up de Eclipse Incluido en eclipse Plugin de Checkstyle http://eclipse-cs.sourceforge.net/ Plugin de PMD http://pmd.sourceforge.net/ PMD: Conjunto de reglas basadas en el análisis de código Java que identifica problemas como código muerto, posibles bugs, etc... Checkstyle: Herramienta para el análisis estático de código usado para chequear que el código fuente Java cumple con unas reglas de codificación determinadas. El framework proporciona los siguientes ficheros de reglas: Fichero Descripción ATLAS_JAVA_CC_CS.xml Fichero con las reglas de checkstyle del framework Atlas ATLAS_JAVA_CC_PMD.xml Fichero con las reglas de pmd del framework Atlas ATLAS_JAVA_CC_ECLIPSE_CLEANUP_PROFILE.xml Fichero con las opciones para la utilidad de cleanup de Eclipse ATLAS_JAVA_CC_ECLIPSE_FORMATTER_PROFILE.xml Fichero con las opciones para la utilidad de formatter de Eclipse. Para más información sobre el uso de estas utilidades consultar el manual ATLAS_MUS_Preparacion_Entorno_Desarrollo. 177 de 198 Framework Atlas Normativa NORMA CSPMD Los módulos desarrollados deberán cumplir las reglas de checkstyle y pmd específicas del framework Atlas. CODFrecuente PRACTICA BUENA Se recomienda ejecutar frecuentemente las herramientas proporcionadas por el framework Atlas para validar que se cumplen las normas de codificiación Java (herramientas Checkstyle y PMD), con el fin de evitar que los incumplimientos de la normativa se vayan acumulando a lo largo del desarrollo y esto suponga carga adicional de trabajo. Puede configurarse el entorno de desarrollo Eclipse para que compruebe las normas de Checkstyle y PMD en caliente, al tiempo que el programador va desarrollando la aplicación. 10.3 GENERACION AUTOMÁTICA DE CODIGO A partir de la versión 1.2.0 del framework de desarrollo de aplicaciones ATLAS, se incluye una herramienta de generación automática de código. Esta herramienta permite, a partir de un modelo de datos, generar código para gestionar las operaciones básicas (alta, baja, modificación y consulta) de ese modelo de datos de acuerdo a la normativa del framework Atlas en las distintas capas de la aplicación. La herramienta nos permite seleccionar las tablas de las que queremos generar el código, y a partir de ellas realiza una ingeniería inversa del modelo de datos y genera el código en la aplicación. Para el desarrollo de la herramienta se ha tomado como punto de partida el plugin JBoss Hibernate Tools, y se ha personalizado su configuración para adaptarlo a las necesidades propias de ATLAS. GENCOD PRACTICA BUENA Se recomienda al inicio del desarrollo utilizar la herramienta de generación automática de codigo del framework Atlas. El código generado por la herramienta va a reducir el coste/tiempo de desarrollo del proyecto ya que nos va a generar el código requerido por el framework Atlas para el acceso a base de datos en las operaciones básicas de alta, baja, modificación y consulta y en el caso de mantenimiento de catálogos nos va a generar también las pantallas de usuario que permiten la gestión del catálogo en las operaciones básicas tal y como se ha indicado. Atención El código fuente generado es un punto de partida para el desarrollo. Lo generado se debe evolucionar 178 de 198 Framework Atlas Normativa para adaptarlo a las necesidades y requisitos específicos del proyecto. A continuación se muestran, para cada una de las capas del framework Atlas, los diagramas de clases del código que se genera. Se ha tomado como ejemplo una entidad de base de datos llamada Expediente. Para una descripción más detallada de este código y conocer como utilizar la herramienta se debe consultar el manual ATLAS_MUS_Generador_Codigo que se puede encontrar en la sección “Desarrollos Atlas->Herramientas” del portal de arquitectura. 179 de 198 Framework Atlas Normativa 10.3.1 ACCESO A DATOS En la capa de acceso a datos la herramienta va a generar las clases que la normativa del framework Atlas determina (Clases de dominio y DAOS) para las operaciones básicas de consulta, alta, baja y modificación. Además se van a realizar las correspondientes actualizaciones en los ficheros de configuración de Spring para que estas clases puedan ser usadas desde los servicios de negocio. Clases generadas para la capa de acceso a datos class Acceso a Datos «interface» dao::BaseDAO + + + + + + + + + + + + + + findAll() : List<T> countAll() : Long findAllDistinct() : List<T> countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T> count(AtlasQuery) : int exists(PK) : boolean insert(T) : T insertOrUpdate(T ) : void update(T ) : void delete(PK) : void delete(T ) : void findByNamedQuery(String, Map<String, Object>) : List<T> java.io.Serializable «interface» dao:: ExpedienteDAO T PK:extends Serializable HibernateDaoSupport dao::BaseDAOImpl - logger: Log = LogFactory.getL... {readOnly} persistentClass: Class<T> + + + + + + + + + + + + + + + + # BaseDAOImpl(Class<T>) BaseDAOImpl(Class<T>, SessionFactory) findAll() : List<T > countAll() : Long findAllDistinct() : List<T > countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T> count(AtlasQuery) : int findInternal(AtlasOrder[], AtlasQuery, boolean) : Criteria exists(PK) : boolean insert(T ) : T insertOrUpdate(T) : void update(T) : void delete(PK) : void delete(T ) : void findByNamedQuery(String, Map<String, Object>) : List<T> getLog() : Log dao::ExpedienteDAOImpl + ExpedienteDAOImpl() expedienteDAO : ExpedienteDAOImpl Bean de Spring para utilizar desde los servicios de negocio. 180 de 198 domain::Expediente - serialVersionUID: long = 1L {readOnly} idExpediente: Integer oficina: Oficina cdExpediente: String dsExpediente: String itEstado: String fcAlta: Date fcModif: Date clDsExtendida: Clob nmCdUadmin: Integer expeInteresados: Set<ExpeInteresado> = new HashSet<Exp... expeArchivos: Set<ExpeArchivo> = new HashSet<Exp... + + + Expediente() Expediente(Integer) Expediente(Integer, Oficina, String, String, String, Date, Date, Clob, Integer, Set<ExpeInteresado>, Set<ExpeArchivo>) getIdExpediente() : Integer setIdExpediente(Integer) : void getPKAsString() : String getPKFromString(String) : Integer getOficina() : Oficina setOficina(Oficina) : void getCdExpediente() : String setCdExpediente(String) : void getT extoListaValores() : String getDsExpediente() : String setDsExpediente(String) : void getItEstado() : String setItEstado(String) : void getFcAlta() : Date setFcAlta(Date) : void getFcModif() : Date setFcModif(Date) : void getClDsExtendida() : Clob setClDsExtendida(Clob) : void getNmCdUadmin() : Integer setNmCdUadmin(Integer) : void getExpeInteresados() : Set<ExpeInteresado> setExpeInteresados(Set<ExpeInteresado>) : void getExpeArchivos() : Set<ExpeArchivo> setExpeArchivos(Set<ExpeArchivo>) : void toString() : String equals(Object) : boolean hashCode() : int + + + + + + + + + + + + + + + + + + + + + + + + + + + + Framework Atlas Normativa 10.3.2 SERVICIOS DE NEGOCIO En la capa de servicios de negocio la herramienta va a generar las clases que la normativa del framework Atlas determina (Fachada y Servicios) para las operaciones básicas de consulta, alta, baja y modificación invocando para su ejecución a los DAOs de la capa de acceso a datos. Además va a realizar las correspondientes configuraciones para incluir objetos de estos servicios en el contexto de Spring.. Código generado para la capa de servicio de negocio class Serv icio «interface» serv ices::BaseServ ice + + + + + + + + + + + + + + + + setDao(D) : void getDao() : D findAll() : List<T > countAll() : Long findAllDistinct() : List<T > countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T > count(AtlasQuery) : int exists(PK) : boolean insert(T) : T insertOrUpdate(T) : void update(T ) : void delete(PK) : void delete(T) : void findByNamedQuery(String, Map<String, Object>) : List<T> facade::PruebasFacadeImpl «interface» serv ices:: ExpedienteServ ice -expedienteService + + + + + + + + + + + + + + + + setDao(D) : void getDao() : D findAll() : List<T > countAll() : Long findAllDistinct() : List<T> countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T > count(AtlasQuery) : int exists(PK) : boolean insert(T ) : T insertOrUpdate(T ) : void update(T) : void delete(PK) : void delete(T) : void findByNamedQuery(String, Map<String, Object>) : List<T > + + setExpedienteService(ExpedienteService) : void findExpediente(int, int, AtlasOrder[], AtlasQuery) : List<Expediente> findExpediente(Integer) : Expediente countExpediente(AtlasQuery) : int insertExpediente(Expediente) : void updateExpediente(Expediente) : void insertOrUpdateExpediente(Expediente) : void deleteExpediente(Expediente) : void deleteExpediente(Integer) : void «interface» facade::PruebasFacade + serv ices::BaseServ iceImpl logger: Log = LogFactory.getL... {readOnly} dao: D expedienteService: ExpedienteService + + + + + + + T PK:extends Serializable D:extends BaseDAO<T, PK> - - expedienteDAO : ExpedienteDAOImpl expediente : Expediente + + + + + + + findExpediente(int, int, AtlasOrder[], AtlasQuery) : List<Expediente> findExpediente(Integer) : Expediente countExpediente(AtlasQuery) : int insertExpediente(Expediente) : void updateExpediente(Expediente) : void insertOrUpdateExpediente(Expediente) : void deleteExpediente(Expediente) : void deleteExpediente(Integer) : void serv ices:: ExpedienteServ iceImpl expedienteServ ice : ExpedienteServ iceImpl pruebasFacade : PruebasFacadeImpl Bean de Spring para ser usado desde los beans de respaldo de JSF 181 de 198 Framework Atlas Normativa 10.3.3 PRESENTACION En la capa de presentación se generan para cada una de las entidades/tablas unas pantallas que nos permitan realizar el mantenimiento básico de dicha tabla. La generación de la parte de presentación está pensada como una solución para generar el código asociado al mantenimiento de cátalogos que tipicamente podemos encontrar en las aplicaciones. A continuación se muestra el código generado en la capa de presentación: Código generado: Presentación class Presentacion listaExpediente.xhtml formularioExpediente.xhtml expedienteBean : ExpedienteBean expedienteBean : ExpedienteBean Managed Bean para ser usado desde las páginas JSF j sf::ExpedienteBean - serialVersionUID: long = 1L {readOnly} facade: PruebasFacade orderAndFilter: OrderAndFilterBean = null entidad: Expediente = null listaValoresOficina: ListaValores textoOficina: String oficinaFilter: String cdExpedienteFilter: String dsExpedienteFilter: String itEstadoFilter: String fcAltaFilter: Date fcModifFilter: Date scroller: UIDataScroller = new UIDataScroller() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ExpedienteBean() getEntidad() : Expediente setEntidad(Expediente) : void getFacade() : PruebasFacade setFacade(PruebasFacade) : void getTimeZone() : TimeZone getOrderAndFilter() : OrderAndFilterBean setOrderAndFilter(OrderAndFilterBean) : void obtener(int, int, Object, Object) : List<Expediente> obtenerTotal(Object) : int cargar() : String cargar(ActionEvent) : void eliminar() : String eliminar(ActionEvent) : void confirmarEliminar() : String confirmarEliminar(AjaxBehaviorEvent) : void guardar() : String nuevo() : String volver() : String getListaValoresOficina() : ListaValores setListaValoresOficina(ListaValores) : void setTextoOficina(String) : void getTextoOficina() : String obtenerListaOficina(int, int, Object, Object) : List<AtlasHashMap> obtenerTotalOficina(Object) : int getOficinaFilter() : String setOficinaFilter(String) : void getCdExpedienteFilter() : String setCdExpedienteFilter(String) : void getDsExpedienteFilter() : String setDsExpedienteFilter(String) : void getItEstadoFilter() : String setItEstadoFilter(String) : void getFcAltaFilter() : Date setFcAltaFilter(Date) : void getFcModifFilter() : Date setFcModifFilter(Date) : void getScroller() : UIDataScroller setScroller(UIDataScroller) : void filtrar() : String setIdOficina(String) : void getRequiredMessage() : String «interface» facade::PruebasFacade + + -facade + + + + + + -entidad 182 de 198 countExpediente(AtlasQuery) : int insertExpediente(Expediente) : void updateExpediente(Expediente) : void findExpediente(int, int, AtlasOrder[], AtlasQuery) : List<Expediente> findExpediente(Integer) : Expediente insertOrUpdateExpediente(Expediente) : void deleteExpediente(Expediente) : void deleteExpediente(Integer) : void java.io.Serializable domain::Expediente Framework Atlas Normativa A continuación se muestran ejemplos de pantallas generadas para el mantenimiento de la entidad Expediente. Ejemplo de página xhtml generada Listado: listaExpediente.xhtml Desde esta pantalla nos permite realizar las siguientes operaciones: · Búsqueda basada en filtros · Nuevo elemento: Accede a la pantalla de alta · Eliminación · Edición: Accede a la pantalla de edición Características de esta pantalla: · Filtros: o Para cada campo de la tabla de tipo Textual se genera un <inputText> para buscar en ese campo. o En el caso de que un campo sea una foreign key de una tabla se genera un <inputText> para buscar en el primer campo de tipo texto de la tabla foránea. · Tabla de resultados: o Ordenación por columnas o Paginación 183 de 198 Framework Atlas Normativa Ejemplo de página xhtml generada Página de alta y edición: formularioExpediente.xhtml Características de esta pantalla: · Para los campos que son foreign key de otra tabla se genera un <inputText> asociado a una lista de valores. · Para los campos de tipo Date se genera un campo de tipo Calendario · Resto de campos se genera un <inputText> de tamaño fijo · Cada campo lleva asociado un enlace a una ayuda de contexto · Los campos generados de tipo <inputText> cuyo valor es obligatorio (en la tabla de base de datos tienen la propiedad NOT NULL) se marcan en amarillo, y si no se rellenan se muestra un mensaje de error indicándolo. 184 de 198 Framework Atlas Normativa 11 PRUEBAS El desarrollo de software requiere e implica la construcción de aplicaciones de forma robusta, extensible y escalable. Conseguir dichos objetivos requiere la aplicación de una metodología de desarrollo que incluya la realización de pruebas de software precisas. El “objetivo de las pruebas” de software es “asegurar que el producto final cumple todas las funcionalidades requeridas por los usuarios”. Para conseguir dicho objetivo, los encargados de realizar las pruebas tendrán que revisar el producto final y concluir si los requisitos iniciales son completamente satisfechos. La ejecución de pruebas es tan importante que se debe hacer durante todo el tiempo y a lo largo del ciclo de vida de desarrollo del software. Mediante las pruebas de software es posible demostrar formalmente que las especificaciones funcionales y técnicas se cumplen. Un software probado contendrá menos errores y será más seguro. Por otro lado, la demora en la corrección de errores software hace que sea más costosa su detección y eliminación. Si un error es detectado en el mismo momento en el cual el desarrollador hace un cambio, será probable que pueda arreglarlo en ese instante. Por el contrario si un error no es detectado hasta después de la entrega parcial o final el coste de su detección se dispara, además de la consiguiente pérdida de confianza generada. Por último comentar que la realización de pruebas permite poder refactorizar el código con la seguridad de que el comportamiento seguirá siendo correcto. La refactorización ayuda a resaltar o recuperar la claridad de un diseño que se ha ido complicando a causa de modificaciones o implementaciones posteriores. 11.1 TIPOS DE PRUEBAS Los tipos de pruebas a desarrollar en el momento de probar el software pueden ser categorizadas de diferente forma: · Pruebas unitarias: Las pruebas unitarias ejercitan el funcionamiento de una unidad de código, normalmente una clase aislada del resto de la aplicación. Su objetivo es comprobar que su estructura es correcta y que se ajusta a la funcionalidad establecida previamente y aprobada en la fase de análisis. Es muy importante incorporar la implementación de pruebas unitarias a la metodología de desarrollo, de modo que las pruebas unitarias se desarrollen a la vez que se implementa el código, probando cada parte del código que se desarrolla (test-driven development, o desarrollo guiado por las pruebas). 185 de 198 Framework Atlas Normativa TESTUnitarios Todos los bloques funcionales de la aplicación deberán contener Tests que realicen las pruebas unitarias de dicho bloque funcional. Para implementar las pruebas unitarias se utilizará como herramienta principal JUnit (los arquetipos ya vienen preparados para trabajar con esta herramienta). Se podrán utilizar objetos mock como los pertenecientes a las librerías JMock, Spring NORMA Mock, EasyMock y PowerMock. Se podrán utilizar herramientas a modo de extensión de JUnit como pueda ser DBUnit que mejoren y faciliten el proceso de pruebas unitarias. Las clases de testeo se deben incluir en la carpeta src/test/java. Desde de esta carpeta se crearan con la misma estructura de paquetes que se ha definido en el proyecto. Los recursos necesarios para ejecutar las pruebas (ficheros de configuración, etc) se incluirán en la carpeta src/test/resources. Esta batería de pruebas nunca se deberá incluir en el proyecto final que se despliegue en el entorno de producción (esto será controlado por maven en empaquetación de la aplicación). · Pruebas de integración: Las pruebas integrales o pruebas de integración son aquellas que se realizan en el ámbito del desarrollo de software una vez que se han aprobado las pruebas unitarias. Únicamente se refieren a la prueba o pruebas de todos los elementos unitarios que componen un proceso, hecha en conjunto, de una sola vez. Estas pruebas permiten comprobar que la unión de partes de software funcionan juntos y de forma correcta. 186 de 198 Framework Atlas Normativa TESTIntegracion Para realizar los test de integración se recomienda la utilización del paquete org.springframework.test “spring-mock.jar” que permite realizar pruebas de integración mediante el contenedor Spring. NORMA También se permite el uso de las librerías JMock, EasyMock y PowerMock Las clases de testeo se deben incluir en la carpeta src/test/java. Desde de esta carpeta se crearan con la misma estructura de paquetes que se ha definido en el proyecto. Los recursos necesarios para ejecutar las pruebas (ficheros de configuración, etc) se incluirán en la carpeta src/test/resources. Esta batería de pruebas nunca se deberá incluir en el proyecto final que se despliegue en el entorno de producción (esto será controlado por maven en empaquetación de la aplicación). · Pruebas funcionales (aceptación): Las pruebas funcionales y de aceptación permiten a los usuarios finales comprobar que toda la funcionalidad de la aplicación está implementada. Puede involucrar procesos de pruebas automáticas y parte manual aunque esto último debe limitarse al mínimo. TESTAceptacion Para automatizar pruebas de aceptación de módulos web se utilizará la herramienta Selenium. NORMA Cuando las pruebas a realizar sean sobre servicios web, se utilizará la herramienta SoapUI. Los tests de Selenium deben ir incluidos en un módulo del proyecto aparte llamado “test”, que se crea al generar el proyecto partiendo del arquetipo. Las clases de testeo se deben incluir en la carpeta src/test/java del módulo test. Los recursos necesarios para ejecutar las pruebas con Selenium (ficheros de configuración, etc) se incluirán en la carpeta src/test/resources del módulo test. · Pruebas de servicios web: Las pruebas de los servicios web permiten a los clientes finales de los servicios web comprobar el correcto funcionamiento de los mismos además de poder automatizarla 187 de 198 Framework Atlas Normativa y repetir dichas pruebas en cualquier momento. Estas pruebas se realizan utilizando la herramienta SoapUI. TESTServiciosWeb Se implementarán pruebas en los módulos de tipo webservice para cubrir los distintos NORMA métodos expuestos en las interfaces de los distintos servicios web del módulo. Para implementar las pruebas de servicios web se utilizará la herramienta SoapUI. Los tests de SoapUI deben ir incluidos en el submódulo del proyecto llamado “test”, que se crea al generar el proyecto partiendo del arquetipo. Los tests se deben incluir en la carpeta src/test/soapui del módulo test. · Pruebas de carga y stress: Las pruebas de carga y stress evalúan el rendimiento del sistema en base a los requisitos. Permite verificar el comportamiento del sistema en situaciones extremas, tanto en carga como en tiempo, donde los usuarios y peticiones se producen de forma concurrente. TESTRendimiento Se implementarán pruebas de carga y estrés para las funcionalidades de la aplicación en NORMA las que el rendimiento sea un factor a tener en cuenta. Para implementar las pruebas de carga y estrés se utilizará JMeter. Los tests de JMeter deben ir incluidos en un módulo del proyecto aparte llamado “test”, que se crea al generar el proyecto partiendo del arquetipo. Los tests se deben incluir en la carpeta src/test/jmeter del módulo test. · Pruebas de usabilidad: Las pruebas de usabilidad permiten comprobar que la aplicación no solo cumple funcionalmente su cometido, sino que además, es fácil e intuitivo su uso. · Revisiones de código estático: Una vía de detección de muchos errores y de mejora de los diseños es la realización de revisiones de código. Las revisiones de código se realizan por el propio desarrollador y por otros desarrolladores. Es altamente recomendable realizar revisiones de código periódicas, ya que mejoran la calidad del software tanto en diseño como en robustez. Este tipo de revisiones ya se han indicado en el apartado Validación de codificación Java. 188 de 198 Framework Atlas Normativa NORMA TESTAutomatizacion NORMA A continuación se definen algunas normas generales para la ejecución de pruebas: TESTCobertura Se empleará Maven como herramienta para la ejecución automática de las pruebas y los informes de resultados de las mismas. La cobertura del código debe incluir las ramas principales y de más importancia en la aplicación. 189 de 198 Framework Atlas Normativa 11.2 PLAN DE PRUEBAS Un plan de pruebas debe ser interpretado como la piedra angular y en consecuencia el principal factor crítico de éxito para la puesta en práctica de un proceso de pruebas que permita entregar un software de calidad ya que resumirá, entre otras cosas, las actividades de prueba que se deberán realizar. De tal forma, se puede definir el plan de pruebas como un documento que describe el alcance, enfoque, recursos y calendario de las actividades de prueba. Además identificará elementos a evaluar, características, tareas, responsabilidades y prevendrá de riesgos que quizás requieran un plan de contingencia. Identifica ítems de prueba, características a ser probadas, tareas de prueba, quien realizará cada tarea y riesgos que quizás requieran un plan de contingencia. Además, los planes de pruebas son especialmente útiles al tratarse de documentos sencillos de revisar, lo que confiere la posibilidad a individuos que pertenecen a roles distintos (equipo de ingenieros, responsables de proyecto, etc.) poder inspeccionarlo y adaptarlo a sus necesidades concretas. TESTPlanPruebas Como parte de los entregables de los proyectos será necesario entregar los planes de pruebas, los resultados de los mismos y un informe de evaluación de dichos resultados. El plan de pruebas entregado por el proveedor tendrá que incorporar (como mínimo) los siguientes elementos · Identificador del plan de pruebas: El identificador será de alguna forma mnemónica que permita relacionarlo con su alcance, por ejemplo: PP-Global (plan de pruebas global), PP-Aceptacion (plan de pruebas para pruebas de aceptación), NORMA etc. · Versión y la fecha del plan de pruebas. · Alcance del plan de pruebas: Se deberá especificar los requisitos que se van a probar con este plan. Por otra parte se deberán indicar igualmente aquellos requisitos excluidos justificando los motivos por los cuales no se van a probar. · Configuración necesaria · Para cada uno de los siguientes tipos de pruebas incluir un apartado donde se especifiquen los casos de prueba, el instrumento o herramienta usada, donde pueden ser encontrados, cómo serán ejecutados y los datos que serán usados. · Pruebas unitarias · Pruebas de integración · Pruebas de aceptación · Pruebas de carga y estrés 190 de 198 Framework Atlas Normativa 11.3 DOCUMENTACION DEL CODIGO La documentación del código debe explicar claramente que función realiza dicho código y debe exponer toda funcionalidad interna que afecte a su comportamiento externo. Además debe incluir información que permita identificar el autor del código (el proveedor) para permitir una rápida resolución del problema. Por otra parte, es necesario que se incluya información sobre la versión en la que se incluyeron nuevos métodos o la etiqueta deprecated si el método está obsoleto. JAVADOC NORMA Todas las clases Java de las aplicaciones deberán incluir tanto en sus métodos como en sus propiedades las correspondientes etiquetas de Javadoc que permitan generar la documentación correspondiente. Asimismo, todas las clases java deben incluir una cabecera en la que se muestre una descripción de la clase, y en la que se incluya la etiqueta @author indicando el proveedor que realiza el desarrollo. El porcentaje de javadoc que se debe incluir es del 100%. A continuación se muestra un ejemplo de clase Java con la documentación completa: package ejpl.comunes.general; import java.util.Properties; /** * Clase de ejemplo correctamente documentada con javadoc * @author ICM */ public class EjemploJavaDoc { /** identificador de serialización */ private static final long serialVersionUID = 30460628734587345L; /** Ejemplo de variable */ public static final String CONSTANTE = "prueba"; /** * Ejemplo de método documentado * @return un objeto de tipo {@link String} */ public String getValor() { return CONSTANTE; } } 191 de 198 Framework Atlas Normativa 12 ENTREGA El proveedor desarrollará los distintos módulos en sus instalaciones y posteriormente realizará la entrega al Responsable de Proyecto para que solicite a la Unidad de de Paso a Producción el despliegue de la misma en el entorno de desarrollo. La Unidad de Paso a Producción desempeña actualmente las tareas de despliegue en el entorno de desarrollo durante la fase de construcción y hasta la puesta en producción de la aplicación. La Unidad de Paso a Producción dispone de un servidor SFTP para que los proveedores puedan realizar las entregas. La entrega del proyecto de un proveedor externo al responsable de proyecto deberá efectuarse mediante alguno de los siguientes mecanismos: · Entrega de un CD/DVD al jefe de proyecto · Entrega en el directorio del proveedor en el SFTP destinado a tal efecto En cada entrega el proveedor deberá cumplimentar una ficha de instalación (disponible en la web) que deberá enviar al responsable de proyecto para que la revise antes de solicitar la instalación. La Unidad de Paso a Producción se encargará de la compilación y despliegue de los distintos módulos entregados sin la asistencia del proveedor, por lo tanto la entrega deberá tener la estructura de directorios exigida y todo el código fuente, librerias, etc necesarios para la compilación del proyecto. Pudiendo desestimarse la instalación si no se cumple lo anterior. PRACTICA BUENA ENTREGAParcial A lo largo del ciclo de vida del desarrollo del proyecto es recomendable realizar al menos dos entregas intermedias a ICM, al 30% y 70% del desarrollo, no realizando una única entrega final con todo el proyecto sólo cuando esté finalizado. La Unidad de Paso a Producción emitirá un resumen de la realización de la instalación al jefe de proyecto. Tras la primera instalación de un proyecto la Unidad de Paso a Producción creará el repositorio de subversion para el control de versiones de este proyecto. A partir de este momento las solicitudes a la Unidad de Paso a Producción pueden hacerse bien con una nueva entrega en el servidor FTP o bien creando subiendo la entrega a subversión tal y como se indica en 192 de 198 Framework Atlas Normativa el siguiente manual: NORMA http://www.madrid.org/arquitecturasw/images/documentacion/portal/actual/Guia_Uso_Subversion.pdf ENTREGABUILD Es obligatorio que la aplicación entregada compile correctamente sin errores. NORMA NORMA ENTREGATARGET 13 La entrega sólo debe contener los ficheros fuente del proyecto, no se incluirá el directorio “target” generado por Maven. Dentro de la entrega no se incluirá ninguna librería “jar” ya que éstas se descargarán automáticamente del repositorio artifactory. ENTREGALIB Las aplicaciones no podrán utilizar librerías externas que no estén incluidas en el repositorio artifactory de ICM, a no ser que sean autorizadas por ICM. ENLACES RELACIONADOS Producto URL Portal para el desarrollo http://gestiona.madrid.org/arquitecturasw de aplicaciones Artifactory de Atlas http://gestiona.madrid.org/artifactory 193 de 198 Framework Atlas Normativa A1.1 NORMAS ENTORNO .................................................................................................................................................................... 19 ENTORNOEJECUCION ............................................................................................................................................. 19 ARQUETIPOS .............................................................................................................................................................. 21 NOMARCHIVO ............................................................................................................................................................ 22 NOMPAQUETES ......................................................................................................................................................... 22 VERSIONADO .............................................................................................................................................................. 22 IMPLWEB ..................................................................................................................................................................... 23 LIBCOMUN .................................................................................................................................................................. 24 IMPLLIB ....................................................................................................................................................................... 24 IMPLWS ........................................................................................................................................................................ 25 WSLIBCLIENTE .......................................................................................................................................................... 25 IMPLBATCH ................................................................................................................................................................ 26 REFLEXION ................................................................................................................................................................. 27 GARBAGE .................................................................................................................................................................... 27 MULTIHILO ................................................................................................................................................................. 27 CLASESIGUALES ....................................................................................................................................................... 27 JSFCOMPONENTES ................................................................................................................................................... 29 JSFXHTML ................................................................................................................................................................... 30 JSFPOB .......................................................................................................................................................................... 30 JSFNEGOCIO ............................................................................................................................................................... 33 JSFVALIDACION ........................................................................................................................................................ 38 JSFCUSTOMVALIDATOR ........................................................................................................................................ 39 JSFCUSTOMCONVERSOR ....................................................................................................................................... 39 JSFINTERNALIZACION............................................................................................................................................ 40 JSFLAYOUT ................................................................................................................................................................. 44 JSFPANEL .................................................................................................................................................................... 45 JSFCUSTOMMENU .................................................................................................................................................... 46 JSFJAVASCRIPT ......................................................................................................................................................... 46 JSFJQUERY.................................................................................................................................................................. 46 JSFACCESIBILIDAD .................................................................................................................................................. 48 JSFIMAGENES ............................................................................................................................................................ 48 JSFCSS ........................................................................................................................................................................... 49 JSFIFRAMES................................................................................................................................................................ 49 JSFAJAX ....................................................................................................................................................................... 50 JSFAJAXINTERAC ..................................................................................................................................................... 50 JSFMBEANSIMPL....................................................................................................................................................... 54 JSFANOTACION ......................................................................................................................................................... 56 194 de 198 Framework Atlas Normativa JSFMBATRIBUTOS .................................................................................................................................................... 56 JSFFACADE ................................................................................................................................................................. 57 JSFEXCEPTION .......................................................................................................................................................... 58 JSFNAVEGACION ...................................................................................................................................................... 59 JSFFACESCONFIGXML ............................................................................................................................................ 62 JSFREQUEST ............................................................................................................................................................... 63 JSFNAVDES.................................................................................................................................................................. 65 JSFCONFADICIONAL................................................................................................................................................ 67 JSFWEBXML ............................................................................................................................................................... 67 JSFSESION ................................................................................................................................................................... 69 JSFHTTPSESSION ...................................................................................................................................................... 69 JSFTIEMPOSESION ................................................................................................................................................... 69 JSFUSOSESION ........................................................................................................................................................... 69 JSFCREACIONSESION .............................................................................................................................................. 70 SNFACADE ................................................................................................................................................................... 72 SNFACADEIMPL......................................................................................................................................................... 73 SNDOMINIO ................................................................................................................................................................. 74 SNSERVICEIMPL ....................................................................................................................................................... 76 SNANOTACION ........................................................................................................................................................... 76 SNMVC .......................................................................................................................................................................... 77 SNSPRING .................................................................................................................................................................... 81 SNSPRINGLIB .............................................................................................................................................................. 81 SNDEPENDENCIAS .................................................................................................................................................... 82 SNAMBITOS ................................................................................................................................................................. 83 SNTHROWSEXCEPTION .......................................................................................................................................... 84 SNCUSTOMEXCEPTION .......................................................................................................................................... 84 SNNEGOCIOEXCEPTION ......................................................................................................................................... 85 SNSYSTEMEXCEPTION............................................................................................................................................ 86 SNDAOEXCEPTION ................................................................................................................................................... 86 SNTRANSACTIONANNOTATED ............................................................................................................................. 91 SNTRANSACTIONDEFAULT ................................................................................................................................... 91 SNTRANSACTIONROLLBACK ............................................................................................................................... 92 SNFICHEROSTEMPORALES ................................................................................................................................... 94 ADHIBERNATE ........................................................................................................................................................... 96 DAODATASOURCE .................................................................................................................................................... 97 DAOSESSION ............................................................................................................................................................... 97 DAOFLUSHING ........................................................................................................................................................... 97 DAODEPENDENCIAS .............................................................................................................................................. 101 ADENTITYIMPL ....................................................................................................................................................... 102 ADRENDIMIENTO ................................................................................................................................................... 102 195 de 198 Framework Atlas Normativa ADEQUALSHASHCODE .......................................................................................................................................... 108 ADMAPEOTABLA .................................................................................................................................................... 109 ADIDENTIFICADOR ................................................................................................................................................ 109 ADRELACIONES....................................................................................................................................................... 110 ADDINAMICOS ......................................................................................................................................................... 110 ADLOBANOT ............................................................................................................................................................. 110 ADHIBERNATEDAOIMPL ...................................................................................................................................... 113 ADDAOANOTACION ............................................................................................................................................... 113 ADDAONOMENCLATURA ..................................................................................................................................... 114 ADDAOHIBERNATETEMPLATE .......................................................................................................................... 114 ADCATALOGOS ....................................................................................................................................................... 121 ADREMOTO ............................................................................................................................................................... 121 ADSQL ......................................................................................................................................................................... 122 ADSQLUSO ................................................................................................................................................................. 122 ADNAMEDPARAMETER ........................................................................................................................................ 123 DAOEXCEPCIONES ................................................................................................................................................. 124 ADTRANSACCION ................................................................................................................................................... 124 ADROLLBACK .......................................................................................................................................................... 125 ADSTOREDPROC ..................................................................................................................................................... 126 ADCACHE2NIVEL .................................................................................................................................................... 131 DAOCACHEDISTRIBUIDA ..................................................................................................................................... 132 ADRENDIMIENTO ................................................................................................................................................... 132 CONFENTORNO ....................................................................................................................................................... 134 CONFPARTICULAR ................................................................................................................................................. 134 CONFPARTICULARLIB .......................................................................................................................................... 135 CONFENTORNOLIB ................................................................................................................................................ 135 CONFNOMENCLATURA ........................................................................................................................................ 136 CONFSEG ................................................................................................................................................................... 136 SBAUTENAUTO ........................................................................................................................................................ 140 SBAUTOPERFILES ................................................................................................................................................... 140 SBENS .......................................................................................................................................................................... 142 SBTRAZAS.................................................................................................................................................................. 144 SBTRAZASSEG .......................................................................................................................................................... 145 SBAUDIT ..................................................................................................................................................................... 146 SIPLAN ........................................................................................................................................................................ 149 SICERT ........................................................................................................................................................................ 150 SIBI............................................................................................................................................................................... 152 INTWS ......................................................................................................................................................................... 153 INTNOMCLIENT....................................................................................................................................................... 153 SIBPM .......................................................................................................................................................................... 155 196 de 198 Framework Atlas Normativa SOLLIB ........................................................................................................................................................................ 155 SOLRPT ....................................................................................................................................................................... 156 SOLRPTCONEX ........................................................................................................................................................ 156 SOLRPTMODULO .................................................................................................................................................... 157 SOLRPTCONF ........................................................................................................................................................... 157 SOLCOMPOSITOR ................................................................................................................................................... 158 SOLEXCEL ................................................................................................................................................................. 160 SOLPDF ....................................................................................................................................................................... 161 SOLGRAFICOS .......................................................................................................................................................... 162 SOLMULTIMEDIA ................................................................................................................................................... 163 SOLACCESOLOCAL ................................................................................................................................................ 164 SOLXML ..................................................................................................................................................................... 166 SOLCORREO ............................................................................................................................................................. 168 WSSECURITY ............................................................................................................................................................ 174 VALEXCLUDE ........................................................................................................................................................... 176 CSPMD ........................................................................................................................................................................ 178 TESTINTEGRACION ............................................................................................................................................... 187 TESTACEPTACION .................................................................................................................................................. 187 TESTSERVICIOSWEB ............................................................................................................................................. 188 TESTRENDIMIENTO ............................................................................................................................................... 188 TESTAUTOMATIZACION ...................................................................................................................................... 189 TESTCOBERTURA ................................................................................................................................................... 189 TESTPLANPRUEBAS ............................................................................................................................................... 190 JAVADOC ................................................................................................................................................................... 191 ENTREGABUILD ...................................................................................................................................................... 193 ENTREGATARGET .................................................................................................................................................. 193 ENTREGALIB ............................................................................................................................................................ 193 197 de 198 Framework Atlas Normativa A1.2 BUENAS PRACTICAS JSFMANAGEDBEAN .................................................................................................................................................. 32 JSFGET.......................................................................................................................................................................... 32 JSFTAMANO ................................................................................................................................................................ 33 JSFEL ............................................................................................................................................................................. 33 JSFACCIONES ............................................................................................................................................................. 35 JSFMESSAGES ............................................................................................................................................................ 38 JSFACCESOMESSAGES ............................................................................................................................................ 41 JSFAJAXLIMITE......................................................................................................................................................... 51 JSFAYUDA.................................................................................................................................................................... 53 JSFMBUNICO .............................................................................................................................................................. 56 JSFSTOREERROR ...................................................................................................................................................... 59 JSFSAVESTATE .......................................................................................................................................................... 64 JSFATLASFACESUTILS ............................................................................................................................................ 70 SNFACADEWS ............................................................................................................................................................. 73 ADBASESERVICE ....................................................................................................................................................... 79 SNAGRUPACION ........................................................................................................................................................ 83 SNEXCCOMUNES ....................................................................................................................................................... 85 SNGENERICTRANSACTION .................................................................................................................................... 91 SNNOMFICHEROTEMPORAL ................................................................................................................................ 94 ADBASEDAO .............................................................................................................................................................. 117 ADHQL ........................................................................................................................................................................ 121 SOLCOMPOSITOR ................................................................................................................................................... 158 SOLGRAFICOSGRANDES ...................................................................................................................................... 162 VALFRECUENTE ...................................................................................................................................................... 175 CODFRECUENTE ..................................................................................................................................................... 178 GENCOD ..................................................................................................................................................................... 178 ENTREGAPARCIAL ................................................................................................................................................. 192 198 de 198