64
Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software Angel Luis Rubio García Facultad de Ciencias, Estudios Agroalimentarios e Informática Grado en Ingeniería Informática 2012-2013 Título Autor/es Director/es Facultad Titulación Departamento TRABAJO FIN DE GRADO Curso Académico

Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Javier Hernáez Hurtado

Estudio para la realización de una 'navaja suiza' para eldesarrollo de aplicaciones software

Angel Luis Rubio García

Facultad de Ciencias, Estudios Agroalimentarios e Informática

Grado en Ingeniería Informática

2012-2013

Título

Autor/es

Director/es

Facultad

Titulación

Departamento

TRABAJO FIN DE GRADO

Curso Académico

Page 2: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

© El autor© Universidad de La Rioja, Servicio de Publicaciones, 2013

publicaciones.unirioja.esE-mail: [email protected]

Estudio para la realización de una 'navaja suiza' para el desarrollo deaplicaciones software, trabajo fin de grado

de Javier Hernáez Hurtado, dirigido por Angel Luis Rubio García (publicado por la Universidad de La Rioja), se difunde bajo una Licencia

Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported. Permisos que vayan más allá de lo cubierto por esta licencia pueden solicitarse a los

titulares del copyright.

Page 3: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

TRABAJO FIN DE GRADO

Estudio para la realización de una “navaja suiza” para el desarrollo

de aplicaciones software

Javier Hernáez Hurtado

Tutor: Ángel Luis Rubio García

Universidad de La RiojaFacultad de Ciencias, Estudios Agroalimentarios e Informática

Logroño, junio de 2013

Page 4: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software
Page 5: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Resumen

En este trabajo se llevará a cabo el estudio de una serie de conceptos que debería-mos tener en cuenta siempre que desarrollemos. Algunos de ellos como, los siste-mas de control de versiones, registro de mensajes o internacionalización, son con-ceptos genéricos. Otros como, el mapeo relacional de objetos, sistemas de búsqueda o presentación web, están más orientados para aplicaciones específicas. Para cada uno de éstos, elegiremos las herramientas y librerías necesarias teniendo en cuenta la experiencia propia y su aceptación por parte de la comunidad de desarrolladores Java. Una vez elegidas todas las herramientas y librerías a utilizar, las organizare-mos y configuraremos. Con la ayuda de Maven generaremos una plantilla, con la que obtendremos un entorno de trabajo que, ayude y facilite en la construcción de nuestras aplicaciones.

Abstract

This work will study some concepts that we should always keep in mind when de-veloping applications. Some of them, such as version control systems, message log or internationalisation, are generic concepts. Other concepts are more specific for particular applications; for instance, object relational mapping systems, system search and web presentation. For each of them, we will choose the necessary tools and libraries considering our experience and its acceptance by the Java developers commnunity. Once that the tools and libraries have been chosen, we will organise and configure them. Thanks to Maven, we will generate a template to make the build of applications easier.

Page 6: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software
Page 7: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Índice

1. Introducción.........................................................................................11.1. Contexto.........................................................................................................11.2. Objetivos.........................................................................................................21.3. Planificación...................................................................................................5

1.3.1. Presentación............................................................................................51.3.2. Trabajo Fin de Grado..............................................................................6

2. Estudio.................................................................................................72.1. Control de Versiones.......................................................................................72.2. Sistema de registro de mensajes...................................................................102.3. Programación orientada a pruebas...............................................................122.4. Conexiones a la Base de Datos.....................................................................142.5. Mapeo Relacional de Objetos.......................................................................162.6. Validaciones..................................................................................................182.7. Caché de objetos...........................................................................................202.8. Motores de búsqueda....................................................................................242.9. Presentación Web.........................................................................................272.10. Internacionalización....................................................................................29

3. Integración y Construcción...............................................................313.1. Maven...........................................................................................................31

3.1.1. Ciclo de vida..........................................................................................333.1.2. Repositorio de Maven............................................................................343.1.3. Estructura de directorios.......................................................................353.1.4. POM (Project Object Model)...............................................................363.1.4.1. Información general del proyecto......................................................363.1.4.2. Opciones de construcción..................................................................373.1.4.3. Gestión de dependencias...................................................................39

3.1.5. Arquetipos.............................................................................................413.1.5.1. Construcción de un arquetipo...........................................................42

3.2. Spring Framework.........................................................................................433.3. Ficheros de configuración.............................................................................44

3.3.1. Registro de mensajes ............................................................................443.3.2. JPA e Hibernate ...................................................................................463.3.3. Pool de conexiones ...............................................................................463.3.4. Caché de objetos....................................................................................473.3.5. JSF (faces-config.xml y web.xml)..........................................................483.3.6. Internacionalización ..............................................................................483.3.7. Configuración de Spring........................................................................49

Page 8: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

4. Aplicación de prueba..........................................................................515. Conclusión..........................................................................................536. Bibliografía.........................................................................................55

Page 9: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Introducción 1

1.Introducción

1.1. ContextoBastantes veces nos hemos enfrentado en nuestra etapa académica o profesional al desarrollo de aplicaciones informáticas; en ocasiones desde su estado inicial de de-sarrollo y otras en su etapa de madurez.

Muchos conocemos las ventajas que nos aporta la separación de capas (persisten-cia, lógica de negocio y presentación), los patrones de diseño o disponer de un am-plio conocimiento de las diferentes librerías o componentes que se encuentran a nuestra disposición.

Una de las mayores dificultades reside en la variedad de soluciones que existen para un mismo problema; y en nuestra mano estará dar con la mejor.

Con el tiempo:

• aprendemos nuevas formas de hacer las cosas,

• tenemos en cuenta hechos que en el pasado pasábamos por alto,

• abordamos los problemas de forma distinta.

En muchas ocasiones tomamos decisiones poco acertadas, pero no debemos preocu-parnos ya que de todo se aprende. Nuestras decisiones mejorarán a medida que aprendamos de los errores cometidos en el pasado y de la experiencia adquirida a lo largo de los años.

Las aplicaciones informáticas evolucionan a lo largo de los años al igual que lo ha-cen las nuevas tecnologías; así que uno de nuestros principales objetivos consistirá en mejorar y hacer más fácil nuestro día a día.

Con frecuencia nos empeñamos en reinventar la rueda; otras, simplemente adopta-

Page 10: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

2 Contexto

mos malas decisiones y, a veces, la propia evolución mencionada con anterioridad, hacen necesario llevar a cabo un cambio. Tampoco hay que dejar de lado que la mayoría de proyectos son desarrollados por equipos de personas que cambian con el tiempo. Debido a ello, muchos diseños bien planteados terminan corrompiéndose y es necesario volver a organizar el código. Es inevitable tener que volver a diseñar algo previamente programado, aunque vaya en contra de todo lo que hayamos aprendido.

Por lo que a mí respecta, he tenido que realizar numerosos proyectos. En ocasiones, desarrollados desde su etapa inicial, pero en mayor medida relacionados con nuevas funcionalidades para un proyecto de gran envergadura, con un margen de maniobra limitado. Aunque se comienzan utilizando determinadas tecnologías, con el trans-curso del tiempo es necesario una adaptación.

Debemos pensar que no todo es blanco o negro y que, quizás, la solución más reco-mendable no sea la mejor para nuestro caso en concreto, sobre todo cuando nos en-frentamos al mantenimiento y creación de nuevas funcionalidades para una aplica-ción asentada.

Las aplicaciones realizadas durante mi etapa académica poco o nada tienen que ver con mi actual etapa profesional. A pesar de poseer un amplio conocimiento teórico, la verdad es que la puesta en práctica siempre es otra historia.

1.2. ObjetivosEn el mundo informático, al igual que en otros ámbitos, disponemos de numerosas alternativas para solucionar un problema. Debido a esto uno no sabe por dónde co-menzar o cómo organizarse, lo que termina siendo fruto de numerosas frustraciones y agobios.

A lo largo de la historia han surgido herramientas bajo un concepto similar. Por poner un ejemplo, la necesidad que los soldados tenían de portar utillajes para su día a día terminó dando lugar a lo que hoy conocemos como “navaja suiza”. Una herramienta en la que se agrupa en un mismo objeto: cuchillas, sacacorchos, des-tornillador, etc.

Según la definición de la wikipedia, “el término Navaja Suiza se usa habitual-mente como sinónimo de navaja de bolsillo, y también, algunas veces, se emplea para describir una herramienta, especialmente una herramienta de software, que consiste en una colección de programas destacados.”

Page 11: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Objetivos 3

Este Trabajo Fin de Grado (en adelante TFG) intentará aportar algo de luz a los problemas que se presentan en las distintas etapas del desarrollo de las aplicaciones informáticas.

La idea, como si de una “navaja suiza” se tratara, consistirá en proponer una es-tructura de proyecto y la utilización de diferentes herramientas, librerías o frameworks que faciliten el trabajo. Mi antiguo Proyecto Fin de Carrera titulado: “Herramienta para la Gestión de las Becas de Colaboración de la Universidad de la Rioja” servirá de ejemplo práctico.

Las decisiones adoptadas se verán condicionadas por aquello que esté más consoli-dado dentro de la comunidad de desarrolladores o por propia experiencia en la uti-lización de las mismas. En todo momento me centraré en el lenguaje de programa-ción Java, ya que además de ser libre, es en el que dispongo de mayor experiencia. Esto no supondrá ningún problema, ya que muchas de las elecciones propuestas pueden ser utilizadas en otros lenguajes o existen otras alternativas.

En numerosas ocasiones surgen problemas comunes entre proyectos muy dispares y podemos dispersarnos. Independientemente del tipo de proyecto que abordemos, conviene hacer las siguientes consideraciones:

• La necesidad de utilizar un sistema de control de versiones.

• Llevar a cabo pruebas unitarias. En este sentido, será conveniente referir-nos a una programación orientada a pruebas (TDD).

• Almacenar logs que permitirán conocer todo lo que sucede en nuestras apli-caciones. Esto nos facilitará observar el funcionamiento de nuestras aplica-ciones y detectar posibles errores.

Por otro lado, las aplicaciones que desarrollamos necesitan consultar, modificar o añadir información a una Base de Datos, siendo recomendable utilizar:

• Un pool de conexiones.

• Algún Mapeo relacional de objetos (ORM) que nos facilite el trabajo.

• Considerar que el acceso a una Base de Datos penaliza considerablemente el rendimiento de nuestras aplicaciones. Por lo tanto, sería recomendable utili-zar una caché de objetos para lograr un óptimo funcionamiento.

En la actualidad es difícil imaginarse una aplicación que no disponga de un sistema

Page 12: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

4 Objetivos

de búsquedas. Todos hemos apreciado dicha funcionalidad implementada por me-dio de infinidad de consultas SQL. Si pretendemos llevar a cabo búsquedas más so-fisticadas será necesaria la utilización de alguna librería, como puede ser lucene.

La utilización de un framework como Spring brinda a los desarrolladores cierta li-bertad, además de aportar soluciones bien documentadas y fáciles de utilizar para prácticas comunes. También dispone de una alta integración con diferentes ORM, entre otras utilidades.

Durante este proceso, observamos que se plantean numerosas dificultades, pero no debemos dejar de lado que pueden surgir otras no menos importantes:

• En la mayoría de las ocasiones hacemos uso de innumerables componentes, librerías y otras piezas de código elaboradas por un equipo de trabajo o ter-ceros. Generalmente son adheridas de forma manual ocasionando verdaderos quebraderos de cabeza cuando se efectúan cambios en las versiones de di-chos componentes, o en la forma en que éstos son utilizados por la aplica-ción a desarrollar.

• La estructura de directorios que debemos tener en cuenta para almacenar las fuentes, imágenes, ficheros de configuración o librerías.

• La frecuencia para llevar a cabo compilaciones de nuestros proyectos, gene-rar documentación, superar los casos de prueba, etc.

Con el fin de facilitar esta labor y otras muchas que iremos viendo a lo largo del TFG, me apoyaré en el uso de una herramienta de administración de proyectos Java denominada MAVEN.

La finalidad consiste en proponer una situación, lo más ideal posible, además de aconsejar y tener en cuenta qué deberíamos utilizar a la hora de desarrollar una aplicación web. Por otra parte, habrá que aportar soluciones a los problemas que surgen a lo largo del ciclo de vida de nuestras aplicaciones.

Una vez alcanzado el objetivo, se habrá conseguido un proceso unificado para cons-truir un proyecto, probarlo, instalarlo y realizar el despliegue. De esta forma aho-rraremos tiempo, pudiendo destinarlo a actividades más propias de la programa-ción.

Page 13: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Planificación 5

1.3. PlanificaciónConocido el tiempo disponible para la realización del TFG y el método de evalua-ción, he considerado conveniente realizar la siguiente planificación:

• Trabajo Fin de Grado: 240 horas.

• Presentación: 60 horas.

Total: 300 horas.

1.3.1. Presentación• Diapositivas: 20 horas.

• Notas: 25 horas.

• Ensayo: 15 horas.

Total: 60 horas.

Dibujo 2: Planificación de la presentación

Diapositivas

Notas

Ensayo

Dibujo 1: Planificación general

Presentación

Trabajo Fin de Grado

Page 14: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

6 Trabajo Fin de Grado

1.3.2. Trabajo Fin de Grado• Introducción: 7 horas.

• Estudio: 91 horas.

• Sistemas de control de versiones: 8 horas.

• Sistemas de registro de mensajes: 8 horas.

• Pruebas unitarias: 10 horas.

• Conexiones a la base de datos: 5 horas.

• Mapeo relacional de objetos (ORM): 12 horas.

• Validaciones: 8 horas.

• Caché de objetos: 12 horas.

• Motores de búsqueda: 12 horas.

• Presentación web: 12 horas.

• Internacionalización: 4 horas.

• Integración y construcción: 22 horas.

• Aplicación de prueba: 20 horas.

• Redacción de memoria: 95 horas.

Total: 240 horas.

Dibujo 3: Planificación del Trabajo Fin de Grado

Introducción

Reuniones

Estudio

Integración y contrucción

Aplicación de prueba

Redacción de la memoria

Page 15: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Estudio 7

2.EstudioEn este capítulo haré hincapié en alguna de las partes más importantes de las que puede constar un proyecto informático (desde el acceso a la información hasta su presentación). Intentaré barajar diferentes alternativas que puedan existir en cada uno de los campos a tratar, analizándolas desde mi experiencia personal y de las conclusiones obtenidas tras el estudio. Los tres primeros apartados harán referencia a conceptos como el control de versiones, sistemas de registro de mensajes y pro-gramación orientada a pruebas que todo el mundo deberíamos conocer y que debie-ran ser de obligado cumplimiento independientemente del proyecto que abordemos. El resto de apartados, estarán más encaminados al desarrollo de aplicaciones más específicas, aunque no por ello menos importantes.

2.1. Control de VersionesEs inevitable que los desarrollos que llevamos a cabo experimenten cambios. A me-dida que transcurre el tiempo surgen nuevos ficheros, modificaciones o, incluso, eli-minamos ficheros existentes. En ocasiones se detectan problemas y es necesario re-cuperar versiones especificas de nuestros ficheros a un estado en el que funcionaban correctamente. Llevar a cabo todas y cada una de estas tareas de forma precisa y eficiente, pero sin la ayuda de ninguna herramienta, sería complicado. Además, no sería la mejor forma, puesto que disponemos de sistemas de control de versiones que facilitan todo el trabajo.

Estas herramientas son imprescindibles en proyectos de cierta envergadura que se desarrollan en un entorno de colaboración, pero también puede ser de gran ayuda para entornos en los que exista un único desarrollador. Además nos brindarán la posibilidad de:

• guardar/recuperar diferentes versiones de nuestros ficheros,

• realizar comparaciones entre distintas versiones,

Page 16: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

8 Control de Versiones

• identificar los cambios realizados y quien los ha llevado a cabo,

• guardar comentarios e información al efectuar los cambios.

Atendiendo a su arquitectura podemos clasificarlos de la siguiente forma:

• Centralizados: Existe un repositorio central donde se almacenan las dis-tintas versiones de los ficheros. Los usuarios trabajan sobre una copia local, obtenida de la exportación, donde pueden realizar los cambios pertinentes. Una vez que queden reflejados dichos cambios en el repositorio se encuen-tran a disposición de todos los usuarios. Como puede observarse, es neces-ario pasar a través del repositorio central para realizar la sincronización. Los sistemas de control de versiones centralizados más populares son: CVS y Subversion.

• Distribuidos: En este caso no existe un repositorio central, ya que todos los usuarios disponen de su propia copia con las distintas versiones e históri-co. Todos los cambios se llevan a cabo en el repositorio local. Normalmente existe un repositorio que se considera oficial, del que se obtiene la primera copia de los proyectos, y donde los desarrolladores añaden las versiones fina-les. Los sistemas de control de versiones distribuidos más destacados son: Bazaar, Mercurial y Git.

Existen numerosas comparativas del uso de los distintos sistemas de control de ver-siones por parte de la comunidad de desarrolladores. Una fuente de información importante es la aplicación popularity contest(popcorn), instalada por los usuarios de Debian, y que hace una comparativa de la popularidad de estos sistemas entre sus usuarios. También es interesante el uso de Google Trends, que permite conocer la tendencia de las búsquedas llevadas a cabo por los usuarios.

Dibujo 4: Comparativa de sistemas de control de versión

Page 17: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Control de Versiones 9

Todas ellas tienen algo en común, y es la clara tendencia ascendente que ha tenido Git en los últimos años. Actualmente es uno de los más utilizados y está presente en proyectos de gran relevancia como puede ser el desarrollo del núcleo de Linux. En los noventa el más utilizado fue CVS, para ser posteriormente desbancado por Subversion, su claro sucesor.

En el momento que comencé mi experiencia laboral y tuve que utilizar por primera vez un sistema de control de versiones, entendí su importancia y necesidad. Por el momento sólo he trabajado con sistemas de control de versiones centralizados. En un principio utilizando CVS, con el cual no he tenido muy buenas experiencias.

En los equipos de desarrollo es común que se trabaje con distintos sistemas opera-tivos. Lo que aparentemente puede no parecer un problema, con CVS lo era. La utilización de diferente codificación de caracteres generaba incompatibilidades en-tre los miembros del equipo a la hora de recuperar la información del CVS.

Normalmente la modificación del nombre de un fichero no resulta una tarea trivial. Para llevarla a cabo, deberemos eliminar y crear un nuevo fichero con el mismo contenido y el nombre deseado.

En ocasiones es necesario trabajar en ramas alternativas del proyecto, puesto que no interesa que los cambios se vean reflejados en la rama principal hasta que todo esté finalizado, probado y funcionando correctamente. La experiencia con CVS no fue plato de buen gusto e incluso fue necesario más trabajo del necesario para vol-ver a tener el proyecto estable.

Debido a estos problemas, decidimos migrar a Subversion, solucionando total o parcialmente alguno de los problemas enumerados con anterioridad y aportando al-gunas de las ventajas que señalo a continuación:

• Las versiones se realizan a nivel de proyecto y no de fichero, permitiendo re-cuperar el estado del repositorio en un instante determinado.

• Su uso resulta más eficiente puesto que sólo se envían las diferencias mien-tras que en CVS se enviaban los ficheros al completo.

• Maneja más eficientemente el almacenamiento de ficheros binarios.

Aun así, una de las mayores carencias que tienen este tipo de sistemas de control de versiones, es la posible falta de conectividad con el repositorio central. En oca-siones pasamos horas sin poder sincronizar cambios, algo que resulta menos impro-bable en los sistemas de carácter distribuido.

Page 18: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

10 Control de Versiones

Cuando vuelvo la vista atrás y pienso en mi proyecto fin de carrera me resulta complicado imaginar cómo pude no utilizar ningún sistema de control de versiones.

No necesariamente deben utilizarse en un contexto relacionado con el desarrollo de aplicaciones, sino que también pueden ayudarnos a mantener diferentes versiones de archivos de texto, imagen, vídeo o música en los que estemos trabajando. Sin ir más lejos, en mi caso lo he llegado a utilizar en alguna ocasión para guardar dife-rentes versiones de canciones que he compuesto y grabado.

2.2. Sistema de registro de mensajesTodo el mundo está familiarizado con los cuadernos de bitácora, y el simple he-cho de nombrarlos hace que todos tengamos grabada la misma imagen en nuestra mente. Es inevitable no pensar en los libros que se encontraban a disposición de los capitanes de los barcos. En ellos se relatan los acontecimientos más relevantes du-rante sus largos viajes; acontecimientos relatados en orden cronológico, facilitando así una posterior consulta.

El uso de los cuadernos de bitácora también se extiende a otros ámbitos. Los cien-tíficos, sin ir más lejos, suelen escribir diarios durante sus investigaciones para ex-plicar el proceso y compartir sus experiencias con otros especialistas.

El registro de mensajes o registro de logs (término con el que estaremos más fami-liarizados) persigue exactamente el mismo fin. Es importante conocer las tareas que nuestras aplicaciones realizan en cada momento, y es necesario reflejar con exactitud el “qué” y el “cuándo” ocurren las cosas. Además permiten detectar con mayor facilidad cualquier error que se produzca durante la ejecución de nuestras aplicaciones.

Con el fin de facilitar estas labores, es recomendable mostrar los mensajes de forma clara, breve y concisa. Estructurar correctamente estos mensajes, independiente-mente de dónde se almacenen, también facilitará nuestro trabajo.

Todos, o casi todos, hemos generado alguna vez líneas de código para mostrar mensajes que nos sirvan de guía. Durante el desarrollo de mi proyecto fin de carre-ra se convirtió en una práctica habitual. Aun así, resultan usos poco recomendables que empañan el código de nuestras aplicaciones.

A pesar de existir numerosas herramientas que permiten el registro de mensajes (Java Util Logging-JUL, log4j, LogBack...), no comencé a utilizarlos, por desconoci-

Page 19: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Sistema de registro de mensajes 11

miento, hasta que comencé a trabajar. Desde entonces, es algo que considero im-prescindible u obligatorio en cualquier proyecto informático.

Gracias a la utilización de estas herramientas podremos:

• Almacenar los mensajes en ficheros de texto, servidor remoto, dirección de correo electrónico e, incluso, en una base de datos.

• Dotar de formato a nuestros mensajes.

• Añadir información extra a nuestros mensajes, como la fecha, clase que lo generó, etc.

• Definir diferentes niveles de detalle para los mensajes que queremos repor-tar, facilitando la depuración, la solución de problemas y las auditorías. És-tos, pueden variar dependiendo de la herramienta que utilicemos. En el caso de log4j tenemos disponibles los siguientes niveles: debug, info, warn, error, fatal, off y all.

Aunque Java introdujo su propio sistema de logs desde la versión 1.4, log4j se creó años antes estableciéndose como una de los sistemas de logs más utilizadas entre la comunidad de desarrolladores. Actualmente, en mi trabajo, utilizamos dicha libre-ría, y a día de hoy, continúa siendo una de las más utilizadas en numerosos proyec-tos y aplicaciones.

Sin embargo, desde la versión 1.2, log4j no dispone de un mantenimiento activo. Al parecer, se están haciendo esfuerzos para una nueva versión que implementará las mejoras disponibles en LogBack. Este proyecto, creado por el mismo desarrollador de log4j, surgió con idea de mejorar lo existente.

Como vemos, existen multitud de librerías para el almacenamiento de mensajes y por ello surgió commons-logging. La idea era generalizar el uso del sistema de logs y crear un API común capaz de manejarlos. Dicho de otra manera, un API que en-volvería los sistemas de logs que realmente se utilizasen. Gracias a esto, es posible integrar proyectos que utilizan diferentes sistemas de registro de logs. Actualmente commons-logging, aunque se encuentra estable, desde hace tiempo no dispone de actualizaciones.

Slf4j se creó como una alternativa a commons-loggin, y a diferencia de éste, no se trata de una implementación. Solamente es una definición de interfaces que reduce el acoplamiento entre una aplicación y un determinado sistema registro de logs.

Page 20: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

12 Sistema de registro de mensajes

Se trata de una dependencia más limpia y eficiente en tiempo de ejecución, ya que utiliza enlaces en tiempo de compilación en vez de en tiempo de ejecución. Esto significa que, en caso de querer cambiar la implementación del sistema de registro, no puedes hacerlo en tiempo de ejecución, sino que previamente debes configurar cual vas a utilizar.

Además es posible enlazar con los sistemas de registro más comunes, tales como: commons-logging, log4j o logback. También incluye “puentes” entre los sistemas de registro de mensajes y él mismo. De esta forma, es posible utilizar Slf4J con Spring, aunque éste use por defecto commons-logging, simplemente utilizando el “puente” adecuado. Esto traducirá las llamadas de registro de mensajes hechas con Spring a llamadas al API de Slf4j, por lo que si diferentes librerías de tu aplicación usan dicho API, dispondrás de un lugar centralizado donde configurar y adminis-trar el registro de logs.

2.3. Programación orientada a pruebasEs prácticamente imposible generar código que sea perfecto y no tenga errores. Todo programador que se precie ha tenido que lidiar alguna vez con fallos, y por ello es necesario llevar a cabo pruebas del código generado. Para la elaboración de estos test generalmente se utilizan las denominadas pruebas unitarias, cuya fina-lidad consiste en probar de forma correcta y formal el funcionamiento de nuestro código. Cuando hablamos de correcto funcionamiento, nos referimos a que nuestras aplicaciones ejecuten lo que establecen sus requisitos y que no hacen lo que no de-berían de hacer. Las pruebas unitarias que realicemos deberían aportarnos, entre otras cosas, lo que enumeramos a continuación:

• Ejecutarse de forma automática.

• Utilizarlas las veces que sea necesario, independientemente de los cambios que sufra nuestro código.

• Abordar el mayor número de casos posibles, aunque resulte una tarea difícil, para que existan menor número de errores.

• Que no resulte excesivamente complicada su implementación.

La utilización de éstas nos proporciona:

• Una mejora en la calidad de nuestro código, puesto que será la mejor forma de detectar y acotar los errores en fases tempranas del desarrollo.

Page 21: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Programación orientada a pruebas 13

• Una definición de los requisitos y responsabilidades de las que dispondrán nuestras clases.

• Modificaciones en nuestro código en una etapa temprana del desarrollo, ha-ciendo que el impacto de los cambios en nuestro diseño sean menores.

• Facilidad y simplicidad en la integración, ya que con total seguridad, llega-dos a este punto, tendremos garantizado el correcto funcionamiento de nues-tro código.

• Conocimiento sistemático del correcto funcionamiento de nuestro código aunque hayamos realizado modificaciones.

Nos resulta imposible imaginar a una persona invidente que pueda desenvolverse en su vida cotidiana sin utilizar un bastón o sin ir acompañado por su perro lazari-llo. Las pruebas unitarias son igual de necesarias e importantes para un programa-dor, ya que sin ellas estarían perdidos.

No podemos confiar en una librería, herramienta o aplicación sobre la que no se han desarrollado pruebas. Actualmente cualquier proyecto que descargamos de la red las incorpora permitiendo su ejecución y comprobación. Además, de cara al fu-turo y más en un entorno donde trabaja más de un desarrollador, hace que al mo-dificar y añadir nuevas funcionalidades resulte mucho más fácil, puesto que de un simple vistazo podemos comprobar si todo continúa funcionando correctamente.

La programación orientada a pruebas ha tenido gran difusión en los últimos años. Hasta ahora, seguramente entendíamos que las pruebas las realizábamos tras im-plementar una determinada funcionalidad. En este caso, el concepto es distinto, ya que propone escribir un código de respuesta a una prueba fallida; es decir, progra-mamos el caso de prueba donde se especifica cómo debería comportarse una deter-minada funcionalidad y, posteriormente, se implementa la funcionalidad conforme a lo establecido en su caso de prueba. De esta forma se garantiza que nuestras apli-caciones cumplen y se ciñen a los requisitos establecidos, ya que muchas veces ten-demos a programar más de lo necesario.

Uno de los puntos fuertes de mi proyecto fin de carrera fue la utilización de JUnit para la elaboración de las pruebas unitarias. A pesar de los años, continúa siendo uno de los frameworks más utilizados para este propósito. Han evolucionado nota-blemente desde entonces, y se encuentran disponibles para un sinfín de lenguajes de programación. Tampoco debemos perder de vista TestNG, que se trata de un framework basado en JUnit y algo más joven, pero que tiene una muy buena carta

Page 22: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

14 Programación orientada a pruebas

de presentación.

Como vemos, una comprobación formal y lo más exhaustiva posible de nuestro có-digo es de vital importancia, pero la realidad es bien distinta. En mi caso y en el de otros muchos compañeros que trabajan en campos similares, se trata de una fase que, desgraciadamente, termina pasándose por alto. En ocasiones, debido a las presiones de tiempo, la curva de aprendizaje del equipo de desarrollo o el propio estado del código de las aplicaciones, lo hace complicado. Aunque se trate de razo-nes totalmente válidas, no deben utilizarse como justificación. Evitarlo no hará que nuestros proyectos mejoren, sino todo lo contrario.

2.4. Conexiones a la Base de DatosUno de los principales “cuellos de botella” de las aplicaciones suele ser el acceso a la base de datos. Iniciar una conexión y mantenerla en el tiempo, es una tarea que consume recursos. Debido a ello, la manera más óptima de gestionar las cone-xiones es utilizar un pool de conexiones, y más cuando nos encontramos ante apli-caciones donde acceden numerosos usuarios de forma concurrente.

Un pool de conexiones está formado por un conjunto limitado de conexiones que se encuentran a nuestra disposición y pueden utilizarse en cualquier momento. No es necesario abrir una conexión cada vez que lo necesitemos, ya que éstas estarán dis-ponibles para su uso. Los beneficios que nos aportan son significativos y se encuen-tran relacionados con el rendimiento, concurrencia y escalabilidad de nuestras apli-caciones. Además permiten configurar parámetros como pueden ser: el numero má-ximo y mínimo de conexiones que se van a manejar, validación de las conexiones antes de prestarlas, el número de conexiones a crear cuando no se encuentran dis-ponibles, el número de segundos que una conexión puede estar en el pool sin ser utilizada antes de descartarse o eliminarse, etc.

Buscando información para que disipe dudas sobre qué proveedor de conexión es más recomendable utilizar, encontraremos las siguientes alternativas: DBCP, c3p0, Proxool y BoneCP.

Utilizando GoogleTrends, tal y como se hizo en la parte de sistemas de de control de versiones, podemos hacernos una idea de cual de ellos es el que más interés des-pierta entre la comunidad de usuarios. Hasta el año 2007 tanto DBCP como c3p0 destacaban sobre el resto de sus competidores, teniendo una ligera ventaja este pri-mero. Actualmente esta tendencia ha cambiado, pero no debemos ceñirnos exclusi-vamente en nuestra decisión a este aspecto.

Page 23: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Conexiones a la Base de Datos 15

Algo que no debemos dejar de lado, ya que es una de las circunstancias que más debemos tener en consideración, es la actividad que estos proyectos tienen (fre-cuencia con la que sacan nuevas versiones, mejoras, corrección de errores, etc). En este aspecto, c3p0 toma una clara ventaja respecto al resto. La mayoría de ellos, a excepción del pool de conexiones antes enumerado, han quedado obsoletos, como podemos ver a continuación:

Nombre de pool Fecha de la última versión

C3p0 2013-02-09

BoneCP 2011-04-05

DBCP 2010-11-25

Proxool 2008-08-23

Tabla 1: Versiones de pool de conexiones

Como hemos visto anteriormente, en el desarrollo de mi proyecto fin de carrera no fue una buena práctica no utilizar un sistema de logs ni un control de versiones, aunque tengo que lanzar una lanza a favor del acierto que supuso el desarrollo de unas pruebas unitarias y la utilización de un pool de conexiones. Por aquel enton-ces me decanté por DBCP pero observando la evolución y el cambio que se ha pro-ducido en éste campo actualmente sería más acertado decantarse por c3p0. Algo si-milar sucedió no hace mucho en mi trabajo migrando desde nuestro antiguo y des-fasado proveedor de conexiones a c3p0.

Dibujo 5: Comparativa entre diferentes pool de conexiones

Page 24: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

16 Conexiones a la Base de Datos

El hecho de cambiar no significa que se adoptara una mala decisión. Una mala ac-tuación sería no adaptarse a los cambios que se producen. Debemos estar en conti-nuo proceso de aprendizaje y estudio para evitar quedarnos desfasados tecnológica-mente hablando.

2.5. Mapeo Relacional de ObjetosEn el apartado anterior nos referíamos a la importancia y alternativas disponibles a la hora de conectarnos a una Base de Datos. Una vez hecho esto, debemos ser ca-paces de recuperar, actualizar y eliminar la información que ésta alberga; aunque, como viene siendo habitual, existe una gran variedad de alternativas para llevar a cabo todas estas tareas.

Seguramente todos estamos familiarizados con Java Database Connectivity o lo que comúnmente denominamos como JDBC. Este API nos permite ejecutar operacio-nes sobre una base de datos mediante un lenguaje de consulta estructurado (SQL). En un principio podemos pensar que con la ayuda de JDBC tenemos cubiertos to-dos los problemas que puedan surgir, pero la realidad es que cuando trabajas con él en proyectos de gran tamaño, comienzan a surgir los problemas.

Cada entidad disponible en nuestra aplicación es lógico que disponga de las opera-ciones más comunes que deberemos realizar (CRUD). Cada vez que surge una enti-dad deberíamos escribir, como mínimo, las consultas correspondientes para su con-sulta, inserción, eliminación y modificación. A simple vista, aunque repetitivas, pa-recen tareas relativamente fáciles, que pueden complicarse a medida que los atribu-tos y relaciones aumentan.

Llegados a este punto llega el momento de pensar en los problemas con los que po-demos encontrarnos y sus posibles consecuencias. Cuando deseemos obtener una entidad, deberemos pensar en sus relaciones. No hay que pasar por alto la posibili-dad de que se establezcan relaciones recursivas o de encontrarnos ante un árbol de relaciones de gran tamaño. Nuestra objetivo será implementar y solucionar estos problemas que, no por ello, resultarán sencillos.

Existen otros muchos problemas, como los que pueden surgir a raíz de las actuali-zaciones. Lo lógico sería controlar los campos que han cambiado para modificar so-lamente esos campos. Hay que tener en cuenta que una entidad también está com-puesta por relaciones y que éstas, a su vez, pueden cambiar.

Page 25: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Mapeo Relacional de Objetos 17

Imaginemos por un momento que no realizásemos dicho control; seguramente esta-ríamos modificando tablas en las que no se ha realizado ningún cambio, mermando la eficiencia y funcionalidad de nuestras aplicaciones.

A modo de ejemplo, sólo hemos destacado alguno de los problemas que podrían plantearse; pero, ni de lejos, serían los únicos. De todas las alternativas, segura-mente el uso de JDBC fuese la solución de más bajo nivel. Esto significa que cual-quier problema que se nos plantee, como hemos visto, podrá solucionarse a cambio de realizar un trabajo previo.

Conocer o darse cuenta de los problemas que puedan surgir, es positivo; y provoca que busquemos otras alternativas. Como sabemos, las bases de datos relacionales almacenan la información mediante tablas, filas y columnas, así que para almace-nar o recuperar un objeto hay que realizar una correlación entre el sistema orienta-do a objetos y el sistema relacional de nuestra base de datos.

JPA (API de persistencia en Java) es una especificación estándar (JSR 220) que consiste en una abstracción sobre JDBC que permite realizar de forma sencilla la conversión entre nuestros objetos y las tablas de una base de datos. Esta conver-sión se denomina mapeo relacional de objetos (ORM). Por otro lado, JPA nos per-mite crear de forma transparente objetos, a partir de las tablas de una base de da-tos. Además establece una interfaz común implementada por un proveedor de per-sistencia que realizará el trabajo; eso sí, delegando siempre en JPA.

A nuestra disposición tenemos gran variedad de proveedores que permiten manejar la persistencia de nuestros objetos de una manera muy sencilla, a la vez de poten-te: Hibernate, TopLink, EclipseLink (basado en Toplink), OpenJPA, etc, y como suele ser habitual, existen diferentes comparativas donde se muestran las fortalezas y debilidades de cada uno de ellos. Hoy por hoy, me atrevería a decir que Hiberna-te es la alternativa más conocida y utilizada por la comunidad de desarrolladores. Nos encontramos ante un proyecto consolidado, completamente libre y gratuito, que dispone de toda la documentación que podamos imaginar.

Si durante el desarrollo de mi proyecto fin de carrera hubiese conocido la existencia de los ORM, a pesar de la inevitable curva de aprendizaje que estos suponen, ten-go la total seguridad de que hubiese escogido este camino. Esto me hubiese aporta-do numerosas ventajas como:

• Un desarrollo más fluido, y...

• Una abstracción con el motor de la base de datos.

Page 26: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

18 Mapeo Relacional de Objetos

Además el uso de JDBC hizo que tuviera presente los problemas con las modifica-ciones. Tuve que ingeniármelas como pude para diseñar e implementar una fórmula que me permitiese identificar los atributos que habían cambiado en una clase para generar las consultas SQL en base a ello. Está claro que iba en ello el buen camino, puesto que los ORM proponen soluciones a problemas de esta índole.

En otras ocasiones, a pesar de resultar una magnífica solución a todos nuestros problemas, es muy complicada su implantación. Actualmente, en el lugar donde trabajo, estamos barajando la posibilidad de adaptar una de las aplicaciones que desarrollamos con el fin de utilizar un ORM, pero no va a resultar una tarea nada fácil. Se trata de una aplicación web cuyo contenido se introduce mediante una aplicación de escritorio que lleva tiempo sin mantenimiento. Esto ha provocado que nos encontremos muy limitados a la hora de realizar cambios en la base de datos, ya que al introducir información, dejaría de funcionar. Con el tiempo esto ha resul-tado un lastre del que debemos deshacernos de manera inmediata. El hecho de es-tar utilizando JDBC hace que surjan enormes problemas, como hemos comentado anteriormente. La solución que más fuerza cobra es la utilización de un ORM, como puede ser Hibernate; aunque eso sí, teniendo en cuenta que la base de datos deberá modificarse si es necesario. La necesidad de continuar desarrollando nuevas funcionalidades, el tiempo y los medios con los que contamos dificultan que alcan-cemos nuestro objetivo, al menos a medio plazo.

A modo de conclusión, pienso que no hay que reinventar la rueda, y más cuando ya existen soluciones a nuestros problemas que han sido desarrollados por un grupo de personas expertas en dicho campo. Siempre es mejor aportar el poco conocimiento del que dispongamos con el fin de mejorar dichos proyectos.

Además, el uso de estándares maximiza las probabilidades de que, entorno al framework utilizado, exista una comunidad que vaya creciendo, mejorando, y no se vuelva obsoleto. Esto nos dará cierta garantía para migrar en el caso de que lo ne-cesitemos.

2.6. ValidacionesIndependientemente del tipo de aplicaciones que desarrollemos, la construcción de validaciones es el pan nuestro de cada día. Debemos tener en cuenta que, a lo largo del desarrollo de nuestras aplicaciones, es inevitable no llevar a cabo validaciones de los datos.

En ocasiones estas validaciones se encuentran desperdigadas en diferentes partes de

Page 27: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Validaciones 19

nuestra aplicación, provocando duplicidades en nuestro código y generando en oca-siones graves consecuencias. Además terminamos perdiendo el tiempo realizando más trabajo del necesario.

Supongamos por un momento que necesitamos validar formularios de una aplica-ción web. Deberíamos comprobar que los datos introducidos son correctos y, en caso contrario, notificar qué campos son incorrectos para facilitar la corrección a los usuarios. Como tónica general, las aplicaciones suelen desarrollarse por un gru-po de programadores. Podría darse el caso de que uno que está programando la ló-gica de negocio presuponga que las validaciones se realizarán en capa de presenta-ción. En ese caso, podríamos provocar que nuestras aplicaciones no fuesen robus-tas, ya que los datos ingresados serían incorrectos. Por lo tanto, lo lógico sería vali-dar que la información es correcta. Esta misma situación puede darse en cualquier parte de nuestra aplicación, lo que provoca:

• Sistemas propensos a errores.

• Generación de código duplicado, que en teoría debería tener la misma fun-cionalidad. Todos sabemos que con el paso del tiempo, las aplicaciones expe-rimentan cambios y es difícil cumplir esta premisa.

• Dificultad de mantenimiento.

Con el fin de evitar estas situaciones, los desarrolladores suelen empaquetar estas lógicas de validación directamente en el modelo de datos. Al fin y al cabo, no deja de ser información propia de los objetos.

Durante años se han utilizado inimaginables técnicas para llevar a cabo validacio-nes. Sin embargo, desde que disponemos de un estándar para la validación en Java, denominado Bean Validation (JSR-303), se ha creado un marco común de trabajo. Además esta especificación nos proporciona:

• Una forma clara para definir y declarar restricciones en el modelo de datos.

• Una validación de los objetos en tiempo de ejecución.

Las diferentes capas de las que constan nuestras aplicaciones (presentación, lógica de negocio, persistencia) pueden delegar las validaciones en JSR-303. De esta for-ma, podremos reutilizar las restricciones declaradas en el modelo. El componente JPA, del que ya hemos hablado con anterioridad, integra Bean Validation, lo que nos facilitará enormemente las cosas.

Page 28: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

20 Validaciones

Las restricciones se definen mediante anotaciones, incluyéndose algunas de las utili-zadas con mayor frecuencia, como pueden ser: NotNull, Max, Min, Size, etc. En caso de necesitar otras validaciones podemos utilizar Hibernate Validator o Apache BeanValidation(Bval), que se tratan de implementaciones de referencia de la JSR-303. No obstante, no debemos preocuparnos ya que podemos crear sin ningún problema y de forma sencilla nuestras propias anotaciones de validación para JSR-303.

Muchos de los problemas enumerados anteriormente los he vivido en primera per-sona en el ámbito laboral. Cuando trabajas en un proyecto con un grupo de desa-rrolladores, es inevitable que se realicen validaciones en diferentes partes del códi-go. Por ello es imprescindible marcar unas pautas de trabajo que se sigan al pie de la letra, y que nos permitan una mayor eficiencia en el desempeño de nuestras la-bores.

A pesar de que estos problemas no sucedían en mi proyecto fin de carrera, lo cierto es que no se utilizó una implementación del estándar JSR-303. La utilización de li-brerías, como puede ser commons-validator, facilitan enormemente nuestro trabajo, pero no olvidemos que no se trata de una implementación de JSR-303.

2.7. Caché de objetosEl rendimiento es algo que siempre debemos tener en cuenta a la hora de desarro-llar nuestras aplicaciones. Cuando comenzamos a desarrollar nuestras primeras aplicaciones, es un factor que no solemos tener en cuenta. Seguramente esto es de-bido a que la mayoría de las aplicaciones desarrolladas no terminan implantándose, pero cuando eso ocurre, o bien nos adentramos al mundo laboral, comenzamos a considerarlo como un factor clave.

Una buena aplicación puede ser lastrada por un nefasto rendimiento. Como suele decirse, la unión hace la fuerza; y es por ello que, uno de los objetivos clave para mejorar el rendimiento, no radica exclusivamente en la utilización de un pool de conexiones, en la mejora de consultas e índices de nuestra base de datos o en la configuración de un ORM. También es necesario combinar todo esto con la utiliza-ción de una caché.

Existen muchos elementos proclives a cachearse: objetos, información, conexiones de la base de datos, database statemens, meta-datos o relaciones; pero normalmen-te nos referimos a los objetos o su información.

Page 29: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Caché de objetos 21

Supongamos que en nuestro sistema existe la entidad País, en la que se indica su nombre y coordenadas geográficas (latitud y longitud). Estos valores los ingresare-mos a la hora de dar de alta a los países en nuestro sistema y suponemos que per-manecen inmutables. Debido a esto podemos plantearnos la siguiente pregunta: ¿Vamos a tener que consultar la base de datos cada vez que necesitemos un país si su información no cambia?. Lo más lógico sería cargar dicha información de forma única en memoria y acceder a ella cuando lo necesitemos. El uso de una caché faci-litará dichas labores.

La caché es un mecanismo que nos permite almacenar nuestras estructuras de ob-jetos en memoria, reduciendo el tráfico con la base de datos, disminuyendo el acce-so a los datos y logrando una mejoría en el tiempo de respuesta. De esta forma, cada vez que necesitemos obtener un objeto al que se accede con determina fre-cuencia, podremos prescindir del acceso a la base de datos y solicitarlo directamen-te a la caché.

El proceso habitual con el que trabaja una caché es el siguiente:

1. El usuario lleva a cabo una operación que provoca una consulta.

2. Se comprueba que los objetos se encuentran en la caché.

3. Si los encuentra, los devuelve. Si no los encuentra, accede a la base de datos para obtenerlos y los registra en la caché para futuros accesos.

Además todos los usuarios comparten la información existente en la caché. Esto in-cremente más el rendimiento si cabe, puesto que los usuarios podrán aprovecharse de los objetos cargados por otros usuarios.

Como viene siendo habitual, no es oro todo lo que reluce. Existen una serie de pro-blemas derivados de la concurrencia de nuestras aplicaciones, que pueden llegar a conseguir el resultado contrario al esperado, mermando el rendimiento de nuestras aplicaciones.

Uno de los problemas más frecuentes suele ser la modificación concurrente de los datos, provocando inconsistencias en los objetos que se manejan. Podría darse el caso de estar trabajando con versiones distintas de un mismo objeto. A simple vis-ta, se podría realizar un chequeo cada cierto tiempo, comprobando el estado de los objetos que en ella se encuentran, con el fin de sincronizarlos. Ligado a esto, surge el concepto de invalidar objetos de caché, que nos permite de forma explícita o me-diante una configuración de tiempo garantizar que los objetos se sincronicen.

Page 30: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

22 Caché de objetos

Independientemente de esto, lo que está claro es que necesitamos algún mecanismo que solucione dichos problemas.

En ocasiones, cuando el número de usuarios es elevado, resultará interesante utili-zar una arquitectura distribuida. Cuando un usuario solicita un objeto a la caché, ésta, además de comprobar si existe el objeto en su estructura interna, necesita tiempo para sincronizar las operaciones que se han llevado a cabo en los diferentes nodos. Existen muchas formas de implementar un sistema de caché distribuido:

• Replicar la caché en cada nodo y asumir la sincronización que se llevará a cabo.

• Tener la caché repartida entre los distintos nodos, asumiendo el coste de so-licitar los objetos.

• Implementar diferentes cachés que se sincronicen con una común cada cierto tiempo.

Sea cual sea nuestra elección, deberemos asumir una serie de costes derivados a ellos.

Siempre que se habla de cachés, vemos referencias a diferentes niveles. Aprovechan-do que ya se ha hablado en anteriores apartados sobre JPA 2.0, debemos destacar que admite dos niveles de caché (L1 y L2).

En la caché de primer nivel dispondremos de los objetos asociados a nuestra se-sión con los cambios que vayamos realizando. Como hemos visto, existen problemas graves derivados de las actualizaciones concurrentes, independientemente del mode-lo que utilicemos. La utilización de una caché de segundo nivel reduce considera-blemente estos problemas y actua como caché global para las cachés de primer ni-vel. La caché de segundo nivel nos garantizará que estamos trabajando con la ulti-ma versión de los objetos, evitando de esta manera posibles inconsistencias. Evi-dentemente el coste será mayor que si los obtenemos directamente desde la caché de primer nivel pero, sin duda alguna, se tratará de un coste más asumible que si accedemos a la base de datos constantemente.

El hecho de existir dos niveles de caché, hace necesario definir una estrategia de concurrencia que permita sincronizar la caché de primer nivel con la caché de se-gundo nivel y ésta, a su vez, con la base de datos. Tenemos a nuestra disposición cuatro estrategias con diferentes niveles de aislamiento transaccional:

• Transactional: de todos los niveles de aislamiento, éste es el más restricti-

Page 31: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Caché de objetos 23

vo, garantizando un nivel de aislamiento de lectura repetible. Altamente re-comendable cuando no podemos permitirnos el lujo de disponer de datos sin actualizar.

• Read-write: mantiene un aislamiento hasta que se realiza el commited de una transacción. Para ello utiliza un sistema de marcas de tiempo (timestamps).

• Nonstrict read-write: no ofrece garantías de consistencia entre la caché y la base de datos. Los objetos de la caché se sincronizan con la base de datos cuando caduca una marca de tiempo. Con esta estrategia existe un intervalo en el que corremos el riesgo de obtener objetos desincronizados.

• Read-only: de todas, ésta es la estrategia menos restrictiva e ideal para da-tos que nunca cambian.

Actualmente existen diferentes proveedores de caché, y nuestra elección dependerá, como siempre, de los requisitos de nuestra aplicación y de la funcionalidad espera-da. Un proveedor de caché, a grandes rasgos, no es más que una librería donde se implementan los diferentes algoritmos soportados por la caché de segundo nivel. A nuestra disposición tenemos numerosos proyectos de código abierto soportados por JPA2 y, en consecuencia, por Hibernate: EhCache, OSCache, SwarmCache, Jboss Cache o Infinispan (el nuevo producto de Jboss).

EhCache es uno de los proveedores con más aceptación en la comunidad de usua-rios. Cuando nos encontramos aplicaciones donde acceden decenas de miles de usuarios, es posible que necesitemos utilizar cachés distribuidas. Llegado a este punto, el único elemento a configurar es la caché de segundo nivel. Disponemos de varias formas para montar una caché de segundo nivel en cluster:

• El más sencillo, sin lugar a dudas, consiste en una instancia del proveedor de caché en cada nodo del cluster, como por ejemplo, EhCache. Este sistema es el más simple, ya que no existe ningún tipo de sincronización.

• Otra alternativa consiste en instalar un proveedor más avanzado que soporte la sincronización de las cachés entre los diferentes nodos. El proveedor que recomienda Hibernate en este caso es JbossCache.

Estoy convencido de que la falta de una caché de objetos en mi proyecto fin de ca-rrera se hubiese convertido en su particular talón de Aquiles. En el momento de su puesta en producción, intuyo que la aplicación no hubiese funcionado con el rendi-miento esperado. En el caso de haber utilizado algún ORM, la solución sería fácil.

Page 32: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

24 Caché de objetos

Simplemente deberíamos escoger un proveedor de caché y configurarlo para comen-zar a utilizarlo. En este caso en concreto, la solución habría que adoptarla con más detenimiento y ver cómo podría encajar. En ningún caso debemos desanimarnos, todas estas cosas nos deben hacer reflexionar: la próxima vez que nos encontremos ante situaciones similares sabremos cual será la mejor forma de actuar.

2.8. Motores de búsquedaPosiblemente la búsqueda de recursos resulta una de los campos más interesantes en la actualidad. Podría poner la mano en el fuego y afirmar que, la mayoría de los usuarios, lo primero que hacemos cuando navegamos por Internet es abrir un nave-gador y utilizar un buscador. Actualmente nos resultaría imposible imaginar el día a día sin Google u otras de las alternativas existentes (Bing, Yahoo!, etc.). Las bús-quedas se han hecho cada vez más importantes y se han abierto un hueco en nues-tras vidas.

De cara al usuario, la ayuda es inestimable, pero no se debe dejar de lado que la información recabada resulta de vital importancia y podrá ser explotada y analiza-da. En el caso de los grandes buscadores, el negocio reside en la publicidad enfoca-da exclusivamente al público potencial. Esto se consigue gracias a la información obtenida sobre el uso de los buscadores por parte de los usuarios. Como suele de-cirse, la información es poder.

Cada vez son más las aplicaciones web, por no decir casi todas, que incluyen un buscador con idénticas funcionalidades a Google. Con la ayuda de estas búsquedas, podemos recuperar fácilmente determinados recursos. Además no podemos dejar de lado que resultan una importante fuente de información a nivel estadístico. Las búsquedas se han convertido en una parte muy importante de la experiencia del usuario en la Web.

En el mundo Java tenemos numerosas alternativas (Apache Solr, Elastic Search, Compass, Index Tank, Hibernate Search, Summa, Sphinx, Nutch...) que nos ayudan en estas labores. A pesar de ello, Apache Solr brilla por encima de las demás debi-do a su madurez. Aun así, no debemos dejar de lado Elastic Search, por tratarse de una de las alternativas a tener en cuenta y que más interés está despertando.

Apache Solr es un motor de búsqueda de código abierto basado en Apache lucene y que actualmente se encuentra en su versión 4.2. Apache Solr está escrito en Java y se ejecuta como un servidor de búsqueda independiente, dentro de un contenedor de servlets, como puede ser Tomcat. Mediante el uso del API Rest es capaz de rea-

Page 33: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Motores de búsqueda 25

lizar la indexación y búsqueda de documentos a través de peticiones http, utilizan-do diferentes formatos como: XML, JSON, CSV o binarios. Esto facilita enorme-mente la utilización de Solr desde prácticamente cualquier lenguaje de programa-ción. Además debemos destacar a continuación una serie de características que, aun siendo propias de Solr, no es descabellado pensar que deberían estar implícitas en cualquier motor de búsqueda que se precie.

• Optimización para grandes volúmenes de tráfico.

• La inclusión de cachés internas que permiten una mayor rapidez a la hora de devolver el resultado de las búsquedas.

• Configuración de la indexación y recuperación de documentos mediante fi-cheros XML de configuración. También es posible indexar documentos PDF, Word, HTML, etc.

• Incluye mejoras respecto a las consultas incluidas en lucene como la utiliza-ción de filtros y uso de facetas en las búsquedas. Las facetas también pue-den ser realizadas por rangos.

• Posibilidad de resaltar en los resultados el término buscado (highlighting).

• Buscar documentos similares respecto a uno en concreto en función de los campos que deseemos.

• Realizar recomendaciones de las búsquedas realizadas mediante revisión gra-matical (spell-check).

• Posibilidad de autocompletado al que se denomina suggester.

• Soporta geolocalización, lo que permitirá realizar búsquedas por distancias.

• Ordenación de las búsquedas en función de los campos que deseemos, fun-ciones complejas o campos numéricos.

No debemos dejar de lado las posibilidades que nos ofrece la sintaxis de lucene para llevar a cabo las consultas. Normalmente las consultas están compuestas por términos y operadores, permitiendo realizar las siguientes funcionalidades:

• Uso de operadores booleanos:

• +: indica que debe existir la palabra en el documento

Page 34: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

26 Motores de búsqueda

• OR: indica la unión de los conjuntos de palabra y también puede usarse ||.

• NOT: indica que no debe existir la palabra en el documento. Esto es equivalente a una diferencia con conjuntos. En su lugar, puede usarse el símbolo !.

• -: indica que no debe existir la palabra en el documento.

• AND: indica la unión de los conjuntos de palabras-

• A la hora de realizar la búsqueda podemos indicar los campos sobre los que queremos llevar a cabo la búsqueda. nombre_campo:valor

• Realizar consultas por rangos. Fecha:[20020101 to 20030101]

• Búsquedas difusas, basadas en el algoritmo de la búsqueda de Levenshtein, y búsquedas por proximidad, gracias a la utilización del carácter ~.

• Uso de la relevancia de un término, mediante el uso del carácter ^.

Durante la realización de mi proyecto fin de carrera, las búsquedas que podían rea-lizarse eran bastante limitadas y no excesivamente complicadas. A lo sumo, se per-mitían búsquedas por uno o dos campos. Su implementación se llevó a cabo me-diante consultas SQL a la base de datos. Como suele decirse, las comparaciones son odiosas y, esto, poco o nada tiene que ver con las funcionalidades que propor-ciona Sorl.

En el momento de comenzar mi etapa laboral, surgió la posibilidad de realizar un desarrollo relacionado con motores de búsqueda. Más concretamente, se trataba de un directorio de autores, donde debíamos recuperarlos buscando por diferentes campos: nombres, apellidos, fechas en las que han publicado contenido bibliográfi-co, textos relacionados con su bibliografía, etc. En las búsquedas implementadas hasta entonces, se utilizaban funcionalidades propias de Oracle, que facilitaban es-tas tareas. Aunque resulta una alternativa totalmente válida, sigue sin acercarse a la potencia y funcionalidades explicadas.

Actualmente estudiamos posibles alternativas y es ahí cuando nos encontramos con la librería denominada lucene. Con su ayuda se puede hacer una búsqueda de auto-res, por lo que dispone de mayores posibilidades frente a las búsquedas que hasta la fecha se venían realizando. Pese a esto, la actualización de los índices generados por lucene resultaba una tarea excesivamente complicada y manual. También sur-

Page 35: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Motores de búsqueda 27

gieron problemas relacionados con los tiempos de respuesta tras migrar a otras ver-siones. Esto provocó que finalmente nos decantáramos por el uso de Apache Solr.

Muchos de los problemas a los que nos enfrentábamos se solucionaron y nos permi-tieron mayores funcionalidades que las ofrecidas por lucene. Solr proporciona una capa de abstracción sobre lucene, facilitando y simplificando la generación y actua-lización de los índices. Las búsquedas ahora incorporaban facets y ordenaciones de los resultados. Todo esto, sin notar ningún incremento en los tiempos de respuesta.

Actualmente, estamos trabajando en la migración del resto de búsquedas, tras comprobar todas las ventajas que Solr nos brinda.

2.9. Presentación WebTodos conocemos de sobra expresiones como “No juzgues un libro por su por-tada” o “La belleza está en el interior”, pero normalmente terminamos tomándo-las a la ligera. En este sentido, posiblemente nuestro trabajo no resulte tan gratifi-cante, puesto que, en ocasiones, somos incapaces de apreciar el esfuerzo realizado para alcanzar determinados resultados. Es algo en lo que normalmente no hacemos demasiado hincapié.

Cuando contemplamos una pintura, un monumento, una obra de teatro o una pe-lícula, todos nos asombramos y maravillamos, pero no solemos percatamos del tra-bajo que hay detrás. Ninguno nos detenemos a pensar en las horas de sacrificio y esfuerzo invertidas; simplemente, valoramos el resultado.

Lo mismo sucede cuando nos referimos a las aplicaciones informáticas. Durante to-dos estos capítulos, me he referido a las herramientas, frameworks y librerías que deberían tenerse en cuenta a la hora de abordar el desarrollo de una aplicación in-formática. Usarlas depende únicamente de nuestra decisión y de un trabajo previo que deberemos realizar. No basta con utilizarlas, también será necesario dedicar un tiempo de aprendizaje en caso de no estar familiarizado con ellas. Por lo tanto, será imprescindible adoptar multitud de decisiones y afrontar numerosos obstáculos hasta alcanzar nuestro objetivo final. Por último, lo que los usuarios verán será una fachada o presentación: la cara bonita del trabajo realizado.

Centrarnos exclusivamente en los resultados no nos llevará a ninguna parte. Imagi-nemos que un constructor, para hacer un edificio, ahorrase costes tanto en el mate-rial como en personal. El edificio puede resultar una maravilla, pero, debido al tra-bajo que hay detrás, empezasen a surgir los primeros problemas o pudiera venirse

Page 36: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

28 Presentación Web

abajo en cuestión de años. Una buena fachada sobre unos buenos cimientos es la clave para conseguir buenos resultados.

Aunque siempre existen alternativas, para la construcción del interfaz gráfico de una página Web, nos centraremos en JavaServer Faces (JSF).

Como la mayoría de las tecnologías más importantes, la creación de JSF es fruto de un proceso de evolución y mejora a lo largo de los años. Surge como una necesi-dad de construir interfaces de usuario bien diseñadas y de fácil mantenimiento, todo ello de una forma simple y eficiente.

A mediados de los años noventa, el desarrollo de aplicaciones web todavía era un concepto relativamente nuevo. Las aplicaciones CGI (The Common Gateway Interface) fueron unas de las primeras en crear contenido dinámico para las pági-nas web. A grandes rasgos, esta técnica permitía a una página web invocar proce-sos en el lado del servidor cuyo resultado final eran objetos MIME.

El siguiente paso en la evolución de las aplicaciones web surgió con la introducción a finales de los noventa de Java Servlet API. Antes de esto, Java no se utilizaba como una tecnología del lado del servidor para aplicaciones Web. La mayoría de las aplicaciones web en aquella época consistían en Applets que podían ejecutarse en un navegador. Aunque eran relativamente buenos para proveer de contenido diná-mico, nunca resultaron muy apropiadas para el desarrollo web. La Java Servlet API permitió a los desarrolladores Java escribir un código para generar contenido dinámico en sus páginas web. Aunque esto supuso una notable mejora, todavía existía un gran problema: la forma de generar HTML era a muy bajo nivel, tediosa y propensa a errores.

Con el fin de mejorar estos problemas, surgieron las páginas JSP (JavaServer Pa-ges). De esta forma, por encima de los servlets, se disponía de una solución que fa-cilitaba la generación de grandes cantidades de HTML dinámico. Proporcionaron una importante mejora, pero no una solución definitiva. Las aplicaciones web cada vez eran más complejas y, la mezcla de código, complicaba las cosas y propiciaba errores. La necesidad de una separación entre el código Java de nuestra aplicación y del marcado de la presentación obligó a utilizar el patrón MVC (Modelo – Vista – Controlador).

Es en este preciso momento cuando surge uno de los frameworks de Java más do-minantes en los últimos años, conocido como Struts. A pesar de su arquitectura, es necesaria una cantidad sustancial de desarrollos a medida para la creación de los interfaces de usuario. Incluso en combinación con el uso de etiquetas JSLT, el desa-

Page 37: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Presentación Web 29

rrollo con Struts continúa siendo complicado y, más si cabe, si comparamos con tecnologías propietarias existentes en la época. Con ASP.NET, la experiencia de desarrollo resultaba menos compleja debido a que estaba más basada en compo-nentes.

Después de la enorme popularidad cosechada por Struts, la comunidad de Java en-seguida descubrió las ventajas que aportaba. Aun así, era necesario mejorar la ma-nera en la que la vista era manejada. Para satisfacer dicha necesidad, terminó ori-ginándose la especificación JSR-127. El objetivo era proporcionar una forma están-dar y mucho más sencilla para construir interfaces para aplicaciones Web, dando lugar a JSF. No debemos dejar de lado la posibilidad de utilizar componentes ricos que nos ayudarán a la hora de construir nuestras aplicaciones web (Primefaces, Ri-chFaces, ICEfaces, etc.)

Poco o nada tengo que añadir al respecto en lo que se refiere a mi proyecto fin de carrera, ya que éste consistía en una aplicación de escritorio. Sin embargo, en el trabajo me ha tocado “lidiar” con Struts. Como se ha comentado con anterioridad, desarrollar una simple funcionalidad implica un enorme esfuerzo por nuestra parte. Debemos “cocinar” absolutamente todo, hasta el más mínimo detalle, lo que no fa-cilita para nada el trabajo.

No hace mucho, con la excusa del desarrollo de una nueva aplicación, surgió la po-sibilidad de realizar un curso de JSF2. Pronto pude comprobar los beneficios que proporcionaba frente al uso de Struts. El desarrollo era mucho más claro y rápido. Me atrevería a decir que los resultados obtenidos, eran mucho más enriquecedores de cara a los usuarios, proporcionando mayores posibilidades visuales.

Es cierto que Struts fue ampliamente reconocido por la comunidad pero, hoy por hoy, JSF2 supone un soplo de aire fresco. El hecho de ser un estándar, actualmente lo convierte en una de las mejores alternativas.

2.10. InternacionalizaciónSeguramente, cuando nombramos la Torre de Babel, a todos nos viene a la me-moria la historia relatada en el antiguo Testamento. Con el fin de evitar el éxito de su edificación, Dios hizo hablar a los constructores en diferentes lenguas, consi-guiendo así su dispersión por la Tierra.

Lo narrado en la historia es un fiel reflejo de la realidad. Según la Wikipedia, Ethnologue, en su resultado del año 2009, indica que hay alrededor de 6.909 len-

Page 38: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

30 Internacionalización

guas en el mundo. No hace falta irnos muy lejos, puesto que en España además del castellano, disponemos de otras lenguas cooficiales, tales como: catalán, gallego o vasco.

Debido a la cantidad de lenguas existentes, siempre deberíamos tener en mente la posibilidad de que nuestras aplicaciones se encuentren disponibles en diferentes idiomas. Esto deberá llevarse a cabo sin realizar cambios en nuestro código. Nor-malmente, cuando nos referimos a este concepto, utilizamos la abreviatura i18n. Las principales características con las que tiene que contar una aplicación interna-cionalizada son:

• Un mismo ejecutable de nuestra aplicación que permita su ejecución en dis-tintos idiomas con sólo cambiar la localización regional (java.util.Locale) del usuario.

• Los textos susceptibles a cambios no debemos incluirlos directamente en el código. En su lugar debieran aparecer variables que sirvan como identifica-dores del texto a mostrar.

• Los números, fechas, moneda, etc, aparecerán con el formato correspondien-te al idioma seleccionado.

Esta funcionalidad no resulta nada complicada implementarla en java y, más aún, con la ayuda de JSF 2.0. Para internacionalizar nuestras aplicaciones, lo más co-mún suele ser, usar el API ResourceBundle en combinación con ficheros de propie-dades. Necesitaremos un fichero de propiedades por cada idioma que deseemos que nuestra aplicación soporte. Dependiendo del idioma seleccionado se utilizará un fi-chero u otro.

Algo que no debemos perder de vista es la codificación de los caracteres existentes en los ficheros de propiedades. Lo lógico es utilizar la codificación UTF-8 todo el tiempo, ya que de esta forma evitaremos problemas con cualquier carácter especial.

Page 39: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Integración y Construcción 31

3. Integración y ConstrucciónEn el capítulo anterior nos hemos referido a los distintos componentes que debería-mos tener en cuenta a la hora de desarrollar una aplicación informática. El abanico es tan amplio que ha sido necesario resaltar lo que he considerado más relevante.

Hubiese resultado interesante abarcar temas relacionados estrechamente con la se-guridad y la gestión de permisos, pero el tiempo es limitado. En el tintero dejamos cantidad de alternativas a tener en cuenta.

El siguiente capítulo lo dedicaremos a algo más técnico y práctico. Una vez desta-cadas las herramientas y componentes que deberíamos considerar a la hora de afrontar un proyecto, ha llegado la hora de construirlo y de configurar cada uno de sus componentes.

Para la construcción del proyecto nos ayudaremos de Maven y de Spring Framework, que actuará como pegamento para la unión de los diferentes compo-nentes de nuestra aplicación. El objetivo consiste en centrarse en el funcionamiento y las posibilidades que nos brinda Maven, así como la creación de los diferentes fi-cheros de configuración que permitan el funcionamiento coordinado entre los com-ponentes.

De esta forma, dispondremos de un entorno funcional sobre el que podremos co-menzar a programar nuestras aplicaciones de la manera más cómoda, sencilla y ágil posible.

3.1. MavenMaven es una herramienta de código libre que permite administrar los proyectos de software que, a día de hoy, se ha hecho un hueco importante en el sector. Cuando hablamos de administrar, nos referimos desde la gestión del ciclo de vida de un proyecto, hasta la generación de sus binarios.

Page 40: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

32 Maven

Hasta ahora, muchas de las fases de un proyecto eran gestionadas prácticamente de forma manual: compilación, empaquetado, versiones, control de dependencias, ge-neración de la documentación, etc.

Maven nos facilita la automatización de todas estas tareas y se involucra totalmen-te en la gestión de la configuración. Según wikipedia, “Se denomina Gestión de la Configuración al conjunto de procesos destinados a asegurar la validez de todo pro-ducto obtenido durante cualquiera de las etapas del desarrollo de un Sistema de Información (S.I.), a través del estricto control de los cambios realizados sobre los mismos y de la disponibilidad constante de una versión estable de cada elemento para toda persona involucrada en el citado desarrollo.”.

Nació como un complemento de Ant y generalmente, al igual que ésta, es conside-rada por muchos como una herramienta de construcción. Maven va más allá e in-tenta conseguir una infraestructura visible, reutilizable, de fácil mantenimiento y comprensible. Sin estas premisas, es difícil que un grupo de personas consiga traba-jar de forma conjunta de manera productiva.

No es de extrañar que en un proyecto no se reutilice el código debido a que los de-sarrolladores no conocen lo que sus compañeros han desarrollado. Esta situación provoca frustración y una enorme dificultad a la hora de mantener el código. No es la primera vez que navegamos entre código, con el fin de recomponer un rompeca-bezas que nos permita comprender el problema en su totalidad.

Maven nació con una idea clara: hacer que todos los proyectos se hicieran de forma similar. De esta forma los desarrolladores podrían desenvolverse y trabajar sin difi-cultades entre una gran variedad de proyectos. Un desarrollador no malgastará tiempo en comprender cómo se construye cada uno de los proyectos, puesto que to-dos tendrán una estructura similar. Esta misma idea se extiende a la generación de documentación, generación de métricas e informes, pruebas y despliegue.

Todos los proyectos compartirán la mayoría de sus principales características, es por esto que Maven aprovecha un enfoque genérico para la gestión de proyectos. Es inevitable que, por norma general, los proyectos tienden a ser construidos, proba-dos, ensamblados, documentados e implementados. Pueden existir pequeñas varia-ciones en los pasos mencionados; no obstante, seguiremos un camino claro y bien definido gracias a la inestimable ayuda de Maven.

La manera más fácil de despejar este camino lleno de obstáculos consiste en pro-porcionar a los desarrolladores un conjunto de patrones que puedan compartirse entre todos los miembros involucrados en el proyecto.

Page 41: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Maven 33

Entre los aspectos más importantes a destacar se encuentran:

• Facilidad en el proceso de construcción.

• Proporciona una estructura consistente, ya que normalmente todos los pro-yectos tienen por defecto la misma estructura de directorios.

• Facilidad en la configuración de proyectos siguiendo buenas prácticas de software, permitiendo generar un nuevo proyecto en poco tiempo.

• Gestión avanzada de las dependencias mediante el uso de repositorios.

• Altamente extensible mediante el uso de plugins existentes o propios.

• Facilidad para trabajar con múltiples proyectos simultáneos.

Hasta no hace mucho tiempo, en mi trabajo, no comenzamos a trabajar con Maven, y las ventajas pronto se hicieron patentes. Entre otras cosas, el despliegue, la gestión de las dependencias y de los diferentes proyectos de los que disponemos, facilitaron el trabajo enormemente. Además, hasta entonces, disponíamos en nues-tro sistema de control versiones de proyectos con estructuras propias de Netbeans (IDE utilizado por los miembros del equipo), lo que hacía bastante difícil e incluso imposible utilizar cualquier otro.

Debido a la estructura de proyectos propuesta por Maven, actualmente no nos en-contramos ligados a ningún IDE determinado, y cada miembro del equipo dispone de total libertad para elegir el que más le apetezca a la hora de trabajar. Aunque son muchas las posibilidades que esta herramienta nos ofrece, a día de hoy conti-nuamos sin utilizar el 100% de sus capacidades.

3.1.1. Ciclo de vidaMaven nos propone una serie de etapas para la gestión de un proyecto. Esto signi-fica que el proceso de construcción y distribución de un proyecto está claramente definido.

Debemos destacar la existencia de 3 ciclos de vida:

• clean: elimina todos los ficheros con la extensión class y jar generados. Des-pués de este comando se puede comenzar un compilado desde cero.

• default: genera archivos binarios de nuestro proyecto.

Page 42: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

34 Ciclo de vida

• site: genera archivos HTML que describen nuestro proyecto.

Cada ciclo de vida está compuesto por varias fases. Entre las más relevantes, y en orden de ejecución, se encuentran:

• validate: valida que el proyecto es correcto y tiene toda la información ne-cesaria.

• initialize: configura propiedades y crea directorios.

• compile: compila el código fuente del proyecto.

• test: compila el código y ejecuta los casos de prueba correspondientes. Sin embargo no es necesario para que el proyecto sea desplegado.

• package: toma el código compilado y lo empaqueta en un formato de dis-tribución, como pueden ser los formatos jar o war.

• verify: ejecuta cualquier verificación para cumplir los parámetros de cali-dad.

• install: instala el jar o war en el repositorio local para que otras aplicacio-nes locales la puedan usar.

• deploy: copia el jar o war a un repositorio remoto para que pueda ser usa-do por otro desarrollador o proyecto.

3.1.2. Repositorio de MavenEl repositorio, en Maven, es una estructura de directorios y archivos que se utiliza para almacenar y organizar, arquetipos y dependencias, con el fin de que sean ac-cesibles desde cualquier proyecto. Podemos diferenciar entre dos tipos de reposito-rios:

• local: situado en la máquina del desarrollador. Almacena dependencias ins-taladas y descargadas desde repositorios remotos. Si es la primera vez que ejecutamos nuestro proyecto, nos llevará tiempo, ya que Maven creará el re-positorio inicial .m2 y descargará todas las librerías necesarias para cons-truirlo.

• remoto: son aquellos que se encuentran en Internet y desde los que podre-mos descargar las dependencias de terceros.

Page 43: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Repositorio de Maven 35

Maven dispone de un repositorio oficial en Internet donde podemos encontrar gran cantidad de proyectos (en adelante nos referiremos a ellos como dependencias). En caso de no encontrar la dependencia buscada en el repositorio por defecto, existe la posibilidad de añadir otros en el fichero POM.

En mi caso, debido a que las dependencias de Primefaces no se encontraban en el repositorio por defecto, ha sido necesario añadir uno:

<repositories><repository>

<id>prime-repo</id> <name>PrimeFaces Maven Repository</name><url>http://repository.primefaces.org</url><layout>default</layout>

</repository></repositories>

En ocasiones, cuando nos encontremos ante proyectos de gran envergadura, será re-comendable la utilización de un repositorio común.

3.1.3. Estructura de directoriosLa estructura de directorios de Maven es muy precisa y nos orienta a la hora de si-tuar nuestras clases, test o recursos para que puedan ser tratados de forma correc-ta. Dicha estructura consiste en una convención utilizada por Maven y que de algu-na forma se ha convertido en un estándar dentro de los proyectos Java. Es posible personalizar los nombres y localización de las carpetas, pero se recomienda utilizar la expuesta a continuación, ya que las personas acostumbradas a trabajar con Maven ya estarán familiarizadas con ella.

• /src/main/java: aquí se guardan las clases Java de nuestra aplicación or-ganizadas por paquetes.

• /src/main/resources: aquí se almacenan los recursos (ficheros XML, fi-cheros de propiedades, imágenes...) que pueda necesitar nuestra aplicación. Por ejemplo, éste sería el lugar donde se almacenen los ficheros de configu-ración de Spring o Hibernate.

• /src/main/webapp: fuentes de la aplicación web.

• /src/test/java: en esta carpeta se guardan las clases de test que se encar-garán de probar el correcto funcionamiento de nuestra aplicación.

• /src/test/resources: en esta carpeta se almacenan los recursos que pue-

Page 44: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

36 Estructura de directorios

dan necesitar nuestras clases de prueba.

• /target: directorio donde Maven almacena los resultados.

• /target/clases: aquí se guarda el resultado de la compilación de nuestro proyecto.

• pom.xml: el POM (Project Object Model), es la piedra angular de Maven.

Cuando hablamos de un proyecto Maven, nos referimos a algo más que una mera colección de archivos que contienen código; se trata de un proyecto compuesto por archivos de configuración, los desarrollares involucrados y los papeles que estos de-sempeñan, licencias, dependencias y otras muchas piezas que darán vida a nuestro código.

3.1.4. POM (Project Object Model)El fichero POM describe con qué tipo de proyecto estamos trabajando y cómo mo-dificar el comportamiento por defecto para generar un resultado adecuado. De la misma manera que una aplicación web Java necesita de un fichero web.xml que describe, configura y personaliza la aplicación, un proyecto Maven se define por la presencia de un fichero POM cuyo formato es el XML. En su mayoría contendrá las descripciones necesarias para ubicar el código fuente y de los recursos, instruc-ciones para compilar el proyecto, etc. Un mapa, que Maven necesita para entender y así poder construir y gestionar el proyecto.

3.1.4.1. Información general del proyecto

Un fichero POM, como mínimo, está obligado a disponer de una serie de atributos que permitirán identificar los proyectos. En esta parte puede incluirse el nombre, versión, URL, organización, lista de desarrolladores de nuestro proyecto, etc.

• groupId: nombre que identifica nuestro proyecto de forma inequívoca res-pecto al resto de proyectos. Una buena práctica consiste en utilizar la es-tructura de paquetes de nuestro proyecto. (ej.: org.slf4j)

• artifactId: Generalmente es el nombre por el que se conocerá a nuestro proyecto. (ej.: slf4j-api)

• version: es la última pieza del rompecabezas y nos permite identificar las diferentes versiones de los proyectos. (ej.: 1.7.5)

Page 45: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

POM (Project Object Model) 37

Otro atributo interesante y que utilizaremos será packaging, que identifica el tipo de proyecto con el que estamos trabajando (war o jar). A continuación podemos ver los atributos que hemos utilizado para la creación de nuestro proyecto:

<project ...><groupId>es.unirioja</groupId><artifactId>TFG</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><name>TFG</name><description>Estudio para la realización de una “navaja suiza”...</description>

</project>

3.1.4.2. Opciones de construcción

En esta sección podemos modificar el comportamiento que tiene por defecto Maven a la hora de construir los proyectos. Entre otras cosas, será posible cambiar la ubicación de los ficheros fuentes o de pruebas, e incluso añadir nuevos plugins. Este apartado viene identificado por las etiquetas <build></build>.

Una característica interesante y de gran utilidad es la utilización de filtros. Pode-mos utilizar ficheros de propiedades que contengan la definición de determinadas constantes y utilizarlas posteriormente en nuestros ficheros de configuración y re-cursos. A la hora de aplicar los filtros, dichas constantes serán sustituidas por su correspondiente valor. Esta técnica se utiliza casi habitualmente con el fin de cen-tralizar determinados valores que pueden repetirse, además de facilitar la configu-ración de distintos perfiles de una manera fácil y cómoda (producción y pruebas).

Conseguir esto es muy simple y basta con seguir los siguientes pasos:

• Crear un fichero de propiedades que se encuentre ubicado en /src/main/filters.

#BD.properties# Authoer: Javier Hernáez Hurtado# Definición de las constantes para conectar a la base de datosbd_driver=org.postgresql.Driverbd_url=jdbc:postgresql://localhost:5432/Librosbd_username=postgresbd_password=rootbd_dialect=org.hibernate.dialect.PostgreSQLDialect

• Establecer los filtros de los que vamos a disponer, es decir, indicar cuáles son los ficheros de propiedades que tienen el valor de las constantes.

Page 46: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

38 POM (Project Object Model)

<filters><filter>src/main/filters/BD.properties</filter>

</filters>

• Indicar los ficheros sobre los que queremos aplicar los filtros. Simplemente deberemos especificar la ubicación de los mismos y todas las constantes que aparezcan serán sustituidas por el valor que hayamos definido.

<build><resources>

<resource><directory>src/main/resources</directory><filtering>true</filtering>

</resource></resources><testResources>

<testResource><directory>src/test/resources</directory><filtering>true</filtering>

</testResource> </testResources>

</build>

• Utilizar las constantes ${nombre_constante} en nuestros ficheros de recursos para que una vez compilemos el proyecto éstas sean sustituidas por su co-rrespondiente valor.

<!-- persistence.xml--><property name="hibernate.connection.driver_class" value="${bd_driver}"/><property name="hibernate.connection.url" value="${bd_url}"/><property name="hibernate.connection.username" value="${bd_username}"/><property name="hibernate.connection.password" value="${bd_password}"/>

Otra opción muy interesante consiste en la utilización de plugins. Éstos, en reali-dad, son programas que se ejecutan en Maven y realizan determinadas tareas. A continuación enumeraremos algunos de los que hemos utilizado y las funciones que estos desempeñan.

• maven-compiler-plugin: este plugin viene por defecto y permite compilar nuestro proyecto. Entre otras cosas, podemos indicarle la versión de java con la que deseamos que se compilen los fuentes y la codificación de caracteres que deseamos utilizar.

• maven-war-plugin: utilizado para empaquetar nuestro proyecto web. En-tre otras cosas podemos indicarle la ubicación de los fuentes y el nombre que le queremos dar al fichero war.

• versions-maven-plugin: permite localizar de forma automática cuál de

Page 47: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

POM (Project Object Model) 39

nuestras librerías dispone de nuevas versiones. En caso de necesitarlo, pode-mos actualizarlas automáticamente, aunque lo recomendable para estos ca-sos es hacerlo de una forma manual.

• maven-dependency-plugin: en ocasiones, es necesario conocer el origen de una determinada dependencia. Es inevitable, que surjan incompatibilida-des entre distintos jar utilizados en el desarrollo de nuestras aplicaciones.

• maven-surefire-plugin: utilizado para ejecutar pruebas unitarias y gene-rar informes con los resultados obtenidos.

• maven-javadoc-plugin: ayuda a generar la documentación de nuestros proyectos.

Existen otros muchos plugins que nos ayudan a verificar buenas prácticas de desa-rrollo realizando métricas de nuestro código, generación de documentos con los cambios más recientes del proyecto que han sido almacenados en nuestro sistema de control de versiones o incluso la construcción de arquetipos, de los que hablare-mos más adelante.

3.1.4.3. Gestión de dependencias

Uno de los puntos fuertes de Maven son las dependencias. En nuestros proyectos, podemos incluir las librerías que necesitamos (por ejemplo log4j o Hibernate), ya que Maven es capaz de buscarlas y descargarlas automáticamente desde los reposi-torios. Hay que tener en cuenta que, si estas librerías dependen de otras (depen-dencias transitivas), lleva a cabo la misma operación, bajándose todas las librerías necesarias.

Si deseamos añadir a nuestro proyecto determinadas dependencias, bastará con editar el fichero POM. Por defecto, Maven incluye de manera automática en todos nuestros proyectos el uso de JUnit como se indica a continuación:

<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependencies>

En caso de necesitar más dependencias, simplemente debemos añadirlas dentro del

Page 48: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

40 POM (Project Object Model)

bloque <dependencies> de la misma forma que se ha añadido JUnit.

Como podemos observar, será necesario incluir los tres atributos obligatorios a los que nos hemos referido anteriormente, ya que es la forma de identificar un proyec-to. Además de éstos, existe el atributo scope, que identifica para qué necesitamos el jar. Puede tomar los siguientes valores:

• compile: es el utilizado por defecto en caso de no especificar ninguno de forma explícita. Estas dependencias se usan en el classpath del proyecto y serán incluidas en el artefacto final.

• provided: estas dependencias se usan durante la fase de compilación y pruebas. Muy utilizado para incluir los jar que son necesarios para compilar pero que no son necesarios volverlos a incluir dentro de nuestro proyecto.

• runtime: indica que la dependencia será necesaria durante la ejecución de tu aplicación pero no a la hora de llevar a cabo la compilación.

• test: indica que la dependencia sólo es necesaria para compilar y ejecutar los casos de prueba de nuestro proyecto.

• system: igual que provided, pero aquí se debe especificar una ubicación de nuestro disco duro para evitar que Maven busque en los repositorios.

• import: permite importar otros archivos POM para simular herencia múlti-ple, ya que Maven solo permite heredar de un único POM.

En nuestro caso, hemos añadido todas las dependencias que serán recomendables utilizar y que ya se avanzaban en el capítulo dos:

• Sistema de registro de mensajes: slf4j, slf4j-log4j12 y log4j.

• Pruebas: JUnit.

• Conexión a base de datos: c3p0.

• Mapeo relacional de objetos: hibernate-core, hibernate-entitymanager e hibernate-jmx.

• Driver de base de datos: postgresql.

• Caché de objetos: EhCache-core, hibernate-EhCache.

• Validaciones: hibernate-validator.

Page 49: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

POM (Project Object Model) 41

• Presentación web: jsf-api y jsf-impl.

• SpringFramework: spring-context, spring-web,spring-tx,spring-orm, spring-jpa, spring-context-support.

La mayoría de las dependencias tendrán el scope por defecto, a excepción de Junit, que tendrá el valor test.

3.1.5. ArquetiposComo podemos observar, son muchas las opciones que nos proporciona Maven, ha-biendo explicado ya algunas con el fin de aclarar en que consisten este tipo de pro-yectos.

Uno de los objetivos del TFG consistía en crear un marco de trabajo que sirviese de base a los desarrolladores para escribir y organizar el código de sus aplicaciones. Por este motivo, no podemos pasar por alto los arquetipos.

En esencia, un arquetipo es una plantilla que nos ayudará a crear proyectos que utilicen determinadas tecnologías ya configuradas. Todos los proyectos que involu-cren las tecnologías de las que hemos hablado, partirán de una base (arquetipo, plantilla o esqueleto) común, proporcionándonos una serie de ventajas:

• Consistencia entre distintos desarrollos cuyo punto en común son las mismas tecnologías o el entorno configurado sobre las que serán desplegados y ejecu-tados.

• Reutilización y composición de unos arquetipos como suma de otros.

• Crear un estándar de los proyectos dentro de una empresa. Los arquetipos pueden compartirse en el repositorio y todos los proyectos de la empresa tendrán características similares.

• Evitar tiempos muertos en el comienzo de la implementación al disponer de un entorno correctamente configurado.

• La estructura del proyecto facilita las tareas de desarrollo, distribución y despliegue al equipo de desarrollo.

La utilización de los arquetipos evitará reinventar la rueda ante situaciones con ca-racterísticas similares.

Page 50: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

42 Arquetipos

3.1.5.1. Construcción de un arquetipo

Crear arquetipos resultará fácil utilizando maven-archetype-plugin. En nuestro caso en particular, el arquetipo se creará a partir del proyecto de prueba construido con objetivo del TFG.

A la hora de definir un arquetipo debemos, al igual que ocurría en las dependen-cias, especificaremos tres parámetros (groupId, artifactId, version) de la siguiente manera:

mvn archetype:create-from-project -DarchetypeGroupId=<archetype-groupId> -DarchetypeArtifactId=<archetype-artifactId> -DarchetypeVersion=<archetype-version>

Esto generará automáticamente un fichero con extensión jar dentro de la carpeta /target/generated-sources/archetype/target.

Sólo nos falta instalar en nuestro repositorio local el arquetipo utilizando maven- install-plugin y crear el fichero de configuración /.m2/archetype-catalog.xml, tal y como veremos a continuación:

mvn archetype:intall-file -Dfile=target/generated-sources/archetype/target/TFG-archetype-1.0-SNAPSHOT.jar-DgroupId=es.unirioja.archetype-DartifactId=tfg-archetype-Dversion=1.0-SNAPSHOT-Dpackaging=jar

<!---------------------------------------------><!-- archetype-catalog.xml --><!---------------------------------------------><archetype-catalog xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/ar-chetype-catalog/1.0.0 http://maven.apache.org/xsd/archetype-catalog-1.0.0.xsd">

<archetypes><archetype>

<groupId>es.unirioja.archetype</groupId><artifactId>tfg-archetype</artifactId><version>1.0-SNAPSHOT</version><description>

Estudio para la realización de una “navaja suiza” para el desarrollo de aplicaciones software.

</description></archetype>

</archetypes></archetype-catalog>

Una vez tenemos nuestro arquetipo instalado en nuestro repositorio local, ha llega-do el momento de crear nuestros proyectos.

Page 51: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Spring Framework 43

3.2. Spring FrameworkSpring nos proporciona un marco de trabajo cuya finalidad es facilitar el desarrollo de las aplicaciones desarrolladas con Java. No nos encontramos ante un framework más, ya que funciona como un contenedor que gestiona el ciclo de vida de los obje-tos y las relaciones existentes entre ellos. Busca la simplicidad y además se basa en la inyección de dependencias para obtener un acoplamiento débil.

Asimismo posee diversos módulos que podemos agregar dependiendo de las funcio-nalidades deseadas en nuestras aplicaciones. El único módulo necesario para utili-zar Spring es el núcleo de Spring, que nos proporciona la inyección de dependencias y la configuración y uso de los objetos Java. A continuación vamos a explicar al-guno de los módulos y características más interesantes que utilizaremos:

• ORM: provee integración para las distintas APIs de mapeo relacional de objetos incluyendo JPA, Hibernate o iBatis.

• Gestión de transacciones: nos proporciona una gestión de transacciones de forma sencilla. El gestor de transacciones nos permite configurar las tran-sacciones mediante un fichero XML, anotaciones o de forma programática. Además, soporta numerosos APIs como JTA, JDBC, Hibernate, JPA y JDO.

• Inyección de dependencia: permite que un objeto conozca sus dependen-cias mediante una interfaz y no por su implementación. De esta forma, la implementación puede variar sin que el objeto dependiente se dé cuenta. Una de las grandes ventajas es el acoplamiento débil entre objetos. También cabe destacar que toda la creación de objetos y paso de dependencias des-aparece de nuestro código, con lo que el código obtenido resultará mucho más limpio. Estas declaraciones quedan reflejadas en un fichero XML (applicationContext.xml).

• Web: módulo que aporta clases especiales orientadas al desarrollo web e in-tegración con tecnologías como Struts y JSF.

• Administración remota: Configuración de visibilidad y gestión de los ob-jetos Java para la configuración local o remota vía JMX. Lo utilizaremos para gestionar remotamente el registro de mensajes y monitorizar el sistema de caché de objetos.

Una vez expuestas las características que vamos a aprovechar de Spring, es hora de

Page 52: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

44 Spring Framework

centrarse en los ficheros de configuración que harán que nuestras aplicaciones co-bren vida.

3.3. Ficheros de configuraciónDurante este capítulo hemos explicado como crear nuestros proyectos Maven. A continuación nos referiremos a las configuraciones necesarias para las herramientas utilizadas y, así, estar listos para programar en un entorno totalmente configurado y operativo. Todos los ficheros de configuración que necesitamos estarán disponi-bles dentro de la carpeta /src/main/resources.

3.3.1. Registro de mensajes Para la configuración de log4j hemos utilizado un fichero de propiedades, aunque también es posible hacerlo mediante un fichero XML. Antes de entrar en detalle, vamos a hacer hincapié en algunos conceptos claves para la configuración:

• logger: Definen la configuración global o particular de nuestros paquetes, en la cual se indica los appenders que se utilizarán y el nivel de detalle de los mensajes (DEBUG, INFO, ERROR, etc.)

• appender: componente que se encarga de definir cuál será plantilla y el destino de nuestros mensajes de log. Tal y como ya comentábamos cuando hablábamos de los sistemas de registros de mensajes, existen varios destinos posibles. Nosotros, de momento, utilizaremos la consola y los archivos de texto. Cada logger puede tener asociado uno o más appender.

• Con esto claro, podemos ver la definición de nuestro lo4j.properties. Al co-mienzo del fichero, se han definido constantes de uso común.

#valor que viene definido como propiedad en el fichero POMdirectorioDeLogs=${log.folder} encodingPorDefecto=UTF-8#Diseño de los mensajes que se mostraránconversionPatternPorDefecto=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

A continuación vamos a ver la definición de rootLogger para detectar cualquier error que se produzca en nuestra aplicación. Éste, tendrá asociado un appender que se encargará de mostrar por consola (console) y otro que escribirá en un fichero (file).

Page 53: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Registro de mensajes 45

#------------------------------------------------------------------------------#- ROOT LOGGER #------------------------------------------------------------------------------# Coloca el nivel del root logger en ERROR# Añade el appender console y filelog4j.rootLogger=ERROR, console, file# Appender para mostrar errores por consolalog4j.appender.console=org.apache.log4j.ConsoleAppender # Appender de consolelog4j.appender.console.encoding=${encodingPorDefecto} #Constante definidalog4j.appender.console.Target=System.outlog4j.appender.console.Threshold=DEBUG # Ningún mensaje con prioridad menor a DEBUGlog4j.appender.console.layout=org.apache.log4j.PatternLayout # Utilización de PatternLayoutlog4j.appender.console.layout.ConversionPattern=${conversionPatternPorDefecto} #Constante definida# Appender para mostrar errores por ficherolog4j.appender.file=org.apache.log4j.RollingFileAppenderlog4j.appender.file.encoding=${encodingPorDefecto} #Constante definidalog4j.appender.file.File=${directorioDeLogs}/consola.log # Fichero donde se almacenan los mensajeslog4j.appender.file.MaxFileSize=1MBlog4j.appender.file.MaxBackupIndex=1log4j.appender.file.Threshold=DEBUGlog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=${conversionPatternPorDefecto} #Constante definida

Como mínimo deberíamos tener definido el rootLogger pero, cuantos más añada-mos, más control tendremos sobre lo que sucede en nuestras aplicaciones. En prin-cipio hemos decidido añadir dos más con el fin de conseguir algo más de detalle.

Uno de ellos nos mostrará todo lo relacionado con Hibernate dejándolo reflejado en el fichero hibernate.log, y el otro nos mostrará todo lo relacionado con la caché de objetos, que aparece reflejado en el fichero EhCache.log.

# Logger y appender para Hibernatelog4j.logger.org.hibernate=DEBUG, orm# Appender para mostrar errores por ficherolog4j.appender.orm=org.apache.log4j.RollingFileAppenderlog4j.appender.orm.File=${directorioDeLogs}/hibernate.log # Fichero donde se almacenan los mensajeslog4j.appender.orm.encoding=${encodingPorDefecto} #Constante definidalog4j.appender.orm.MaxFileSize=1MBlog4j.appender.orm.MaxBackupIndex=1log4j.appender.orm.Threshold=DEBUGlog4j.appender.orm.layout=org.apache.log4j.PatternLayoutlog4j.appender.orm.layout.ConversionPattern=${conversionPatternPorDefecto} #Constante definida# Logger y appender para EhCachelog4j.logger.net.sf.EhCache=DEBUG, cache# Appender para mostrar errores por ficherolog4j.appender.cache=org.apache.log4j.RollingFileAppenderlog4j.appender.cache.File=${directorioDeLogs}/EhCache.loglog4j.appender.cache.MaxFileSize=1MBlog4j.appender.cache.MaxBackupIndex=1log4j.appender.cache.Threshold=DEBUGlog4j.appender.cache.layout=org.apache.log4j.PatternLayoutlog4j.appender.cache.layout.ConversionPattern=${conversionPatternPorDefecto} #Constante definida

Page 54: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

46 JPA e Hibernate

3.3.2. JPA e Hibernate Para configurar JPA con Hibernate como proveedor de persistencia, es necesario crear el fichero persistence.xml dentro de la carpeta /META-INF y seguir los si-guientes pasos:

1. Definimos la unidad de persistencia que en nuestro caso la hemos llamado es.unirioja.tfg

<persistence-unit name="es.unirioja.tfg" transaction-type="RESOURCE_LOCAL">

2. Registramos Hibernate como proveedor de persistencia.

<provider>org.hibernate.ejb.HibernatePersistence</provider>

3. Debemos registrar las entidades que existen en nuestra aplicación y para ello utilizaremos una propiedad que detectará de forma automática las cla-ses mapeadas con JPA.

<property name="hibernate.archive.autodetection" value="class, hbm"/>

4. Registrar las propiedades de conexión a la Base de datos.

<property name="hibernate.connection.driver_class" value="${bd_driver}"/><property name="hibernate.connection.url" value="${bd_url}"/><property name="hibernate.connection.username" value="${bd_username}"/><property name="hibernate.connection.password" value="${bd_password}"/><property name="hibernate.dialect" value="${bd_dialect}"/><!-- Propiedad que muestra la query generada por Hibernate --><property name="hibernate.show_sql" value="true"/><!-- Propiedad formatea las queries generadas por Hibernate --><property name="hibernate.format_sql" value="true"/>

3.3.3. Pool de conexiones La configuración del pool de conexiones la realizaremos en el mismo fichero que el anterior. Aunque Hibernate utiliza su propia conexión de pool por defecto, vamos a configurar c3p0.

<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />

<property name="hibernate.c3p0.min_size" value="5"/><property name="hibernate.c3p0.max_size" value="20"/><property name="hibernate.c3p0.timeout" value="300"/><property name="hibernate.c3p0.max_statements" value="50"/><property name="hibernate.c3p0.idle_test_period" value="100"/><property name="hibernate.c3p0.acquire_increment" value="1"/>

Page 55: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Pool de conexiones 47

Con esto, Hibernate reconoce qué debe utilizar c3p0 en lugar de su propio pool de conexiones. C3p0 es muy configurable y ofrece gran cantidad de parámetros de configuración. Aquí tenemos una pequeña lista con los más característicos:

• min_size: indica el número mínimo de conexiones de las que dispondrá el pool en cualquier momento.

• max_size: indica el número máximo de conexiones que podrá tener el pool.

• timeout: el número de segundos que una conexión puede estar en el pool sin ser utilizada antes de ser descartada o eliminada.

• max_statements: indica el tamaño de la caché de PreparedStatements que guardará el pool. Un cero indicará que está desactivada.

• idle_test_period: si es mayor que cero, c3p0 hará una prueba en todas las conexiones que se encuentren “dormidas” en los segundos establecidos para permitir que sigan activas.

• acquire_increment: determina cuantas conexiones intentará adquirir c3p0 cuando se saturen las conexiones del pool.

3.3.4. Caché de objetosAl igual que la configuración del pool de conexiones, la caché de objetos la configu-raremos en el fichero persistence.xml. Hibernate permite utilizar varios proveedores de caché. En nuestro caso, vamos a ver cómo podemos configurar EhCache como proveedor de caché de segundo nivel.

<!-- Caché activada para todas las entidades a las que se especifique Cacheable (true) --><shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode><!-- Configuración de la caché de segundo nivel --><property name="hibernate.cache.region.factory_class"

value="org.hibernate.cache.EhCache.SingletonEhCacheRegionFactory"/><property name="hibernate.cache.use_second_level_cache" value="true"/><!-- Activar la caché para consultas--><property name="hibernate.cache.use_query_cache" value="true"/>

EhCache proporciona configuraciones por defecto, pero si queremos utilizar una propia, bastará especificar cual es el fichero que dispone de dicha configuración.

<property name="hibernate.cache.provider_configuration_file_resource_path" value="/EhCache.xml"/>

Page 56: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

48 JSF (faces-config.xml y web.xml)

3.3.5. JSF (faces-config.xml y web.xml)Para configurar JSF, tenemos que modificar el fichero web.xml que se encuentra en el directorio /src/main/webapp/WEB-INF. Bastará con registrar el servlet javaxfaces.webapp.FacesServlet y realizar el mapeo de las URLS que vamos a tratar con JSF. Para ello debemos añadir los siguiente:

<!-- Mapeo de JSF --><servlet>

<servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Mapeo de los ficheros con JSF --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>

En este caso estamos indicando que para cada pagina XHTML utilizaremos las li-brerías de JSF. Lo siguiente que debemos hacer es crear el fichero faces-config.xml y añadir en el web.xml su ubicación:

<context-param> <param-name>javax.faces.CONFIG_FILES</param-name> <param-value>/WEB-INF/classes/faces-config.xml</param-value> </context-param>

Este fichero contendrá todos los beans que harán referencia a las páginas de nues-tro proyecto, permitiendo definir la navegación entre las mismas. Aquí también configuraremos la integración de Spring con JSF para que sus contextos trabajen juntos. Para conseguir dicha integración deberemos definir SpringBeanFacesELResolver de la siguiente forma:

<application> <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>

</application>

3.3.6. Internacionalización Con la utilización de JSF es muy fácil configurar esta opción. Debemos informar a la aplicación de cuáles son los lenguajes soportados y almacenar los distintos textos en ficheros de propiedades (resource-bundles). Nuestros resource bundles

Page 57: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Internacionalización 49

(textos_es.properties y textos_en.properties) los hemos creado en la carpeta /src/main/resources/idiomas. Ahora, simplemente añadiendo unas líneas en el fiche-ro faces-config.xml, tendremos nuestra aplicación soportando diferentes idiomas.

<application><locale-config>

<default-locale>es</default-locale> <supported-locale>es</supported-locale> <supported-locale>en</supported-locale> </locale-config> <resource-bundle> <base-name>idiomas.textos</base-name> <var>msg</var> </resource-bundle>

</application>

3.3.7. Configuración de SpringAntes de nada, debemos indicar en el fichero web.xml dónde se encuentra el fichero de configuración de Spring.

<!-- Spring Context Configuration' s Path definition --><context-param>

<param-name>contextConfigLocation</param-name><param-value>/WEB-INF/classes/applicationContext.xml</param-value>

</context-param>

Una vez hecho esto, realizamos las modificaciones pertinentes para la configuración de las transacciones y del entityManagerFactory, que permitirá obtener las cone-xiones a la base de datos.

<!-- Declaración del EntityManagerFactory--><bean id="entityManagerFactory"

class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"><property name="persistenceUnitName" value="es.unirioja.tfg"/>

</bean><!--Configuración de transacciones--><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

<property name="entityManagerFactory" ref="entityManagerFactory"/></bean>

Por otra parte, habíamos comentado la posibilidad de gestionar las transacciones mediante anotaciones. Para llevar a cabo esta tarea, bastará con añadir la siguiente línea.

<!-- Activación de las anotaciones @Transactional utilizando el transactionManager definido --> <tx:annotation-driven transaction-manager="transactionManager"/>

A continuación, activaremos las inyecciones de dependencia e indicaremos los pa-

Page 58: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

50 Configuración de Spring

quetes en los que queremos que detecte las anotaciones.

<!-- Activamos la inyección de dependencia--><bean class = "org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostPro-cessor" />

<!-- Le indicamos a spring donde localizar los beans para utilizar inyección de dependencia --><context:component-scan base-package="es.unirioja.tfg" /> <context:component-scan base-package="es.unirioja.tfg.dao" /><context:component-scan base-package="es.unirioja.tfg.service" /><context:component-scan base-package="es.unirioja.tfg.jsf" />

Para finalizar, realizaremos la configuración de JMX (tecnología que define una ar-quitectura de gestión, la API, los patrones de diseño y los servicios para monitori-zación/administración de aplicaciones basadas en Java). Gracias a la monitoriza-ción, vía JMX, de la caché de objetos EhCache, podremos conocer los objetos de los que disponemos, las consultas que se han realizado, fallos de caché, etc.

<!-- Encargado de notificar cuando se crea o se destruye cualquier caché –><bean id="innerCacheManager"

class="org.springframework.cache.EhCache.EhCacheManagerFactoryBean"><property name="shared" value="true"/>

</bean>

<!-- Encargado de registrar todos los Mbeans y de gestionar e interactuar con ellos --><bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">

<property name="locateExistingServerIfPossible" value="true"/></bean>

<!-- Registro de EhCache por si mismo. No podemos indicar nosotros mismos el Bean a JMX--><bean id="EhCacheMBeanRegistration"

class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"><property name="staticMethod"

value="net.sf.EhCache.management.ManagementService.registerMBeans"/><property name="arguments">

<list><ref bean="innerCacheManager"/><ref bean="mbeanServer"/><value>true</value><value>true</value><value>true</value><value>true</value>

</list></property>

</bean>

Page 59: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Aplicación de prueba 51

4.Aplicación de pruebaA partir del arquetipo creado con Maven, y con el fin de comprobar la utilidad y funcionamiento de las distintas herramientas comentadas durante el TFG, se ha llevado a cabo el desarrollo de una pequeña aplicación de ejemplo.

Dicha aplicación nos mostrará información relacionada con una colección de libros. Podremos listar los libros almacenados en la base de datos, paginar, ordenar y fil-trar los resultados. También permitirá la modificación de algunos campos del libro. Todo esto sin olvidarnos del soporte en varios idiomas.

Con la intención de independizar la capa de persistencia de la base de datos, he utilizado el patrón DAO (Data Access Object). Dispondremos de una serie de inter-faces que proporcionan los métodos necesarios para acceder a la información de nuestras entidades y su implementación, que en este caso se basará en la utiliza-ción de JPA.

Todas nuestras entidades, como mínimo, deberían garantizar las operaciones del CRUD. Por ello se ha creado una clase abstracta que las implementa. De esta for-ma sólo deberemos realizar las implementaciones específicas de cada entidad, aho-rrándonos tiempo y esfuerzo. De una forma bastante similar (esta vez mediante la utilización de Services) se ha realizado la capa de lógica de negocio.

Dibujo 6: Comparativa entre diferentes pool de conexiones

Page 60: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

52 Aplicación de prueba

En ningún momento el objetivo de este trabajo ha sido el desarrollo de una aplica-ción web. La intención de este ejemplo es comprobar, de una forma práctica, el co-rrecto funcionamiento de las librerías y herramientas comentadas a lo largo del TFG, además de reflejar las ventajas que nos aporta la utilización del arquetipo construido.

La creación de un nuevo proyecto a partir del arquetipo, de una forma totalmente inmediata, nos permite disponer de un entorno de trabajo en el que comenzar a utilizar todas las herramientas que se han configurado tal y como hemos explicado en el capítulo anterior. A esto debemos sumar la estructura utilizada mediante los DAOS y Services, que nos permite disponer en pocos minutos de la funcionalidad relacionada con nuestras entidades Libro y Autor. Debemos tener en cuenta que se trata de una aplicación básica, donde no han sido necesarias operaciones que vayan más allá de las proporcionadas por el propio CRUD.

A falta de la creación de un interfaz y de la funcionalidad necesaria en la capa de presentación, en una tarde o como mucho en dos, podemos disponer de un ejemplo como el desarrollado. Debemos tener en cuenta los posibles problemas que siempre terminan aflorando y la necesidad de conocer el funcionamiento de cada una de las herramientas. Las operaciones del ejemplo son limitadas, pero podremos realizar consultas, modificaciones, etc., con un resultado más que satisfactorio.

Invirtiendo el tiempo necesario, tendríamos ante nosotros una aplicación totalmen-te funcional que dispusiese de éstas y otras muchas funcionalidades.

Page 61: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Conclusión 53

5.ConclusiónDurante todos estos años, en los que que he adquirido cierta experiencia y forma-ción laboral, he aprendido, sobre todo, cómo no deben hacerse las cosas. No debe-mos ver esto como algo negativo, ya que esto implica aprender a hacer las cosas de forma correcta. Bajo mi punto de vista, donde más nos podemos enriquecer, es aprendiendo de nuestros propios errores.

A la hora de hablar y elegir distintas tecnologías, he intentado ser lo más objetivo posible pero, en ningún momento, se obliga a utilizar unas tecnologías frente a otras. Debemos ser libres de escoger las que más nos aporten y ayuden en el desa-rrollo de nuestros proyectos. Nunca está de más que nos encontremos cómodos al desarrollar con dichas herramientas.

En el transcurso de este trabajo he incidido en aspectos que, bajo mi punto de vis-ta, deberíamos tener en cuenta siempre que desarrollemos aplicaciones. Por desgra-cia es imposible explicar, y mucho menos conocer, todas y cada una de ellas, por lo que he procurado referirme a las que he considerado más importantes y a aquellas con las que me encuentro más familiarizado.

No será de extrañar que, aunque encontremos soluciones que mejoren las anterio-res, sigamos teniendo la sensación de que puede hacerse mejor y pensar que al final no elegimos la mejor solución, sino la menos mala.

Desarrollar productos de calidad es una tarea bastante complicada, aunque mucho más disponer de los conocimientos suficientes en cada uno de los campos. Por lo tanto, deberemos aprender todo lo que podamos e intentar encontrar soluciones que mejoren las ya propuestas. Intentar alcanzar la perfección en nuestros produc-tos puede llegar a ser frustrante, ya que ésta no existe. Esto no quita para que in-tentemos acercarnos lo más posible.

Page 62: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software
Page 63: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

Bibliografía 55

6.Bibliografía• Gülcü, Ceki. The complete log4j manual.

http://www.qos.ch/shop/products/log4jManual.

• Van Vendeloo, Mike. Logging, which framework to choose? Log4J, Commons Logging, LogBack, SLF4J. http://mike.vanvendeloo.net/2011/05/06/logging-which-framework-to-choose-log4j-commons-logging-logback-slf4j.

• Ben Collins-Sussman, Brian W. Fitzpatrick y C. Michael Pilato. Version Control with Subversion. http://svnbook.red-bean.com/.

• Scott Chacon. Pro Git. http://git-scm.com/book/es.

• Popularidad de sistemas de control de versiones entre los usuarios de Debian. http://quepagina.es/vcs/popularidad-de-sistemas-de-control-de-versiones-entre-los-usuarios-de-debian.html.

• Maximiliano Juarez. Mi granito de java: Java cache. http://migranitodejava.blogspot.com.es/search/label/Java%20Cache.

• EhCache. Documentación. http://EhCache.org/documentation.

• Francesco Marchioni y M. Surtani. Infinispan Data Grid Platform. Packt Publishing, 2012. ISBN 978-1849518222.

• Jboss Commmunity. Infinispan Documentation. http://www.jboss.org/infinispan/documentation.

• Rafał Kuć. Apache Solr 4 Cookbook. Packt Publishing, 2003. ISBN 978-1-78216-132-5.

• Mkyong. Junit 4 Vs TestNg – Comparison. http://www.mkyong.com/unittest/junit-4-vs-testng-comparison/

Page 64: Estudio para la realización de una 'navaja suiza' para el ... · Javier Hernáez Hurtado Estudio para la realización de una 'navaja suiza' para el desarrollo de aplicaciones software

56 Bibliografía

• Cédric Beust y Hani Suleiman. Next Generation Java Testing: TestNG and Advanced Concepts.

• Petar Tahchiev, Felipe Leme, Vincent Massol, and Gary Gregory. Junit in Action. Manning Publications; 2nd Editon, 2010. ISBN 978-1935182023.

• Wikipedia. Mapeo objeto-relacional (ORM). http://es.wikipedia.org/wiki/ORM

• davidmarco.es. Introducción a JPA y Tutorial básico de Hibernate. http://www.davidmarco.es/tutoriales/

• Richard Freedman. People are still writing straight JDBC Code?. Dzone. http://java.dzone.com/news/people-are-still-writing

• Merrick Schincariol y Mike Keith. Pro JPA 2: Mastering the Java Persistence API. Apress, 2009. ISBN 978-1430219569

• WikiBooks. Java Persistence: A book relating to the Java programming language. http://en.wikibooks.org/wiki/Java_Persistence

• Craig Walls. Spring in Action, 3rd Edition. Manning, 2011. ISBN 978-1-935-18235-1.

• Dr. Mark Lui, Mario gray, Andy Chan, Josh Long. Pro Spring Integration. Apress, 2011. ISBN 978-1-4302-3345-9.

• Ed Burns y Chris Schalk. The Complete Reference JavaServer Faces 2.0. Osborne/ McGraw-Hill, 2010. ISBN 978-0071625098

• Srirangan. Apache Maven 3.0 Cookbook. Packt Publishing, 2011. ISBN 978-1849512442.

• Apache. Maven documentation. http://maven.apache.org/guides/

• cemicursoj2ee. Apache Maven 2. http://code.google.com/p/cemicursoj2ee/wiki/ApacheMaven2