0% encontró este documento útil (0 votos)
185 vistas405 páginas

ArquitecturaJava1 0optimizado

Este documento trata sobre la arquitectura Java sólida. Explica conceptos básicos de Java como JSP, el principio DRY y el manejo de excepciones. También cubre temas como la creación de formularios, validaciones, el uso de clases y métodos para evitar duplicación de código.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
185 vistas405 páginas

ArquitecturaJava1 0optimizado

Este documento trata sobre la arquitectura Java sólida. Explica conceptos básicos de Java como JSP, el principio DRY y el manejo de excepciones. También cubre temas como la creación de formularios, validaciones, el uso de clases y métodos para evitar duplicación de código.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 405

!

! !
!
Arquitectura*Java!

!
!
!
!
ARQUITECTURA)JAVA)SLIDA!
Cecilio'lvarez'Caules!

!
!
!
!

2
www.arquitecturajava.com!

!
!
!
!
!

2012 Cecilio lvarez Caules. Todos los derechos reservados.

ISBN : 978-1-291-16766-5

3
Arquitectura*Java!

Agradecimientos!
Este! libro! esta! dedicado! a! la! comunidad! de! desarrolladores! ! JEE! de! Cantabria! puesto!
que! muchos! de! los! captulos! se! basan! en! reflexiones! fundamentadas! en! las! distintas!
preguntas!que!se!me!han!formulado!estos!aos!en!los!cursos!y!consultoras!realizados!
para! su! entorno.! Dichas! aportaciones! me! han! proporcionado! un! animo! esencial! para!
escribir!este!!libro.!

Agradezco! al! grupo! de! arquitectura! JEE! del! gobierno! de! Cantabria! las! distintas!
colaboraciones! en! las! que! hemos! tomado! parte! estos! aos,! ya! que! el! presente! libro!
recoge!un!cmulo!de!!ideas!extradas!directamente!de!stas.!!

Agradezco,! igualmente,! al! equipo! humano! de! Consultec! los! distintos! proyectos! en! los!
que!he!participado!estos!ltimos!aos!:!me!han!hecho!crecer!como!arquitecto!y!me!han!
ayudado! a! obtener! una! visin! ms! neutral! a! nivel! tecnolgico! sobre! las! distintas!
plataformas!y!frameworks!existentes.!

Mi! agradecimiento! va! tambin! para! ! las! aportaciones! de! las! personas! con! las! que!
trabaj!mis!primeros!aos!de!profesional!en!Mundivia.!Esta!etapa!me!ayud!a!!adquirir!
la!visin!necesaria!sobre!la!orientacin!de!mi!futuro!perfil!profesional,!algo!que!con!el!
paso!del!tiempo!ha!sido!clave!en!la!evolucin!de!mi!carrera.!

Gracias,!as!mismo,!!a!!Jess!Martn!Fernndez!y!a!Miguel!Blanchard!Rodrguez!por!las!
distintas! charlas! e! intercambios! de! ideas! que! hemos! tenido! estos! aos! sobre! JEE! ,!
adems!de!los!enfoques!!y!distintas!visiones!que!me!han!venido!aportado.!

Agradecer! a! Jose! Manuel! San! Emeterio! Perez! de! Emcanta! los! distintos! procesos! de!
certificacin! en! los! que! participamos! ambos! ,que! me! permitieron! definir! el! punto! de!
partida!de!los!contenidos!del!libro.!

Es! tambin! necesario! agradecer! a! Jordi! lvarez! Caules! y! a! Ana! Patricia! Fernndez! del!
Llano!!la!revisin!del!documento!y!las!ideas!!objetivas!y!sinceras!que!me!transmitieron!
sobre!cmo!mejorar!el!contenido.!

Agraceder!a!Olga!Pelaez!Tapia!la!revisin!completa!del!documento!a!nivel!de!claridad!
de!contenidos!.Ya!que!sin!ella!tengo!claro!que!muchas!ideas!no!habran!quedado!claras.!

Por!ltimo,!agradezco!!a!mis!padres!la!educacin!en!la!cultura!del!conocimiento!que!me!
han!proporcionado,!!ya!que!sin!ella!no!me!hubiera!convertido!en!arquitecto.!

4
www.arquitecturajava.com!

ARQUITECTURA!JAVA!SLIDA!.......................................................................................!2!

Cecilio!lvarez!Caules!.......................................................................................................!2!

Agradecimientos!.................................................................................................................!4!

Introduccin!.....................................................................................................................!14!

1.! Conocimientos!previos!..........................................................................................!14!

2.! Requerimientos!de!software!...............................................................................!15!

3.! Instalacin!del!entorno!.........................................................................................!15!

4.! Configuracin!del!entorno!...................................................................................!16!

Resumen!.............................................................................................................................!20!

1.HTML!................................................................................................................................!22!

1.! Construir!un!formulario!HTML!..........................................................................!23!

2.! Validaciones!de!JavaScript!...................................................................................!24!

3.! Aadir!formato!........................................................................................................!25!

4.! Uso!correcto!de!etiquetas!.....................................................................................!26!

5.! Accesibilidad!de!la!pagina!....................................................................................!27!

6.! Uso!de!XHTML!como!estndar.!...........................................................................!27!

7.! Uso!de!estndares!DOM!........................................................................................!28!

8.! Uso!de!JavaScript!Degradable!.............................................................................!30!

Resumen!.............................................................................................................................!32!

2.Java!Server!Pages!.......................................................................................................!34!

5
Arquitectura*Java!

1.! Creacin!de!una!tabla!Libros!...............................................................................!34!

2.! Instalar!el!driver!JDBC.!..........................................................................................!35!

3.! Creacin!de!la!pgina!!InsertarLibro.jsp!......................................................!36!

4.! Creacin!de!la!pagina!MostrarLibros.jsp!.........................................................!38!

Resumen!.............................................................................................................................!42!

3.DRY!y!JSP!.........................................................................................................................!44!

1.! Aadir!nueva!clase!..................................................................................................!45!

2.! Modificar!paginas!JSP!.............................................................................................!48!

3.! Aadir!Filtro!por!categora!..................................................................................!50!

4.! El!principio!DRY!y!las!consultas!SQL!.................................................................!52!

5.! El!principio!DRY!mtodos!y!parametros!.........................................................!55!

6.! ResultSets!vs!Listas!de!objetos!............................................................................!57!

7.! Uso!de!interfaces!a!nivel!de!Libro!......................................................................!59!

8.! Cierre!de!conexiones!y!reflection.!......................................................................!61!

4.Editar,!Borrar!y!Filtrar!...............................................................................................!66!

1.! Aadir!enlace!de!borrar!........................................................................................!67!

2.! Aadir!mtodo!borrar!............................................................................................!67!

3.! Aadir!pgina!BorrarLibro.jsp!............................................................................!68!

4.! Aadir!link!Edicin!.................................................................................................!69!

5.! Mtodo!de!bsqueda!por!clave!...........................................................................!70!

6.! Aadir!formulario!de!edicin!de!cdigo.!.........................................................!70!

7.! Aadir!mtodo!salvar!.............................................................................................!73!

6
www.arquitecturajava.com!

8.! Aadir!pagina!SalvarLibro.jsp!............................................................................!73!

9.! Aadir!mtodo!buscarPorCategoria.!................................................................!75!

Resumen!.............................................................................................................................!80!

5.Manejo!de!excepciones!..............................................................................................!82!

1.! Flujo!de!!excepciones!y!clausulas!catch!...........................................................!83!

2.! Manejo!de!las!clasulas!throw,!throws!y!flujo!de!excepciones.!...............!84!

3.! Creacin!y!conversin!de!excepciones!............................................................!86!

4.! Excepciones!anidadas!............................................................................................!90!

5.! Excepciones!RunTime!...........................................................................................!92!

6.! Crear!Pagina!de!Error!............................................................................................!94!

7.! Modificar!fichero!web.xml!...................................................................................!96!

Resumen!.............................................................................................................................!97!

6.Log4J!.................................................................................................................................!98!

1.! Instalacin!de!log4j!................................................................................................!99!

2.! Introduccin!a!log4j!.............................................................................................!100!

3.! Construccin!de!un!ejemplo!sencillo!..............................................................!101!

4.! Mensajes!de!error!y!niveles.!..............................................................................!104!

5.! Manejo!de!Log4j.properties!...............................................................................!107!

6.! Uso!de!log4j!en!nuestra!aplicacin.!.................................................................!109!

Resumen!...........................................................................................................................!111!

7.El!principio!SRP!y!el!modelo!MVC!........................................................................!112!

1.! Responsabilidades!de!la!aplicacin!y!el!principio!SRP!............................!113!

7
Arquitectura*Java!

2.! Construir!un!servlet!controlador!....................................................................!116!

3.! Mapeo!de!Servlet!...................................................................................................!117!

4.! Insercin!con!modelo!MVC!................................................................................!121!

5.! Borrar!en!modelo!MVC!........................................................................................!123!

6.! Editar!en!modelo!MVC!.........................................................................................!125!

7.! Filtrado!en!Modelo!MVC!.....................................................................................!127!

Resumen!..........................................................................................................................!131!

8.JSTL!................................................................................................................................!132!

1.! Instalacin!de!JSTL!...............................................................................................!133!

2.! Introduccin!a!JSTL!..............................................................................................!133!

3.! Etiquetas!Bsicas!JSTL!........................................................................................!134!

4.! Modificar!MostrarLibro.jsp!...............................................................................!135!

5.! Modificar!Formulario!Insertar!.........................................................................!136!

6.! Modificar!FormularioEditarLibro.jsp!............................................................!137!

Resumen!..........................................................................................................................!137!

9.El!principio!OCP!y!modelo!MVC!2!.........................................................................!138!

1.! El!principio!OCP!y!el!Controlador!....................................................................!139!

2.! El!principio!OCP!y!el!patrn!Command!.........................................................!140!

3.! Creacin!de!una!accin!principal!....................................................................!142!

4.! Crear!jerarqua!de!acciones!..............................................................................!143!

5.! Api!de!reflection!y!el!principio!OCP!................................................................!147!

Resumen!..........................................................................................................................!150!

8
www.arquitecturajava.com!

10.Hibernate!...................................................................................................................!152!

1.! Introducion!al!concepto!de!framework!de!persistencia!..........................!153!

2.! Instalacin!de!Hibernate!....................................................................................!154!

3.! Introduccin!a!Hibernate!...................................................................................!155!

4.! Configuracin!Hibernate!....................................................................................!158!

5.! Insertar!Libro!con!Hibernate!............................................................................!161!

6.! Seleccionar!Objetos!con!Hibernate!.................................................................!164!

7.! Seleccionar!un!nico!Objeto!..............................................................................!165!

8.! Borrar!un!objeto!....................................................................................................!166!

9.! Filtrar!objetos!con!Hibernate!...........................................................................!167!

10.! Migrar!nuestra!aplicacin!a!Hibernate!.......................................................!168!

11.! Hibernate!y!Convencin!sobre!Configuracin.!.........................................!172!

12.! DRY!e!Hibernate!..................................................................................................!174!

11.Hibernate!y!Relaciones!.........................................................................................!180!

1.! Construir!la!clase!categora!y!mapearla!........................................................!182!

2.! Modificar!la!!Capa!de!presentacin!y!soportar!la!clase!Categora!........!184!

3.! Creacin!de!relaciones!entre!clases!................................................................!186!

4.! Relaciones!y!persistencia!con!Hibernate!......................................................!188!

5.! Relaciones!y!capa!de!presentacin!.................................................................!194!

Resumen!...........................................................................................................................!197!

12.Java!Persistence!API!...............................................................................................!198!

1.! Introduccin!al!API!de!JPA!.................................................................................!200!

9
Arquitectura*Java!

2.! Migracin!de!Aplicacin!a!JPA!..........................................................................!204!

3.! Manejo!de!Excepciones!.......................................................................................!207!

Resumen!..........................................................................................................................!208!

13.El!principio!ISP!y!el!patrn!DAO!........................................................................!210!

Objetivos!:!........................................................................................................................!213!

1.! Crear!las!clases!LibroDAO!y!CategoriaDAO.!.................................................!213!

2.! Uso!de!interfaces!en!componentes!DAO!.......................................................!218!

3.! El!principio!DRY!y!!el!patrn!GenericDAO!....................................................!221!

4.! Rendimiento!...........................................................................................................!228!

Resumen!..........................................................................................................................!228!

14.El!principio!de!inversin!de!control!y!patrn!factory!................................!230!

1.! Crear!Factoras!e!implementar!el!principio!de!IOC,!..................................!232!

2.! El!principio!DRY!y!el!patrn!Abstract!Factory!............................................!237!

Resumen!..........................................................................................................................!243!

15.El!Principio!DRY!y!el!patrn!servicio!...............................................................!244!

1.! El!principio!DRY!y!el!acceso!a!la!capa!de!persistencia!.............................!245!

2.! Creacin!de!una!clase!de!Servicio!...................................................................!247!

Resumen!..........................................................................................................................!251!

16.El!principio!IOCy!el!framework!Spring!............................................................!252!

1.! Creacin!de!ejemplo!de!factorias!....................................................................!255!

2.! Instalacin!de!Spring!...........................................................................................!261!

3.! Instalacin!de!Spring!en!nuestra!aplicacin.!..............................................!266!

10
www.arquitecturajava.com!

Resumen!...........................................................................................................................!269!

17.Inyeccion!de!Dependencia!!y!Spring!framework!..........................................!270!

1.! Introduccin!al!!principio!de!Inyeccin!de!Dependencia!........................!275!

2.! Spring!e!inyeccin!de!dependencia.!................................................................!280!

3.! Spring!y!factora!para!aplicaciones!web!.......................................................!283!

4.! Spring!inyeccin!de!dependencia!y!Capas!DAO!..........................................!283!

Resumen!...........................................................................................................................!287!

18.El!principio!DRY!y!Spring!Templates!................................................................!288!

1.! El!patrn!Template!...............................................................................................!290!

2.! Spring!y!plantillas.!................................................................................................!297!

3.! Spring!Herencia!Plantillas!y!JDADAOSupport!.............................................!302!

Resumen!...........................................................................................................................!304!

19.Programacin!Orientada!a!Aspecto!(AOP)!.....................................................!306!

1.! Introduccin!a!AOP!...............................................................................................!308!

2.! Usando!Proxies!con!Spring!................................................................................!314!

3.! Configuracin!de!proxies!y!transacciones.!...................................................!319!

Resumen!...........................................................................................................................!326!

20.Uso!de!anotaciones!y!COC!.....................................................................................!328!

1.! @PersistenceContext!y!EntityManager!.........................................................!329!

2.! @Repository!y!manejo!de!excepciones!.........................................................!332!

3.! Anotacin!@Service!.............................................................................................!333!

4.! Anotaciones!@AutoWired!..................................................................................!334!

11
Arquitectura*Java!

Resumen!..........................................................................................................................!337!

21.Java!Server!faces!.....................................................................................................!338!

1.! Introduccin!a!JSF!.................................................................................................!339!

2.! Instalacin!de!JSF!..................................................................................................!340!

3.! Hola!Mundo!con!JSF!..............................................................................................!342!

4.! Construir!un!combo!con!JSF!..............................................................................!346!

5.! Crear!Tabla!con!JSF!..............................................................................................!350!

Resumen!..........................................................................................................................!352!

21.Migracin!a!Java!Server!Faces!............................................................................!354!

1.! Aadir!controlador!de!JSF!y!eliminar!el!existente!....................................!355!

2.! Creacin!ManagedBean!......................................................................................!358!

3.! Crear!MostrarLibro.xhtml!.................................................................................!362!

4.! Borrar!Libro!...........................................................................................................!365!

5.! Insercin!Libro!......................................................................................................!366!

6.! Funcionalidad!de!Edicin!...................................................................................!368!

7.! Filtrar!por!categorias!..........................................................................................!371!

8.! Mejoras!Expression!Language!2.0!...................................................................!372!

9.! Integracin!de!Spring!..........................................................................................!374!

10.! JSF!2!y!Business!Objects!...................................................................................!375!

Resumen!..........................................................................................................................!375!

23.Servicios!Web!y!JAXlWS!........................................................................................!376!

1.! Introduccin!!a!programacin!distribuida!..................................................!376!

12
www.arquitecturajava.com!

2.! Introduccin!a!Servicios!Web!...........................................................................!380!

3.! Servicio!Web!...........................................................................................................!382!

4.! Publicacin!del!servicio!web.!............................................................................!387!

5.! Instalacin!de!Apache!CXF!.................................................................................!387!

6.! Configuracin!del!framework!...........................................................................!388!

Resumen!...........................................................................................................................!391!

24.Administracin!y!pools!.........................................................................................!392!

1.! El!framework!Spring!y!Pools!.............................................................................!393!

2.! Pool!de!conexiones!y!Tomcat!............................................................................!394!

3.! Configuracin!de!Spring!va!JNDI.!....................................................................!396!

Resumen!...........................................................................................................................!399!

25.Conclusiones!.............................................................................................................!400!

Que!es!lo!mas!importante?!.......................................................................................!400!

1.! JEE!un!ecosistema!.................................................................................................!402!

Resumen!...........................................................................................................................!403!

Bibliografa!......................................................................................................................!404!

!
!
!

!
13
Arquitectura*Java!

Introduccin!
!
!
!
!
La! idea! original! de! escribir! este! libro! viene! de! las! distintas! formaciones! y! consultoras!
sobre! JEE! que! he! realizado! en! los! ltimos! aos.! En! la! plataforma! JEE! existen! muchos!
libros!que!tratan!sobre!EJBs,!JPA,!Spring!etc.!Pero!casi!siempre!estos!libros!se!centran!
en!un!nico!producto.!As!pues,!para!muchas!personas!resulta!realmente!difcil!adquirir!
una!visin!global!de!cmo!estos!productos!se!integran!unos!con!otros!y!conforman!una!
solucin! empresarial.! El! objetivo! de! este! libro! no! trata! de! hacernos! expertos! en!
Hibernate! o! en! Spring! sino! de! ser! capaces! de! comenzar! a! manejar! cada! uno! de! estos!
frameworks! y! adquirir! una! visin! global! como! arquitectos! de! cmo! construir! una!
aplicacin! empresarial! .Para! ello! vamos! ! a! construir! desde! cero! una! aplicacin! JEE!
pequea! que! ir! evolucionando! segn! vayamos! avanzando! captulos! y! se! apoyar! en!
los! distintos! frameworks! o! estndares! existentes! a! la! hora! de! abordar! las! distintas!
problemticas.!

!
1. Conocimientos!previos!

Para!poder!abordar!los!conceptos!que!se!explican!en!este!libro!no!ser!necesario!tener!
unos! conocimientos! amplios! de! la! plataforma! Java! y! de! JEE! .Ahora! bien,! s! es!
recomendable! conocer! un! mnimo! del! lenguaje! Java,! as! como! unos! mnimos! de! JEE!
,concretamente! los! conceptos! de! Servlet! y! JSP.! Por! ltimo,! sern! necesarios!
conocimientos!sobre!el!lenguaje!HTML.!

14
www.arquitecturajava.com!

2. Requerimientos!de!software!

Una! vez! que! tenemos! claros! los! conocimientos! necesarios! para! abordar! con! garantas!
los! distintos! captulos,! vamos! a! listar! el! software! que! utilizaremos! a! la! hora! de! crear!
nuestra!aplicacin.!

Open!JDK!1.6!o!JDK!1.6!
FireFox!
Web!Developer!
Eclipse!JEE!
Tomcat!7!
MySQL!
Ubuntu!10.10!o!Windows!7!

3. Instalacin!del!entorno!

Antes! de! comenzar! a! desarrollar! nuestra! aplicacin! debemos! abordar! una! serie! de!
pasos!previos!relativos!a!la!instalacin.!

Instalacin!JDK!1.6:!En!este!caso!simplemente!nos!bajamos!el!jdk!1.6!para!Windows!o!
bien!lo!instalamos!desde!el!gestor!de!paquetes!synaptic!en!caso!de!usar!Ubuntu!(open!
jdk).!

Firefox! y! WebDeveloper! :! No! hay! mucho! que! decir! en! esta! seccin! simplemente!
obtendremos! el! navegador,! lo! instalamos! y! aadimos! el! plugin! de! web! developer!
correspondiente.!

Eclipse!JEE!:!Obtendremos!el!entorno!de!desarrollo!eclipse!y!lo!descomprimimos!en!un!
directorio! cualquiera! ya! que,! al! estar! desarrollado! en! java! y! tener! instalado! el! jdk!
,simplemente!con!pulsar!sobre!su!icono!el!entorno!se!lanzara!sin!mayores!necesidades!
de!instalacin.!!

Tomcat! ! 7:! Obtendremos! ! el! servidor! web! Tomcat! de! la! pagina! de! apache! y! lo!
descomprimimos!en!un!directorio!paralelo!al!que!tenemos!ubicado!eclipse!JEE!

MySQL:!Bajamos!el!instalador!e!instalamos!el!servidor!de!MySQL!!con!las!opciones!por!
defecto!.Aadimos!las!GUI!Tools!o!el!MySQL!Workbench!para!una!gestin!ms!sencilla!
del!servidor!.En!Ubuntu!podemos!instalar!MySQL!y!sus!herramientas!grficas!a!travs!
de!Synactic.!

15
Arquitectura*Java!

4. Configuracin!del!entorno!

Hemos! instalado! ya! todo! el! software! que! necesitamos! y! acabamos! de! abrir! el! eclipse!
(ver!imagen)!

Es!momento!de!integrar!Eclipse!JEE!con!Tomcat!7.!Esto!puede!realizarse!de!una!forma!
muy! sencilla! en! la! pestaa! de! servers,! pulsando! botn! derecho! New>Server! (ver!
imagen)!

Al! pulsar! esta! opcin! pasaremos! a! elegir! el! tipo! de! servidor! que! deseamos! aadir! a!
nuestro!entorno!de!desarrollo!(Tomcat!7)!(ver!imagen).!

16
www.arquitecturajava.com!

Elegido! el! tipo! de! servidor,! nos! solicitar! que! especifiquemos! en! qu! directorio! se!
encuentra!instalado!(ver!imagen).!

17
Arquitectura*Java!

Seleccionamos!el!directorio!y!podemos!pulsar!Finish!.!En!la!pestaa!de!servidores!nos!
aparecer!el!nuevo!servidor!para!que!podamos!utilizarlo.!

Configurado!el!servidor!,!vamos!a!proceder!a!construir!nuestra!primera!aplicacin!web!
y! desplegarla! en! dicho! servidor.! Para! ello! usaremos! el! men! de! File>New>Dynamic!
Web!Project!y!crearemos!un!nuevo!proyecto!web!(ver!imagen)!.!

18
www.arquitecturajava.com!

Una!vez!que!hayamos!elegido!el!tipo!de!proyecto,!eclipse!nos!solicitar!que!lo!alojemos!
en! alguno! de! los! servidores! que! tenemos! definidos.! En! nuestro! caso! Tomcat! 7! (ver!
imagen)!

! !

Tras! realizar! estas! operaciones,! dispondremos! en! eclipse! de! un! nuevo! proyecto! web!
sobre! JEE! con! el! que! podremos! comenzar! a! construir! nuestra! aplicacin! como! se!
muestra!seguidamente.!

19
Arquitectura*Java!

Resumen!
Este!captulo!ha!servido!para!introducir!los!objetivos!del!libro!as!como!para!configurar!
el! entorno! de! desarrollo! que! vamos! a! utilizar! en! captulos! posteriores.! En! el! prximo!
captulo!comenzaremos!con!el!desarrollo!de!!la!aplicacin.!

20
www.arquitecturajava.com!

21
Arquitectura*Java!

1.HTML!
!
!
!
!
En!este!captulo!vamos!a!comenzar!a!construir!una!pequea!aplicacin!web!sobre!JEE!
que! nos! ayudar! a! gestionar! una! coleccin! de! libros.! La! aplicacin! se! encargar! de!
aadir,!borrar!y!modificar!los!distintos!libros!que!tenemos!e!ir!!evolucionando!durante!
el! transcurso! de! los! distintos! captulos! segn! se! vayan! abordando! las! distintas!
tecnologas!de!la!plataforma!JEE.!

Comenzaremos! entonces! por! la! parte! ms! sencilla:! la! construccin! de! un! formulario!
HTML!a!travs!del!cul!insertaremos!la!informacin!del!libro!que!deseamos!guardar!en!
la!aplicacin.!

Objetivo:!!

Crear! un! formulario! HTML! que! nos! permita! dar! de! alta! nuevos! libros! en! la!
aplicacin.!
Tareas:!

1. Construir!un!formulario!HTML!que!contenga!los!campos!necesarios!para!dar!de!
alta!un!nuevo!libro!(ISBN,!titulo,!categora).!
2. Construccin!de!las!validaciones!de!JavaScript!que!el!formulario!necesita!para!
poder!gestionar!la!informacin.!
3. Aplicar!formato!al!formulario!utilizando!una!hoja!de!estilo!CSS.!
4. Revisin!del!uso!correcto!de!etiquetas!HTML!!en!el!formulario.!
5. Uso!de!etiquetas!de!accesibilidad!en!el!formulario.!
6. Uso!de!XHTML!como!estndar!en!el!formulario.!
7. Uso!de!DOM!como!estndar!a!nivel!de!JavaScript.!
8. Uso!de!JavaScript!degradable!en!el!formulario.!
!

22
www.arquitecturajava.com!

Acabamos! de! definir! el! conjunto! de! tareas! a! realizar! .Quiz! en! este! momento! no!
tengamos!claras!todas!ellas!pero!se!irn!clarificando!segn!las!vayamos!abordando.!!

1. Construir!un!formulario!HTML!

La! primera! tarea! que! debemos! llevar! a! cabo! es! ! sencilla! y! se! trata! de! construir! un!
formulario!HTML!para!dar!de!alta!nuevos!libros!.Para!ello!vamos!a!definir!el!conjunto!
inicial!de!campos!que!va!a!contener!.!

Campos:!

ISBN!
Titulo!
Categora!

Una! ! vez! definidos! los! campos,! es! momento! de! construir! el! formulario! utilizando!
etiquetas!HTML!(ver!imagen)!

Cdigo!1.1:!(FormularioLibro01Inicio.html)!

<html>
<head>
<title>Formulario Libro</title>
</head>
<body>
<h1>Formulario alta Libro</h1>
<form>
ISBN:
<input type="text" name="isbn"><br>
Titulo:
<input type="text" name="titulo"><br>
Categoria:
<input type="text" name="categoria"><br>
<input type="button" value="Insertar" >
</form>
</body>
</html>
!

Nuestra! primera! versin! del! formulario! es! realmente! sencilla,! ! como! se! muestra! (ver!
imagen).!

23
Arquitectura*Java!

El!formulario!se!encuentra!ubicado!dentro!de!un!proyecto!web!de!eclipse!!(ver!imagen)!

2. Validaciones!de!JavaScript!

El! objetivo! de! este! libro! es! ayudarnos! a! tomar! buenas! decisiones! orientadas! a! la!
arquitectura,! las! validaciones! que! vamos! a! usar! en! el! formulario! sern! sencillas! y! en!
este!caso!nicamente!nos!encargaremos!de!validar!si!el!ISBN!esta!vaco.!Vamos!a!ver!a!
continuacin!el!cdigo!de!JavaScript!que!se!encarga!de!esta!funcionalidad!dentro!de!la!
pgina.!

24
www.arquitecturajava.com!

Cdigo!1.2:!(FormularioLibro02JavaScript.html)!

<html>
<head>
<script type="text/javascript">
function validacion() {
if (document.forms[0].isbn.value == "")
alert("datos no validos");
else
document.forms[0].submit();
}
</script>
<title>Formulario Libro</title>
</head>
<body>
<h1>Formulario alta Libro</h1>
<form>
ISBN:
<input type="text" name="isbn"><br>
Titulo:
<input type="text" name="titulo"><br>
Categoria:
<input type="text" name="categoria"><br>
<input type="button" value="Insertar" onclick="validacion()">
</form>
</body>
</html>
!

Hemos!aadido!una!funcin!de!validacin!y!un!evento!onclick!al!formulario,!el!cul!a!
partir!de!este!momento!obliga!a!que!introduzcamos!el!ISBN!.!

3. Aadir!formato!

Para! aadir! formato! a! nuestro! formulario! usaremos! una! hoja! de! estilo! mnima! que!!
simplemente!presentar!el!texto!del!formulario!en!negrita!(ver!imagen)!

Cdigo1.3!:(FormularioLibro03CSS.html)!

<style type="text/css">
font-weigth:bold;
</style>
!

25
Arquitectura*Java!

4. Uso!correcto!de!etiquetas!

Es!frecuente!encontrarmos!con!situaciones!en! las!que,!aunque!se!usa!una!tecnologa,!
sta!no!se!conoce!en!profundidad!.ste!es!el!caso!de!la!pgina!!que!acabamos!de!crear,!
ya! que! usamos! una! etiqueta! <h1>! de! cabecera! para! asignar! un! ttulo! al! formulario! y!
etiquetas! <br>! para! separar! el! contenido,! algo! que! no! es! correcto,! ya! que! existen!
etiquetas! ms! especificas! que! pueden! realizar! estas! tareas.! Tales! etiquetas! son,! en!
concreto:!

<field></field>y!<legend></legend>!:Etiquetas!encargadas!de!agrupar!un!conjunto!de!
campos!de!un!formulario!y!asignar!a!este!un!titulo!o!leyenda.!

<p></p>:Etiqueta!que!se!encarga!de!definir!un!prrafo!

As!pues,!es!preciso!modificar!las!etiquetas!de!nuestro!formulario!de!la!siguiente!forma.!

Cdigo1.4:!(FormularioLibro04UsoEtiquetas.html)!

<form action="insertarLibro.jsp">
<fieldset>
<legend>Formulario alta libro</legend>
<p>ISBN:
<input type="text" name="isbn">
</p>
<p>
Titulo:
<input type="text" name="titulo">
</p>
<p>
Categora:
<input type="text" name="categoria">
</p>
<p>
<input type="button" value="Insertar" onclick="validacion()">
</p>
</fieldset>
</form>
!

Como! podemos! observar,! no! solo! hemos! aadido! las! nuevas! etiquetas! sino! que!
tambin!hemos!eliminado!las!que!no!eran!correctas!<h1>.!

26
www.arquitecturajava.com!

5. Accesibilidad!de!la!pagina!

En! estos! momentos! ! nuestra! pagina! HTML! carece! de! las! etiquetas! habituales! de!
accesibilidad,! como! por! ejemplo! la! etiqueta! <label>,! las! cules! definidas! en! el!
formulario!!permiten!una!mejor!accesibilidad!a!usuarios!discapacitados.!Para!solventar!
este!problema!vamos!a!aadirlas!a!nuestro!cdigo!(ver!cdigo).!

Cdigo!1.5:!(FormularioLibro05Accesibilidad.html)!

<fieldset>
<legend>Formulario alta libro</legend>
<p><label for="isbn">ISBN:</label>
<input type="text" name="isbn"/>
</p>
<p>
<label for="titulo">Titulo:</label>
<input type="text" name= "titulo"/>
</p>
<p>
<label for="categoria">Categoria :</label>
<input type="text" name="categoria"/>
</p>
<p>
<input type="button" value="Insertar" onclick="validacion()">
</p>
</fieldset>
!

Despus! de! aadir! estas! etiquetas,! podemos! pasar! a! las! siguientes! tareas! encargadas!
de!mejorar!el!uso!de!estndares!a!nivel!de!HTML.!

6. Uso!de!XHTML!como!estndar.!

XHTML!es!hoy!por!hoy!el!estndar!que!se!utiliza!a!la!hora!de!construir!paginas!HTML!,!
en! espera! de! que! HTML! 5! se! imponga! en! el! mercado.! Para! conseguir! que! nuestra!
pagina! web! cumpla! con! los! requerimientos! de! XHTML,! necesitamos! realizar! las!
siguientes!modificaciones!!a!nuestra!pgina.!

1. Aadir!declaracin!XML!al!documento!!
2. Aadir!DOCTYPE!al!documento!
3. Aadir!espacio!de!nombres!(xml!namespace)!
4. Todas!las!etiquetas!deben!ser!declaradas!en!minsculas!
5. Toda!etiqueta!abierta!debe!ser!cerrada!
!

27
Arquitectura*Java!

Aunque! en! principio! parecen! bastantes! cambios,! son! rpidos! de! aplicar.! Vamos! a! ver!
como!queda!modificado!nuestro!cdigo!para!cumplir!con!XHTML.!

Cdigo!1.6:!(FormularioLibro06XHTML.html)!

1
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
"DTD/xhtml1-strict.dtd">
3
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<!omitimos JavaScript y cabecera-->
<title>Ejemplo01</title>
</head>
<body>
<form >
<fieldset>
<legend>Formulario alta libro</legend>
<!Omitimos etiquetas que no varan!
<p>
<input type="button" value="Insertar" onclick="validacion()"/>
</p>
</fieldset></form>
</body>
</html>
!

Hemos! aadido! una! serie! de! cabeceras! al! documento! que! permiten! validar! el!
formulario! como! XHTML! y! nos! hemos! encargado! tambin! de! abrir! y! cerrar!
correctamente!las!etiquetas!HTML.!En!estos!momentos!podemos!!nuestro!documento!
cumple! los! estndares! algo! que! podemos! comprobar! si! utilizamos! la! herramienta!
WebDeveloper!de!Firefox!como!muestra!la!siguiente!imagen.!

7. Uso!de!estndares!DOM!

DOM!o!Document!Object!Model!!es!el!estndar!que!usan!todos!los!!navegadores!!para!
representar!en!memoria!la!pagina!como!una!serie!de!nodos!enlazados!entre!s!en!forma!
de!rbol!(ver!imagen).!
28
www.arquitecturajava.com!

DOM! es! usado! por! JavaScript! para! acceder! a! los! distintos! elementos! de! la! pgina.! En!
nuestro!caso,!el!uso!de!DOM!afecta!a!la!funcin!de!validacin!que!hemos!construido!en!
JavaScript.! Para! facilitar! y! estandarizar! el! uso! de! DOM! en! nuestra! pgina,!
modificaremos!algunas!de!las!etiquetas!de!nuestro!formulario!HTML!y!les!aadiremos!
atributos!de!!identificador!idcomo!muestra!el!siguiente!bloque!de!cdigo.!

Cdigo!1.7:!(FormularioLibro07DOM.html)!

<p><label for="isbn">ISBN:</label>
<input id="isbn" type="text" name="isbn"/></p>
<p>
<label for="titulo">Titulo:</label>
<input id="titulo" type="text" name= "titulo"/>
</p><p>
<label for="categoria">Categoria :</label>
<input id="categoria" type="text" name="categoria"/>
</p>
!

Una!vez!realizados!estos!cambios!a!nivel!de!estructura!HTML,!podremos!usar!el!API!de!
DOM!de!JavaScript!para!acceder!de!una!forma!ms!directa!a!los!distintos!elementos!de!
la!pagina!.En!este!caso,!haremos!uso!de!la!siguiente!instruccin.!

Cdigo!1!8:!(FormularioLibro07DOM.html)!

document.getElementById(identificador);
!

29
Arquitectura*Java!

Dicha! instruccin! sirve! para! acceder! a! un! elemento! determinado! del! documento! a!
travs! de! ! su! identificador! ;! de! esta! forma,! la! funcin! de! JavaScript! pasar! a! tener! la!
siguiente!estructura.!

Cdigo1.9:!(FormularioLibro08JavaScriptDOM.html)!

function validacion() {
var isbn= document.getElementById("isbn");
var miformulario=document.getElementById("miformulario");
if(isbn.value==""){
alert("datos no validos");
return false;
}else{
miformulario.submit();
}
}
</script>
!

El! uso! de! DOM! a! nivel! de! JavaScript! visiblemente! nos! permite! ganar! en! claridad! y!
sencillez!a!la!hora!de!construir!nuestras!funciones!de!validacin.!Llegados!a!este!punto,!
hemos!terminado!de!definir!las!tareas!asociadas!al!!uso!de!estndares.!La!ltima!tarea!
pendiente!est!orientada!a!mejorar!el!propio!funcionamiento!de!la!pgina!en!el!caso!de!
que!el!navegador!no!soporte!JavaScript!(usuarios!con!discapacidad).!

8. Uso!de!JavaScript!Degradable!

Es! el! momento! de! ver! cmo! nuestro! formulario! se! comporta! en! situaciones! adversas!
como! puede! ser! el! caso! de! que! el! navegador! no! disponga! de! JavaScript.! Para! simular!
esta! situacin,! usaremos! el! plugin! WebDeveloper! que! permite! deshabilitar! el!
JavaScript! de! una! pgina! en! concreto! .! La! siguiente! imagen! muestra! deshabilitar!
JavaScript!usando!esta!herramienta.!

30
www.arquitecturajava.com!

Tras!deshabilitar!el!JavaScript,!nos!podemos!dar!!cuenta!de!que!el!botn!del!formulario!
ha! dejado! de! funcionar.! Esto! se! debe! a! que! nuestro! formulario! no! ha! sido! diseado!
para!soportar!una!degradacin!correcta!de!JavaScript!y!deja!de!funcionar!en!ausencia!
de! ste.! Para! conseguir! que! el! formulario! se! degrade! ! ! es! necesario! realizar! dos!
modificaciones.!

1. Cambiar!el!tipo!de!botn!que!estamos!usando!por!tipo!submit.!
2. Cambiar! el! evento! de! tipo! onclick! a! tipo! onsubmit! y! ubicarlo! a! nivel! del!
propio!formulario!

A!continuacin!se!muestran!las!modificaciones!que!se!precisan!realizar!en!cdigo.!

Cdigo!1.10:(FormularioLibro09JavascriptDegradable.html)!

<body>
<form action="destino.html" onsubmit="return validacion();" >
<!cdigo omitido-->
<input type="submit" value="Insertar" />
</form>

Una!vez!realizadas!estas!modificaciones!el!formulario!funcionar!de!forma!correcta!en!
el!caso!de!que!el!navegador!no!soporte!JavaScript.!En!estos!momentos!disponemos!de!
una!versin!final!de!nuestro!formulario.!A!continuacin,!pasaremos!a!modificar!la!CSS!
de! ste! para! que! encaje! de! forma! ms! natural! con! las! ultimas! modificaciones!
realizadas.!A!continuacin!se!muestra!el!cdigo!de!la!nueva!hoja.!

Cdigo1.11!:!(formato.css)!

legend,label {
font-weight:bold;
}
p{
text-align:right;
width:300px;
}
!

Por! ultimo! modificaremos! la! pgina! para! que! externalice! correctamente! la! hoja! de!
estilo!y!la!funcin!de!JavaScript.!

!
31
Arquitectura*Java!

Cdigo1.12:!(validacion.js)!

<head>
<link rel="stylesheet" type="text/css" href="css/formato.css" />
<script type="text/javascript" src="js/validacion.js" >
</script>
</head>
!

Una!vez!realizadas!estas!modificaciones!podemos!ver!el!resultado!final!

Resumen!
Este! captulo! nos! ! ha! servido! para! construir! un! formulario! HTML! que! usaremos! mas!
adelante! en! nuestra! aplicacin! JEE! .Pero! sobre! todo! nos! ha! servido! para! irnos!
familiarizando!con!la!estructura!de!contenidos!que!tendrn!los!distintos!captulos.!

32
www.arquitecturajava.com!

33
Arquitectura*Java!

2.Java$Server$Pages!
!
!
!

En! el! captulo! anterior! hemos! construido! un! formulario! HTML.! En! este! captulo! nos!
encargaremos! de! construir! las! primeras! pginas! JSP! de! nuestra! aplicacin,! stas! se!
encargarn! de! guardar! los! datos! de! nuestros! libros! en! base! de! datos,! as! como! de!
mostrar! una! lista! con! los! libros! que! hemos! almacenado! en! sta.! A! continuacin! se!
detallan!los!objetivos!del!captulo.!

Objetivos:

Crear! la! pagina! ! InsertarLibro.jsp! ! que! se! encargar! de! insertar! libros! en!
nuestra!base!de!datos.!
Crear!la!pagina!MostrarLibros.jsp!que!se!encargar!de!presentar!una!lista!con!
los!libros!almacenados!en!la!base!de!datos.!

Tareas:

1. Construccin!de!la!tabla!Libros!en!!un!servidor!MySQL.!
2. Instalacin!de!un!driver!JDBC!nativo!para!acceder!a!la!base!de!datos!desde!Java.!
3. Creacin!de!la!pagina!InsertarLibro.jsp.!
4. Creacin!de!la!pagina!!MostrarLibros.jsp.!

1. Creacin!de!una!tabla!Libros!

Para!realizar!esta!tarea!necesitamos!haber!instalado!previamente!un!servidor!MySQL!y!
aadido!un!esquema!!denominado!arquitecturajava!a!ste.!Una!vez!realizadas!estas!
dos! operaciones! elementales,! usaremos! la! herramienta! ! MySQL! QueryBrowser! para!
crear!una!tabla!con!los!siguientes!campos:!!

34
www.arquitecturajava.com!

Isbn:!varchar!(10).!
Titulo:!varchar!(30).!
Categora:!varchar!(30).!
!

A!continuacin!se!muestra!una!imagen!con!la!tabla!ya!creada!dentro!del!esquema.!

Tras! crear! la! tabla! en! la! base! de! datos,! la! siguiente! tarea! que! nos! ayuda! a! instalar! un!
driver!JDBC.

2. Instalar!el!driver!JDBC.!

Al! ! crear! la! tabla! en! el! servidor! MySQL! ser! preciso! acceder! a! ella! desde! nuestra!
aplicacin!web!,!para!ello!necesitaremos!instalar!en!la!aplicacin!un!driver!JDBC!nativo!
para!MySQL.!El!driver!se!puede!obtener!de!la!siguiente!url.!

http://www.mysql.com/downloads/connector/j/

Despus!de!obtener!el!driver!(formato!tar.gz!para!Ubuntu)!lo!vamos!a!descomprimir!y!
as!obtendremos!el!fichero!mysqleconnectorejavae5.1.12ebin.jar!que!contiene!las!clases!
que! nos! permiten! conectarnos! a! MySQL! desde! Java.! Tras! obtener! este! fichero,! lo!
aadiremos!a!la!carpeta!lib!de!nuestra!aplicacin!web!(ver!imagen)!

!
Terminadas!ya!estas!primeras!tareas!orientadas!ms!hacia!la!administracin!que!hacia!
el!desarrollo,!podemos!comenzar!a!construir!las!pginas!de!nuestra!aplicacin.!
35
Arquitectura*Java!

3. Creacin!de!la!pgina!!InsertarLibro.jsp!

La! pgina! InsertarLibro.jsp! recoger! los! datos! enviados! por! el! formulario! construido!
en! el! captulo! anterior! e! insertar! un! nuevo! registro! en! la! base! de! datos! .El! siguiente!
diagrama!muestra!la!relacin!entre!los!tres!elementos.!

Como!podemos!observar!hemos!renombrado!el!fichero!del!captulo!anterior!como!!

FormularioInsertarLibro.jsp!

Asignndole!.jsp!para!que,!a!partir!de!estos!momentos,!todas!las!paginas!compartan!la!
misma! extensin.! Es! el! momento! de! pasar! a! construir! la! pagina! InsertarLibro.jsp,! a!
continuacin!se!muestra!su!cdigo!fuente.!

Cdigo!2.1:!(InsertarLibro.jsp)!

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<!-- sentencias de import necesarias para jdbc-->
<%@ page import="java.sql.Connection"%>
<%@ page import="java.sql.Statement"%>
<%@ page import="java.sql.DriverManager"%>
<%@ page import="java.sql.SQLException"%>

<%
//1
String isbn = request.getParameter("isbn");
String titulo = request.getParameter("titulo");
String categoria = request.getParameter("categoria");

Connection conexion = null;


Statement sentencia = null;

36
www.arquitecturajava.com!

int filas=0;
try {
//2
Class.forName("com.mysql.jdbc.Driver");
conexion = DriverManager.getConnection(
"jdbc:mysql://localhost/arquitecturajava",
"root",
"java");

sentencia = conexion.createStatement();
//3
String consultaSQL = "insert into Libros (isbn,titulo,categoria) values ";
consultaSQL += "('" + isbn + "','" + titulo + "','" + categoria + "')";
//4
filas = sentencia.executeUpdate(consultaSQL);

response.sendRedirect("MostrarLibros.jsp");

} catch (ClassNotFoundException e) {

System.out.println("Error en la carga del driver"


+ e.getMessage());

} catch (SQLException e) {
System.out.println("Error accediendo a la base de datos"
+ e.getMessage());
} finally {
//5
if (sentencia != null) {

try {sentencia.close();}
catch (SQLException e)
{System.out.println("Error cerrando la sentencia" +
e.getMessage());}
}
if (conexion != null) {

try {conexion.close();}
catch (SQLException e)
{System.out.println("Error cerrando la conexion" +
e.getMessage());}
}
}%>

Es!evidente!que!el!cdigo!de!la!pagina!aunque!sencillo,!es!tambin!bastante!extenso!ya!
que!se!encarga!de!gestionar!la!conexin!a!la!base!de!datos!y!posterior!ejecucin!de!una!
consulta!.A!continuacin!se!enumeran!las!principales!operaciones!que!el!cdigo!realiza.!

37
Arquitectura*Java!

1. Lee! la! ! informacin! que! proviene! de! FormularioInsertarLibro.html! usando! el!


objeto!request!de!JSP.!
2. Crea! un! objeto! ! de! tipo! Connection(conexin)! y! un! objeto! de! tipo! Statement!
(sentencia)!
3. Crea!una!consulta!!SQL!de!insercin!con!los!datos!del!libro!
4. Ejecuta!la!sentencia!con!su!SQL!
5. Cierra!los!recursos!(conexin!,sentencia!etc)!

A!continuacin!se!muestra!una!imagen!de!la!estructura!del!proyecto!y!el!nuevo!fichero!
que!acabamos!de!crear.!

Terminada! esta! primera! pgina,! es! momento! de! abordar! el! segundo! objetivo! del!
captulo.!

4. Creacin!de!la!pagina!MostrarLibros.jsp!

La!pgina!MostrarLibros.jsp!se!encargar!de!mostrar!una!lista!completa!de!todos!los!
libros!que!tenemos!almacenados!en!la!base!de!datos.!Para!ello!har!uso!del!API!de!JDBC!
(ver!imagen).!

38
www.arquitecturajava.com!

ste!es!el!cdigo!fuente!de!la!pgina.!

Cdigo!2.2:MostrarLibros.jsp!

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.Statement" %>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.SQLException" %>
<%@ page import="java.sql.ResultSet" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Lista de Libros</title>
</head>
<body>
<%
Connection conexion=null;
Statement sentencia=null;
ResultSet rs=null;
try {
Class.forName("com.mysql.jdbc.Driver");
//1
conexion =
DriverManager.getConnection("jdbc:mysql://localhost/arquitecturajava",
"root",
"java");

sentencia= conexion.createStatement();
//2
String consultaSQL= "select isbn,titulo,categoria from Libros";
//3 y 4
rs=sentencia.executeQuery(consultaSQL);
//5
while(rs.next()) { %>

<%=rs.getString("isbn")%>
<%=rs.getString("titulo")%>
<%=rs.getString("categoria")%>
<br/>

<% }

}catch (ClassNotFoundException e) {

System.out.println("Error en la carga del driver"

39
Arquitectura*Java!

+ e.getMessage());

}catch (SQLException e) {

System.out.println("Error accediendo a la base de datos"


+ e.getMessage());
}
finally {
//6
if (rs != null) {

try {rs.close();} catch (SQLException e)


{System.out.println("Error cerrando el resultset" + e.getMessage());}

if (sentencia != null) {

try {sentencia.close();} catch (SQLException e)


{System.out.println("Error cerrando la sentencia" + e.getMessage());}

}
if (conexion != null) {

try {conexion.close();} catch (SQLException e)


{System.out.println("Error cerrando la conexion" + e.getMessage());}
}
}
%>
<a href="FormularioInsertarLibro.jsp">Insertar Libro</a>
</body></html>
!

Podemos!apreciar!que!el!cdigo!fuente!de!MostrarLibro.jsp!realiza!las!siguientes!tareas.!

1. Crea!un!objeto!conexin!y!un!objeto!sentencia.!
2. Crea!una!consulta!SQL!de!seleccin!para!todos!los!libros!de!la!tabla.!
3. Ejecuta!la!sentencia!con!su!SQL.!
4. Devuelve!un!ResultSet!con!todos!los!registros.!
5. Recorre!el!ResultSet!y!lo!imprime!en!html.!
6. Cierra!los!recursos!(conexin!,sentencia,!etc).!

Una!vez!creadas!ambas!pginas,!podemos!invocar!la!pgina!MostrarLibros.jsp!a!travs!
del!navegador!y!!as!ver!cul!es!la!lista!inicial!de!libros!que!presenta(hemos!insertado!2).!

40
www.arquitecturajava.com!

Tras!cargar!esta!pgina,!podremos!pulsar!en!el!enlace!que!nos!redirige!al!formulario!de!
insercin!(ver!imagen)!

En! el! momento! en! que! pulsemos! al! botn! de! insertar! un! nuevo! libro,! ste! ser!
insertado!en!la!tabla!Libros!y!la!aplicacin!volver!a!mostrar!la!pgina!MostrarLibros.jsp!
(ver!imagen).!

41
Arquitectura*Java!

Por!ltimo!mostramos!la!estructura!de!ficheros!final!del!captulo.!

Resumen!
En! este! captulo! hemos! progresado! al! aadir! una! nueva! funcionalidad! a! nuestra!
aplicacin,!que!en!estos!momentos!ya!es!capaz!de!insertar!y!seleccionar!registros!en!!la!
base!de!datos.! !

42
www.arquitecturajava.com!

43
Arquitectura*Java!

3.DRY$y$JSP!
!

En!el!captulo!anterior!hemos!construido!la!funcionalidad!de!insertar!y!listar!libros!.!Sin!
embargo,! si! revisamos! el! cdigo! de! nuestras! paginas,! veremos! que! gran! parte! es!
idntico! en! ambas.! sto! es! muy! habitual! en! el! desarrollo! de! aplicaciones! y! genera!
problemas! de! mantenimiento! pues! si! en! algn! momento! hay! que! cambiar! parte! del!
cdigo,!en!vista!de!que!lo!hemos!repetido!en!todas!las!pginas,!ser!necesario!realizar!
las! modificaciones! una! por! una! .! Para! solventar! este! problema,! en! este! captulo!
introduciremos! uno! de! los! principios! mas! importantes! de! ingeniera! de! software! el!
principio!DRY.!

DRY!:!DRY!o!Don't!Repeat!YourSelf!implica!que,!cualquier!funcionalidad!existente!en!un!
programa!debe!existir!de!forma!nica!en!l!,!o!lo!que!es!lo!mismo,!no!debemos!tener!
bloques!de!cdigo!repetidos.!!

Objetivos:!

Aplicar! el! principio! DRY! a! las! pginas! que! hemos! construido! hasta! este!
momento,eliminando!cualquier!repeticin!de!cdigo.!
Avanzar! en! la! construccin! de! la! aplicacin! y! aadir! un! desplegable! de!
categoras.!Revisar!el!uso!del!principio!DRY!apoyndonos!en!dicho!desplegable!

44
www.arquitecturajava.com!

Tareas:!

1. Aplicar!el!principio!DRY!y!crear!una!nueva!clase!que!ayude!a!eliminar!el!cdigo!
repetido!JDBC!de!las!pginas.!
2. Modificar! las! pginas! JSP! para! que! deleguen! parte! de! su! funcionalidad! en! la!
nueva!clase.!
3. Aadir!desplegable!de!categoras!para!seguir!profundizando!en!la!aplicacin!del!
principio!DRY.!
4. El!principio!DRY!y!las!consultas!SQL.!
5. El!principio!DRY!!mtodos!y!parmetros!
6. ResultSet!vs!listas!de!objetos!
7. Uso!de!interfaces!a!nivel!de!libro!
8. Cierre!de!conexiones!usando!reflection!

1. Aadir!nueva!clase!

En!nuestro!caso!nos!vamos!a!centrar!en!eliminar!el!cdigo!JDBC!repetido!!en!nuestras!
pginas!(ver!imagen).!

45
Arquitectura*Java!

Para! ello! vamos! a! una! nueva! clase! que! se! se! va! a! denominar! DataBaseHelper! y! nos!
ayudara! a! gestionar! mejor! el! cdigo! JDBC.! Esta! clase! implementar! los! siguientes!
mtodos:!

public! static! ResultSet! seleccionarRegistros(String! sql):! Mtodo! que! se! encargar! de!
ejecutar!una!consulta!SQL!de!seleccin!!y!devolvernos!un!conjunto!de!registros!con!una!
estructura!de!ResultSet.!

public!static!void!modificarRegistro(String!sql)!:Mtodo!que!se!encargar!de!ejecutar!
cualquier! consulta! SQL! de! modificacin! (insert,update,delete! etc)! y! devolvernos! un!
entero!con!el!numero!de!filas!afectadas.!

A!continuacin!se!muestra!su!cdigo!fuente.!

Cdigo!3.1:!(DataBaseHelper.java)!

package com.arquitecturajava;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DataBaseHelper {

private static final String DRIVER = "com.mysql.jdbc.Driver";


private static final String URL = "jdbc:mysql://localhost/arquitecturajava";
private static final String USUARIO = "root";
private static final String CLAVE = "java";

public int modificarRegistro(String consultaSQL) {

Connection conexion = null;


Statement sentencia = null;
int filasAfectadas = 0;

try {

Class.forName(DRIVER);
conexion = DriverManager.getConnection(URL,

USUARIO, CLAVE);

sentencia = conexion.createStatement();
filasAfectadas = sentencia.executeUpdate(consultaSQL);

} catch (ClassNotFoundException e) {
46
www.arquitecturajava.com!

System.out.println("Error driver" + e.getMessage());


} catch (SQLException e) {

System.out.println("Error de SQL" + e.getMessage());


} finally {

if (sentencia != null) {

try {sentencia.close();} catch (SQLException e) {}

}
if (conexion != null) {

try {conexion.close();} catch (SQLException e) {}


}

}
return filasAfectadas;
}
public ResultSet seleccionarRegistros(String consultaSQL) {

Connection conexion = null;


Statement sentencia = null;
ResultSet filas = null;
try {
Class.forName(DRIVER);

conexion = DriverManager.getConnection(URL,
USUARIO, CLAVE);

sentencia = conexion.createStatement();

filas = sentencia.executeQuery(consultaSQL);
} catch (ClassNotFoundException e) {
System.out.println("Error Driver" + e.getMessage());
} catch (SQLException e) {
System.out.println("Error de SQL " + e.getMessage());
}
return filas;
}
}
!

Una! vez! que! esta! clase! est! construida,! las! pginas! JSP! de! nuestra! aplicacin!
simplificarn! significativamente! el! cdigo! que! contienen! y! delegarn! en! la! clase!
DataBaseHelper!para!realizar!la!mayor!parte!de!las!operaciones!JDBC!(ver!imagen)!.!

47
Arquitectura*Java!

Acabamos!de!construir!la!clase!DataBaseHelper,!es!momento!de!pasar!a!modificar!!las!
paginas!JSP!para!que!deleguen!en!ella.!

2. Modificar!paginas!JSP!

Tras!la!construccin!de!la!nueva!clase,!modificaremos!el!cdigo!de!las!pginas!que!se!
ven!afectadas!InsertarLibro.jsp!y!MostrarLibros.jsp!(ver!cdigo).!!

Cdigo!3.2:!(InsertarLibro.jsp)!

<%@page import="com.arquitecturajava.DataBaseHelper"%>
<%
String isbn= request.getParameter("isbn");
String titulo= request.getParameter("titulo");
String categoria= request.getParameter("categoria");
//realizo la consulta usando el DBHelper y el codigo queda simplificado
String consultaSQL= "insert into Libros (isbn,titulo,categoria) values ";
consultaSQL+= "('" +isbn+ "','" +titulo + "','" +categoria+"')";
DataBaseHelper db= new DataBaseHelper();
int filas=db.modificarRegistro(consultaSQL);
response.sendRedirect("MostrarLibros.jsp");
%>

48
www.arquitecturajava.com!

Como! podemos! ver! la! pgina! InsertarLibros.jsp! queda! visiblemente! simplificada! .Sin!
embargo,!no!ocurre!lo!mismo!con!MostrarLibros.jsp,!(ver!imagen).!

Cdigo!3.3:!(MostrarLibros.jsp)!

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>

<%@ page import="java.sql.ResultSet"%>


<%@ page import="java.sql.SQLException"%>
<%@page import="com.arquitecturajava.DataBaseHelper"%>
<!omitimos cabecera!
<body>
<%
ResultSet rs = null;
try {
String consultaSQL = "select isbn,titulo,categoria from Libros";
DataBaseHelper helper = new DataBaseHelper();
rs = helper.seleccionarRegistros(consultaSQL);
! while (rs.next()) {
%>
<%=rs.getString("isbn")%>
<%=rs.getString("titulo")%>
<%=rs.getString("categoria")%>
<br />
<%
}
}
catch (SQLException e) {

System.out.println("Error accediendo a la base de datos"


+ e.getMessage());
} finally {

if (rs != null) {

try {
rs.close();
} catch (SQLException e) {
System.out.println("Error cerrando el resultset"
+ e.getMessage());
}

}
}
%>
<a href="FormularioInsertarLibro.jsp">Insertar Libro</a>
</body>
</html>

49
Arquitectura*Java!

Para!poder!simplificar!an!ms!el!cdigo!de!!la!pgina!MostrarLibros.jsp!precisaremos!
apoyarnos!!de!nuevo!en!el!principio!DRY.!Sin!embargo,!con!tan!poco!cdigo!construido,!
es!difcil!ver!cmo!aplicarlo!con!mayor!coherencia.!As!pues!vamos!a!aadir!una!nueva!
funcionalidad!a!nuestra!aplicacin!para!en!adelante!ver!las!cosas!con!mayor!claridad.!

3. Aadir!Filtro!por!categora!

!Vamos! a! aadir! un! desplegable! de! categoras! a! la! pgina! MostrarLibros.jsp! que! nos!
permitir! posteriormente! realizar! filtrados! sobre! la! lista! dependiendo! de! la! categora!
que!elijamos!(ver!imagen)!.

Para!conseguir!que!nuestra!pgina!de!MostrarLibros!muestre!el!desplegable!tendremos!
que!aadirle!el!siguiente!bloque!de!cdigo.!

Cdigo!3.4:!(MostrarLibros.jsp)!

<select name="categoria">
<option value="seleccionar">seleccionar</option>
<%
ResultSet rs=null;
try {
String consultaSQL = "select distinct(categoria) from Libros";
DataBaseHelper helper = new DataBaseHelper();
rs=helper.seleccionarRegistros(consultaSQL);
while(rs.next()) { %>
<option value="<%=rs.getString("categoria")%>">
<%=rs.getString("categoria")%></option>
<% } %>
</select>
<br/>
!

50
www.arquitecturajava.com!

En!principio!esta!accin!no!es!muy!complicada,!sin!embargo!si!revisamos!el!formulario!
de!insercin,!nos!daremos!cuenta!de!que!hay!disearlo!como!desplegable!(ver!imagen).!

En! la! pgina! de! MostrarLibros.jsp! utilizaremos! el! desplegable! para! filtrar! la! lista! de!
libros! por! categora,! mientras! que! el! formulario! permitir! al! usuario! seleccionar! las!
categoras!de!forma!ms!sencilla,!evitando!cualquier!tipo!de!error!de!escritura!al!estar!
prefijadas.! Ahora! bien,! la! consulta! SQL! est! repetida! en! ambas! pginas! como! se!
muestra!en!la!siguiente!imagen.!

51
Arquitectura*Java!

Por!lo!tanto!nos!encontramos!en!una!situacin!similar!a!la!!anterior!,!slo!que!en!esta!
ocasin!en!vez!de!tener!cdigo!JDBC!repetido!tenemos!consultas!SQL.!

4. El!principio!DRY!y!las!consultas!SQL!

Para! evitar! la! ! repeticin! de! SQLs! a! lo! largo! de! las! distintas! pginas! JSP! (con! los!
problemas! de! mantenimiento! asociados)! nos! apoyaremos! en! la! idea! anterior! y!
crearemos! una! nueva! clase! que! se! encargue! de! gestionar! las! consultas.!
Denominaremos! a! la! nueva! clase! Libro! :! sta! almacenar! todas! las! consultas! que!
manejen!los!datos!que!la!tabla!Libro!contiene.!A!continuacin!se!muestra!una!imagen!
sobre!cmo!encaja!la!nueva!clase!en!la!estructura!que!ya!tenamos!definida.!

52
www.arquitecturajava.com!

Clarificado!as!donde!encaja!la!nueva!clase!en!nuestra!arquitectura,!vamos!a!mostrar!su!
cdigo!fuente.!

Cdigo!3.5!:!(Libro.java)!

public class Libro {


public static ResultSet buscarTodasLasCategorias() {
String consultaSQL = "select distinct(categoria) from Libros";
DataBaseHelper helper = new DataBaseHelper();
ResultSet rs = helper.seleccionarRegistros(consultaSQL);
return rs;
}
public static void insertar(String isbn, String titulo, String categoria) {
String consultaSQL = "insert into Libros (isbn,titulo,categoria) values ";
consultaSQL += "('" + isbn + "','" + titulo + "','" + categoria + "')";
DataBaseHelper helper = new DataBaseHelper();
helper.modificarRegistro(consultaSQL);
}
public static ResultSet buscarTodos() {
String consultaSQL = "select isbn,titulo,categoria from Libros";
DataBaseHelper helper = new DataBaseHelper();
ResultSet rs = helper.seleccionarRegistros(consultaSQL);
return rs;
}}

53
Arquitectura*Java!

Como!podemos!ver,!la!clase!alberga!tres!mtodos.!

1. buscarTodos()!
2. buscarPorCategoria()!
3. insertar()! !

Cada!uno!de!ellos!se!encarga!de!ejecutar!una!de!las!consultas!necesarias!para!la!tabla!
Libros.!Una!vez!creada!esta!clase,!las!paginas!JSP!podrn!delegar!en!ella!!y!eliminar!las!
consultas! SQL! de! las! pginas.! A! continuacin! se! muestra! la! pagina! InsertarLibro.jsp!
como!ejemplo!del!uso!de!la!clase!Libro!en!las!pginas!JSP.!!

Cdigo!3.6:!(InsertarLibro.jsp)!

<%@page import="com.arquitecturajava.Libro"%>
<% String isbn= request.getParameter("isbn");
String titulo= request.getParameter("titulo");
String categoria= request.getParameter("categoria");
//realizo la consulta usando el DBHelper y el codigo queda simplificado
Libro.insertar(isbn,titulo,categoria);
response.sendRedirect("MostrarLibros.jsp");%>

Hemos!eliminado!las!consultas!SQL!de!nuestras!pginas!aplicando!el!principio!DRY.!Sin!
embargo!es!buen!momento!para!volver!a!revisar!este!principio!de!cara!a!la!nueva!clase!
Libro!!que!hemos!construido.!Si!nos!fijamos!en!la!firma!del!mtodo!insertar,!

Cdigo3.7:!(Libro.java)!

public static void insertar(String isbn, String titulo, String categoria)

nos! podemos! dar! cuenta! de! que! probablemente! no! sea! el! nico! mtodo! que! incluya!
estos!parmetro,s!ya!que!el!mtodo!modificar!y!el!mtodo!borrar!tendrn!parmetros!
similares!cuando!se!construyan:!

Cdigo!3.8:!(Libro.java)!

public static void editar(String isbn, String titulo, String categoria)


public static void borrar(String isbn)
!

Parece! claro! que! todos! comparten! un! mismo! grupo! de! parmetros.! Es! una! ocasin!
perfecta!para!volver!a!aplicar!el!principio!DRY!y!eliminar!esta!repeticin!de!parmetros.!

54
www.arquitecturajava.com!

5. El!principio!DRY!mtodos!y!parametros!

En!programacin!orientada!a!objeto,!una!clase!siempre!se!compone!de!propiedades!y!
mtodos! o! funciones.! En! nuestro! caso,! la! clase! Libro! no! dispone! de! propiedades! y! de!
ah!los!problemas!con!todos!los!!parmetros(ver!imagen).!

Por! lo! tanto,! vamos! a! modificar! nuestra! clase! para! que! disponga! de! las! propiedades!
necesarias!y!los!mtodos!se!puedan!apoyar!en!ellas!evitando!repeticiones!innecesarias.!
La!siguiente!imagen!clarifica!la!nueva!estructura!de!la!clase!y!como!sta!se!apoya!en!el!
principio!DRY.!

Una! vez! tenemos! claro! las! modificaciones! que! afectaran! a! la! clase,! vamos! a! ver! su!
cdigo!fuente.!

55
Arquitectura*Java!

Cdigo!3.9:!(Libro.java)!

public class Libro {


private String isbn;
private String titulo;
private String categoria;
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public String getCategoria() {
return categoria;
}
public void setCategoria(String categoria) {
this.categoria = categoria;
}
public Libro(String isbn, String titulo, String categoria) {
this.isbn = isbn;
this.titulo = titulo;
this.categoria = categoria;
}
public static ResultSet buscarTodasLasCategorias() {
String consultaSQL = "select distinct(categoria) from Libros";
DataBaseHelper helper = new DataBaseHelper();
ResultSet rs = helper.seleccionarRegistros(consultaSQL);
return rs;}
public void insertar() {
String consultaSQL = "insert into Libros (isbn,titulo,categoria) values ";
consultaSQL += "('" + this.isbn + "','" + this.titulo + "','"
+ this.categoria + "')";
DataBaseHelper helper = new DataBaseHelper();
helper.modificarRegistro(consultaSQL);
}
public static ResultSet buscarTodos() {
String consultaSQL = "select isbn,titulo,categoria from Libros";
DataBaseHelper helper = new DataBaseHelper();
ResultSet rs = helper.seleccionarRegistros(consultaSQL);
return rs;
}}
!
56
www.arquitecturajava.com!

Visto! as! el! cdigo! fuente,! es! momento! de! mostrar! las! modificaciones! que! debemos!
realizar! a! nivel! de! las! pginas! JSP.! En! este! caso! volveremos! a! apoyarnos! en! la! pgina!
InsertarLibro.jsp.!

Cdigo!3.10:!(InsertarLibro.jsp)!

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<%@page import="com.arquitecturajava.Libro"%>
<% String isbn= request.getParameter("isbn");
String titulo= request.getParameter("titulo");
String categoria= request.getParameter("categoria");
Libro libro= new Libro(isbn,titulo,categoria);
libro.insertar();
response.sendRedirect("MostrarLibros.jsp");
%>

Vemos!que!el!mtodo!insertar!ya!no!necesita!recibir!ningn!tipo!de!parmetro!ya!que!
obtiene!toda!la!informacin!necesaria!de!las!propiedades!que!son!asignadas!a!nivel!del!
constructor! del! objeto.! ! El! avance! ha! sido! significativo,! sin! embargo! todava! quedan!
algunas!cuestiones!pendientes.!Nos!referimos!a!los!mtodos!de!bsqueda!que!en!estos!
momentos!devuelven!ResultSets!(ver!cdigo).!

Cdigo!3.11(Libro.java)!

public ResultSet buscarTodos();


public ResultSet buscarCategorias();
!

6. ! ResultSets!vs!Listas!de!objetos!

!
Para!las!paginas!JSP!sera!mucho!ms!sencillo!a!la!hora!de!trabajar!el!recibir!una!lista!de!
objetos!(lista!de!Libros)!ya!que!no!tendra!que!encargarse!cerrar!el!ResultSet!y!gestionar!
las! posibles! excepciones.! Por! lo! tanto,! nuestra! tarea! ser! modificar! los! mtodos! de!
bsqueda!para!que!devuelvan!estructuras!de!tipo!lista!.Vamos!a!ver!como!estos!cambios!
se!implementan!a!nivel!de!cdigo.!
!
.!
!
!
!

57
Arquitectura*Java!

Cdigo!3.12:!(Libro.java)!

public static ArrayList<Libro> buscarTodos() {


String consultaSQL = "select isbn,titulo,categoria from Libros";
DataBaseHelper helper = new DataBaseHelper();
ResultSet rs = helper.seleccionarRegistros(consultaSQL);
ArrayList<Libro> listaDeLibros= new ArrayList<Libro>();
try {
while (rs.next()) {
listaDeLibros.add(new Libro(rs.getString("isbn"),
rs.getString("titulo"),
rs.getString("categoria")));

}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return listaDeLibros;
}
!

Una!vez!modificado!el!mtodo!buscarTodos()!para!que!devuelva!una!lista!de!libros,!la!
pagina!MostrarLibros.jsp!podr!apoyarse!en!el!nuevo!mtodo!a!la!hora!de!mostrar!los!
datos.!

Cdigo!3.13:!(Libro.java)!

<%
ArrayList<Libro> listaDeLibros=null;
listaDeLibros=Libro.buscarTodos();
for(Libro libro:listaDeLibros){ %>
<%=libro.getIsbn()%>
<%=libro.getTitulo()%>
<%=libro.getCategoria()%>
<br/>
<% }
%>
!

As,!ya!no!existen!referencias!a!JDBC!en!la!pagina,!el!mismo!cambio!se!puede!aplicar!al!
mtodo!de!buscarTodasLasCategorias().!A!continuacin!se!muestra!su!cdigo!fuente.!

!
58
www.arquitecturajava.com!

Cdigo!3.14:!(Libro.java)!

public static ArrayList<String> buscarTodasLasCategorias() {


String consultaSQL = "select distinct(categoria) as categoria
from Libros";
DataBaseHelper helper = new DataBaseHelper();
ResultSet rs = helper.seleccionarRegistros(consultaSQL);
ArrayList<String> listaDeCategorias= new ArrayList<String>();
String categoria=null;
try {
while (rs.next()) {
categoria= rs.getString("categoria");
listaDeCategorias.add(categoria);
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return listaDeCategorias;
}

7. Uso!de!interfaces!a!nivel!de!Libro!

En!estos!momentos!disponemos!de!mtodos!de!bsqueda!de!Libros!o!Categoras!que!
devuelven!un!ArrayList!de!un!tipo!determinado!<Libro>!o<!String>!(ver!cdigo).!

Si!queremos!tener!una!mayor!flexibilidad!en!el!parmetro!de!retorno,!se!debe!cambiar!
el!tipo!ArrayList!por!el!Interface!List!(ver!cdigo).!

59
Arquitectura*Java!

A!continuacin!se!muestra!como!queda!el!mtodo!una!vez!modificado.!

Cdigo!3.15:!(Libro.java)!

public static List<Libro> buscarTodos() {


String consultaSQL = "select isbn,titulo,categoria from Libros";
DataBaseHelper helper = new DataBaseHelper();
ResultSet rs = helper.seleccionarRegistros(consultaSQL);
List<Libro> listaDeLibros= new ArrayList<Libro>();
try {
while (rs.next()) {
listaDeLibros.add(new Libro(rs.getString("isbn"),
rs.getString("titulo"),
rs.getString("categoria")));
}} catch (SQLException e) {
System.out.println(e.getMessage());
}
return listaDeLibros;
}
!

Nos!puede!parecer!!que!hemos!terminado!de!construir!la!clase!libro!y!s!es!cierto!que!
no!tenemos!que!modificar!nada!a!nivel!de!estructura!general.!Ahora!bien,!si!revisamos!
el!cdigo,!veremos!que!el!mtodo!seleccionarRegistros!de!la!clase!DataBaseHelper!no!
cierra!la!conexin!cuando!nos!devuelve!el!ResultSet!(ver!cdigo).!

Cdigo!3.16:!(DataBaseHelper.java)!

public ResultSet seleccionarRegistros(String consultaSQL) {


Connection conexion = null;
Statement sentencia = null;
ResultSet filas = null;
try {
Class.forName(DRIVER);
conexion = DriverManager.getConnection(URL, USUARIO,
CLAVE);
sentencia = conexion.createStatement();
filas = sentencia.executeQuery(consultaSQL);
} catch (ClassNotFoundException e) {
System.out.println("Error de Driver" + e.getMessage());
} catch (SQLException e) {
System.out.println("Error de SQL " + e.getMessage());
}
return filas;
}
!

60
www.arquitecturajava.com!

sto!lamentablemente!es!necesario!ahora!ya!que!!si!cerramos!la!conexin!a!este!nivel!la!
clase!Libro!no!podr!recorrer!el!ResultSet!y!cargar!la!lista!de!Libros!(ver!imagen).!

8. Cierre!de!conexiones!y!reflection.!

Para!poder!solventar!el!problema!de!cierre!de!conexiones,!vamos!a!pasar!a!modificar!la!
clase! DataBaseHelper:! la! convertiremos! en! una! clase! Genrica! de! tal! forma! que! ella!
misma,!dependiendo!del!tipo!de!clase!que!reciba!como!parmetro!en!los!mtodos!de!
bsqueda,!!nos!generar!una!lista!de!objetos!de!ese!tipo!concreto!(ver!imagen).!

61
Arquitectura*Java!

Ahora!bien,!para!que!la!clase!DataBaseHelper!pueda!hacer!uso!de!genricos!y!sea!capaz!
de! construir! distintos! tipos! de! listas! de! objetos,! hay! que! usar! el! API! de! reflection! de!
Java:! ser! la! encargada! de,! a! partir! de! una! consultas! SQL! cualquiera,! generar!
automticamente!una!lista!de!objetos!del!tipo!que!nosotros!solicitamos!(ver!imagen).!

A!continuacin!se!muestra!el!cdigo!fuente!!que!se!encarga!de!realizar!esta!conversin!
no! lo! vamos! a! explicar! detalladamente! ,! su! importancia! es! muy! relativa! pues! en!

62
www.arquitecturajava.com!

captulos! posteriores! utilizaremos! un! framework! de! persistencia! para! realizar! este!
tipo!de!operaciones.!Aun!as,!a!continuacin!se!muestra!el!!cdigo!una!vez!modificado.!

Cdigo!3.17:!(DataBaseHelper.java)!

public class DataBaseHelper<T> {


public List<T> seleccionarRegistros(String consultaSQL,Class clase) {
Connection conexion = null;
Statement sentencia = null;
ResultSet filas = null;
List<T> listaDeObjetos=new ArrayList<T>();
try {
Class.forName(DRIVER);
conexion = DriverManager.getConnection(URL, USUARIO, CLAVE);
sentencia = conexion.createStatement();
filas = sentencia.executeQuery(consultaSQL);
while (filas.next()) {
T objeto=(T) Class.forName(clase.getName()).newInstance();
Method[] metodos=objeto.getClass().getDeclaredMethods();
for (int i=0;i<metodos.length;i++) {
if (metodos[i].getName().startsWith("set") ) {
metodos[i].invoke(objeto,
filas.getString(metodos[i].getName().substring(3)));
}
if (objeto.getClass().getName().equals("java.lang.String")) {
objeto=(T)filas.getString(1);
}
}
listaDeObjetos.add(objeto);
}
} catch (Exception e) {
System.out.println("Error al seleccionar registros" + e.getMessage());
}
finally {
if (sentencia != null) {
try {sentencia.close();} catch (SQLException e) {}
}
if (conexion != null) {
try {conexion.close();} catch (SQLException e) {}
}
return listaDeObjetos;
}
!

63
Arquitectura*Java!

Comprobamos!que!ahora!s!se!realiza!un!correcto!cierre!de!conexiones.!Terminada!esta!
operacin,! los! mtodos! de! la! clase! Libro! que! utilizan! el! DataBaseHelper<T>! quedarn!
muy!simplificados(!ver!cdigo).!

Cdigo!3.18:!(Libro.java)!

public static List<Libro> buscarTodos() {


String consultaSQL = "select isbn,titulo,categoria from Libros";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
List<Libro> listaDeLibros = helper.seleccionarRegistros(consultaSQL,
Libro.class);
return listaDeLibros;
}
public static List<String> buscarTodasLasCategorias() {
String consultaSQL = "select distinct(categoria) as categoria from Libros";
DataBaseHelper<String> helper = new DataBaseHelper<String>();
List<String>listaDeCategorias = helper.seleccionarRegistros(consultaSQL,
String.class);
return listaDeCategorias;
}

Tras!estos!cambios,!vamos!a!mostrar!cmo!queda!el!cdigo!final!de!la!pagina!MostrarLibros.jsp!
en!lo!que!a!las!listas!se!refiere.!

Cdigo!3.19:!(MostrarLibros.jsp)!

<select name="categoria">
<% List<String> listaDeCategorias=null;
listaDeCategorias=Libro.buscarTodasLasCategorias();
for(String categoria:listaDeCategorias) { %>
<option value="<%=categoria%>"><%=categoria%></option>
<% } %>
</select>
<%List<Libro> listaDeLibros=null;
listaDeLibros=Libro.buscarTodos();
for(Libro libro:listaDeLibros){ %>
<%=libro.getIsbn()%><%=libro.getTitulo()%><%=libro.getCategoria()%>
<br/>
<% }
%>
<a href="FormularioInsertarLibro.jsp">Insertar Libro</a>
</body></html>

64
www.arquitecturajava.com!

Resumen!
En!este!captulo!nos!hemos!centrado!en!explicar!el!principio!DRY!!y!aplicarlo!en!nuestra!
aplicacin.! Como! resultado,! han! aparecido! dos! nuevas! clases! Libro! y! DataBaseHelper.!
La! arquitectura! de! nuestra! aplicacin! ha! aumentado! su! nivel! de! complejidad! ! pero!
como! contraprestacin! hemos! reducido! significativamente! la! engorrosa! repeticin! de!
cdigo!,!reducindose!tambin!el!esfuerzo!de!desarrollo.!

! !

65
Arquitectura*Java!

4.Editar,(Borrar(y(Filtrar!

En! el! captulo! anterior! hemos! introducido! el! principio! DRY.! En! este! ! captulo! nos!
centraremos! ! en! aadir! una! nueva! funcionalidad! a! nuestra! aplicacin.! Veremos! las!
capacidades! de! edicin,! borrado! y! filtrado! de! Libros! ! ayudndonos! a! asentar! los!
conceptos!aprendidos!en!el!captulo!anterior.!!

Objetivos!:!

Aadir!la!funcionalidad!que!nos!permita!borrar!libros.!
Aadir!funcionalidad!que!nos!permita!editar!libros.!
Aadir!un!filtro!por!categoras!!a!los!libros.!

Tareas:!

1. Aadir!un!!nuevo!enlace!de!borrar!a!MostrarLibros.jsp!.!
2. Aadir!el!mtodo!!borrar()!a!!la!clase!Libro.!
3. Aadir! una! nueva! pgina! BorrarLibro.jsp! que! se! encargue! de! ejecutar! la!
funcionalidad!de!borrar.!
4. Aadir!un!nuevo!enlace!de!edicin!a!MostrarLibros.jsp.!
5. Aadir! el! mtodo! buscarPorClave()! que! busque! un! libro! por! ISBN! a! ! la! clase!
Libro.!
6. Aadir!una!nueva!pgina!(FormularioEditarLibro.jsp)!que!muestre!los!datos!del!
libro!que!deseamos!modificar.!
7. Aadir! el! mtodo! salvar()! a! la! clase! libro! que! guarda! las! modificaciones!
realizadas.!
8. Aadir! una! nueva! pagina! SalvarLibro.jsp! que! se! encargue! de! ejecutar! la!
funcionalidad!de!salvar!
9. Aadir!el!mtodo!de!buscarPorCategoria()!a!la!clase!Libro!

66
www.arquitecturajava.com!

10. Modificar! la! pagina! MostrarLibros.jsp! para! que! se! apoye! en! el! mtodo!
buscarPorCategoria.!

1. Aadir!enlace!de!borrar!

Para! que! nuestra! aplicacin! sea! capaz! de! borrar! libros,! debemos! aadir! un! nuevo!
enlace!a!la!pgina!MostrarLibros.jsp!(ver!cdigo).!

Para!ello,!necesitamos!aadir!una!nueva!lnea!de!cdigo!a!MostrarLibros.jsp!como!se!
muestra!en!el!cdigo.!

Cdigo!4.1:!(MostrarLibro.jsp)!

<%=libro.getIsbn()%>
<%=libro.getTitulo()%>
<%=libro.getCategoria()%>
<a href="BorrarLibro.jsp?isbn=<%=libro.getIsbn()%>">Borrar</a>
<br/>

2. Aadir!mtodo!borrar!

Al! crear! el! enlace,! es! necesario! aadir! un! nuevo! mtodo! a! la! clase! Libro! que! se!
encargue!de!borrar!el!registro!de!la!tabla.!A!continuacin!se!muestra!el!cdigo!de!este!
mtodo.!

67
Arquitectura*Java!

Cdigo!4.2:!(Libro.java)!

public void borrar() {

String consultaSQL = "delete from Libros where isbn='"+ this.isbn+"'";


DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
helper.modificarRegistro(consultaSQL);
}
!

Una!vez!modificada!la!clase!Libro,!procederemos!a!construir!la!pgina!BorrarLibro.jsp.!

3. Aadir!pgina!BorrarLibro.jsp!

La!pgina!que!se!encarga!de!borrar!los!libros!es!muy!sencilla,!simplemente!obtiene!el!
ISBN! de! la! peticin,! ! se! encarga! de! crear! un! objeto! libro! e! invocar! al! mtodo! borrar.!
Veamos!!su!cdigo!fuente.!

Cdigo!4.3:(BorrarLibro.jsp)!

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<%@page import="com.arquitecturajava.Libro"%>
<%
String isbn= request.getParameter("isbn");
Libro libro= new Libro(isbn);
libro.borrar();
response.sendRedirect("MostrarLibros.jsp");
%>

Tras! todos! estos! pasos,! dispondremos! de! una! nueva! pgina! en! nuestro! proyecto! (ver!
imagen).!

68
www.arquitecturajava.com!

Con! estas! primeras! tres! tareas! complementamos! el! primer! objetivo! del! captulo:! que!
nuestra! aplicacin! sea! capaz! de! borrar! Libros.! A! continuacin! se! muestra! una! imagen!
del!flujo!entre!pginas!y!clases!que!ayuda!a!clarificar!los!pasos!realizados.!

Es!el!momento!de!pasar!a!las!siguientes!tareas!que!se!encargaran!del!segundo!objetivo:!
la!edicin!de!Libros.!

4. Aadir!link!Edicin!

Como! en! el! caso! de! borrar,! la! primera! tarea! ser! la! de! aadir! un! nuevo! enlace! a! la!
pagina!MostrarLibros.jsp!que!permita!editar.!

69
Arquitectura*Java!

A!continuacin!se!muestran!las!modificaciones!del!cdigo!fuente.!

Cdigo!4.4:(MostrarLibro.jsp)!

<%=libro.getIsbn()%>
<%=libro.getTitulo()%>
<%=libro.getCategoria()%>
<a href="BorrarLibro.jsp?isbn=<%=libro.getIsbn()%>">Borrar</a>
<a href="FormularioEditarLibro.jsp?isbn=<%=libro.getIsbn()%>">Editar</a>
<br/>

Aadido!de!esta!forma!el!enlace,!pasaremos!a!definir!la!siguiente!tarea.!

5. Mtodo!de!bsqueda!por!clave!

Para!poder!editar!un!registro!necesitaremos!primero!seleccionarlo,!para!ello!crearemos!
un! nuevo! mtodo! ! para! la! clase! Libro! que! se! denominara! buscarPorClave().! Este!
mtodo!nos!!buscar!un!libro!a!travs!de!su!ISBN.!A!continuacin!se!muestra!el!cdigo!
fuente!del!nuevo!mtodo.!

Cdigo!4.5:(Libro.java)!

public static Libro buscarPorClave (String isbn) {


String consultaSQL = "select isbn,titulo,categoria from Libros where
isbn='"+ isbn+"'";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
List<Libro> listaDeLibros =
helper.seleccionarRegistros(consultaSQL,Libro.class);
return listaDeLibros.get(0);
}

6. Aadir!formulario!de!edicin!de!cdigo.!

Una!vez!aadido!el!mtodo!de!buscarPorClave,!pasaremos!a!aadir!una!nueva!pgina!a!
nuestra!!aplicacin!denominada!FormularioEditarLibro.jsp!(ver!imagen).!

70
www.arquitecturajava.com!

Finalizada! as! esta! operacin,! podremos! apoyarnos! en! el! mtodo! que! acabamos! de!
construir! para! que! la! nueva! pgina! formularioEditarLibro.jsp! muestre! los! datos! del!
registro!que!nos!interesen.!!Veamos!como!quedara:

Una! vez! tenemos! claro! qu! datos! debe! presentar! la! pagina! vamos! a! ver! su! cdigo!
fuente.!

71
Arquitectura*Java!

Cdigo!4.6:!(MostrarLibro.jsp)!

<%@ page import="java.util.List" %>


<%@page import="com.arquitecturajava.Libro"%>
<%Libro libro= Libro.buscarPorClave(request.getParameter("isbn"));%>
<!-- cabecera y javascript omitido-->
<body>
<form id="formularioEdicion" action="SalvarLibro.jsp">
<fieldset>
<legend>Formulario alta libro</legend>
<p><label for="isbn">ISBN:</label>
<input type="text" id="isbn" name="isbn" value="<%=libro.getIsbn()%>"/></p>
<p><label for="titulo">Titulo:</label><input type="text" id="titulo" name="titulo"
value="<%=libro.getTitulo() %>" /></p>
<p><label for="categoria">Categoria :</label>
<select name="categoria">
<%
List<String> listaDeCategorias=null;
listaDeCategorias=Libro.buscarTodasLasCategorias();
for(String categoria:listaDeCategorias) {

if (libro.getCategoria().equals(categoria)) { %>
<option value="<%=categoria%>" selected="selected">
<%=categoria%></option>
<%}else{ %>
<option value="<%=categoria%>"><%=categoria%></option>
<% }
} %>
</select>
<br/>
</p>
<p><input type="submit" value="Salvar" /></p>
</fieldset>
</form>
</body>
</html>
!

Como! vemos,! el! cdigo! es! idntico! al! formulario! de! Insertar! con! el! que! hemos!
trabajado!en!captulos!anteriores,!con!la!nica!salvedad!!del!siguiente!bloque!de!cdigo.!

Cdigo4.7:!(MostrarLibro.jsp)!

Libro libro=Libro.buscarPorClave(request.getParameter(isbn)
!

Esta!lnea!es!la!encargada!de!buscarnos!el!libro!que!deseamos!editar!y!guardarlo!en!la!
variable!libro.!Una!vez!disponemos!de!los!datos!del!libro!simplemente!!los!mostramos!

72
www.arquitecturajava.com!

a!travs!de!las!etiquetas!<input>!y!<select>!usando!scriptlet!de!jsp!!a!la!hora!de!asignar!
la!propiedad!value,!como!muestra!el!siguiente!bloque!de!cdigo.!

Cdigo!4.8:!(MostrarLibro.jsp)!

<input type="text" id="isbn" name="isbn" value="<%=libro.getIsbn()%>"/></p>


!

7. Aadir!mtodo!salvar!

Una!vez!que!hemos!construido!este!formulario,!podemos!modificar!los!datos!del!libro!
que! previamente! hemos! seleccionado.! Realizados! estos! cambios,! es! necesario!
guardarlos! en! la! base! de! datos.! Para! ello! aadiremos! a! la! clase! ! Libro! el! siguiente!
mtodo:!

Cdigo4.!9:!(Libro.java)!

public void salvar() {


String consultaSQL = "update Libros set titulo='"+ this.titulo+"',
categoria='"+ categoria+"' where isbn='"+ isbn+"'";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
helper.modificarRegistro(consultaSQL);
}
!

Por!ltimo,!es!preciso!ligar!el!mtodo!salvar!con!el!formulario!de!edicin!que!acabamos!
de!construir.!!La!siguiente!tarea!abordara!sto.!

8. Aadir!pagina!SalvarLibro.jsp!

Para!ligar!el!formulario!y!el!mtodo!salvar!aadiremos!una!nueva!pgina!a!la!aplicacin!
denominada!SalvarLibro.jsp!(ver!imagen).!

73
Arquitectura*Java!

A!continuacin!se!muestra!el!cdigo!fuente!de!esta!pgina!!

Cdigo!4.9:!(SalvarLibro.jsp)!

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<%@page import="com.arquitecturajava.Libro"%>
<% String isbn= request.getParameter("isbn");
String titulo= request.getParameter("titulo");
String categoria= request.getParameter("categoria");
Libro libro= new Libro(isbn,titulo,categoria);
libro.salvar();
response.sendRedirect("MostrarLibros.jsp");%>

Una!vez!construidos!todos!los!mtodos,!vamos!a!ver!una!imagen!final!aclaratoria.!

74
www.arquitecturajava.com!

9. Aadir!mtodo!buscarPorCategoria.!

Vamos!a!dar!un!ltimo!paso!y!aadir!la!funcionalidad!de!filtro!por!categora!a!nuestra!
aplicacin.! Para! ello,! lo! primero! que! debemos! hacer! es! aadir! un! nuevo! mtodo! a! la!
clase!Libro!que!nos!devuelva!a!una!lista!de!libros!para!una!categora!concreta.!Vamos!a!
ver!el!cdigo!fuente!de!este!mtodo!.!

Cdigo!4.10:!(Libro.java)!

public static List<Libro> buscarPorCategoria (String categoria) {


String consultaSQL = "select isbn,titulo,categoria from Libros where
categoria='"+ categoria+"'";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
List<Libro> listaDeLibros = helper.
seleccionarRegistros(consultaSQL,Libro.class);
return listaDeLibros;
}
}

75
Arquitectura*Java!

Una!vez!construido!este!nuevo!mtodo,!hay!que!modificar!la!pgina!MostrarLibros.jsp!
para! que! pueda! invocarlo.! Para! ello! aadiremos! a! esta! pgina! un! nuevo! botn! de!
filtrado(ver!imagen).!

Vamos! a! mostrar! a! continuacin! el! nuevo! cdigo! de! la! pgina! MostrarLibros.jsp!
orientado!a!!las!modificaciones!susceptibles!de!realizarse!a!nivel!del!filtro.!

Cdigo!4.11:!(MostrarLibro.jsp)!

List<Libro> listaDeLibros=null;
if (request.getParameter("categoria")==null ||
request.getParameter("categoria").equals("seleccionar")) {
listaDeLibros=Libro.buscarTodos();
}
else {
listaDeLibros=Libro.
buscarPorCategoria(request.getParameter("categoria"));

}
for(Libro libro:listaDeLibros){ %>
<%=libro.getIsbn()%>
<%=libro.getTitulo()%>
<%=libro.getCategoria()%>
<a href="BorrarLibro.jsp?isbn=<%=libro.getIsbn()%>">Borrar</a>
<a href="FormularioEditarLibro.jsp?isbn=<%=libro.getIsbn()%>
Editar</a>
<br/>
<% }
%>

76
www.arquitecturajava.com!

En!esta!caso!la!operacin!no!es!muy!complicada!y!simplemente!selecciona!el!mtodo!
buscarTodos()!o!buscarPorCategoria(),!dependiendo!de!si!pasamos!parmetros!o!no.!A!
continuacin!se!muestra!una!imagen!aclaratoria!de!la!ligazn!existente!entre!la!pagina!
jsp!y!las!distintas!clases!que!hemos!construido.!

Llegados!a!este!punto,!hemos!terminado!el!ltimo!objetivo!del!captulo.!!A!continuacin!
se!muestra!el!cdigo!fuente!de!la!clase!Libro!que!se!ha!visto!sucesivamente!modificada.!

77
Arquitectura*Java!

Cdigo!4.12:!(Libro.java)!

package com.arquitecturajava;
import java.util.List;
public class Libro {
private String isbn;
private String titulo;
private String categoria;
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitulo() {
return titulo;
}

public void setTitulo(String titulo) {


this.titulo = titulo;
}

public String getCategoria() {


return categoria;
}

public void setCategoria(String categoria) {


this.categoria = categoria;
}
public Libro(String isbn) {
super();
this.isbn = isbn;
}
public Libro() {
super();
}
public Libro(String isbn, String titulo, String categoria) {
super();
this.isbn = isbn;
this.titulo = titulo;
this.categoria = categoria;
}
public static List<String> buscarTodasLasCategorias() {
String consultaSQL = "select distinct(categoria) as categoria from
Libros";
DataBaseHelper<String> helper = new DataBaseHelper<String>();
List<String> listaDeCategorias = helper.seleccionarRegistros(
consultaSQL, String.class);
return listaDeCategorias;
}

78
www.arquitecturajava.com!

public void insertar() {

String consultaSQL = "insert into Libros (isbn,titulo,categoria) values ";


consultaSQL += "('" + this.isbn + "','" + this.titulo + "','"
+ this.categoria + "')";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
helper.modificarRegistro(consultaSQL);
}
public void borrar() {

String consultaSQL = "delete from Libros where isbn='" + this.isbn


+ "'";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
helper.modificarRegistro(consultaSQL);
}
public void salvar() {

String consultaSQL = "update Libros set titulo='" + this.titulo


+ "', categoria='" + categoria + "' where isbn='" + isbn + "'";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
helper.modificarRegistro(consultaSQL);
}
public static List<Libro> buscarTodos() {

String consultaSQL = "select isbn,titulo,categoria from Libros";


DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
List<Libro> listaDeLibros = helper.seleccionarRegistros(consultaSQL,
Libro.class);
return listaDeLibros;
}
public static Libro buscarPorClave(String isbn) {
String consultaSQL = "select isbn,titulo,categoria from Libros where
isbn='"+ isbn + "'";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
List<Libro> listaDeLibros = helper.seleccionarRegistros(consultaSQL,
Libro.class);
return listaDeLibros.get(0);
}
public static List<Libro> buscarPorCategoria(String categoria) {

String consultaSQL = "select isbn,titulo,categoria from Libros where


categoria='"+ categoria + "'";
DataBaseHelper<Libro> helper = new DataBaseHelper<Libro>();
List<Libro> listaDeLibros = helper.seleccionarRegistros(consultaSQL,
Libro.class);
return listaDeLibros;
}
}

79
Arquitectura*Java!

Resumen!
En! este! captulo! hemos! afianzado! conceptos! mientras! aadamos! distintas!
funcionalidades!a!nuestra!aplicacin.!Con!ello!hemos!conseguido!una!clase!Libro!que!se!
encarga!de!realizar!todas!las!consultas!SQL!que!la!Tabla!Libros!necesita.!A!estas!clases!
que! mapean! todas! las! operaciones! sobre! una! tabla! concreta! se! las! denomina! clases!
ActiveRecord,! ya! que! implementan! el! patrn! Active! Record! ! (definido! en! Patterns( of(
Enterprise(Application(Architecture,!de!Martin!Fowler)!.!La!conclusin!de!este!captulo!
y!del!anterior!es!que!aplicar!principios!de!ingeniera!de!software!como!el!principio!DRY!
suele!llevar!a!diseos!basados!en!patrones.!

80
www.arquitecturajava.com!

81
Arquitectura*Java!

5.Manejo'de'excepciones!

En! el! captulo! anterior! hemos! aadido! funcionalidad! a! la! aplicacin! y! construido! una!
clase! Libro! que! cumple! con! el! patrn! ActiveRecord.! A! partir! de! este! captulo! no!
aadiremos! mucha! ms! funcionalidad! sino! que! nos! centraremos! en! ir! aplicando!
distintos!refactorings!que!permitan!un!mejor!comportamiento!de!la!aplicacin.!En!este!
captulo!nos!encargaremos!de!!mejorar!la!gestin!de!excepciones!.!

Objetivos:!

Simplificar!el!manejo!de!excepciones!de!la!aplicacin!

Tareas:

1. Revisin!de!el!flujo!de!excepciones!y!uso!de!la!clausulas!try/catch.!
2. Manejo!de!la!clusula!throw!,!throws!y!flujo!de!excepciones.!
3. Creacin!y!conversin!de!excepciones.!
4. Anidamiento!de!excepciones.!
5. Excepciones!de!Tipo!RunTime.!
6. Creacin!de!una!pgina!jsp!!de!error.!
7. Modificacin!del!fichero!web.xml.!
!
!
!
!
!
!
!
!

82
www.arquitecturajava.com!

1. Flujo&de&&excepciones&y&clausulas&catch!

Como! punto! de! partida,! vamos! a! analizar! cmo! se! gestionan! las! excepciones! en! la!
aplicacin!en!estos!momentos.!Para!ello,!nos!vamos!a!apoyar!en!los!siguientes!ficheros.!

Clase!DataBaseHelper!
Clase!Libro!
MostrarLibros.jsp!

Si! revisamos! el! cdigo! de! manejo! de! excepciones! que! tiene! la! clase! DataBaseHelper,!
veremos! que! se! encarga! de! capturar! todas! las! excepciones! que! se! producen! usando!
clausulas!try/catch!e!imprimiendo!los!errores!por!la!consola!(ver!imagen).!

Aunque! esta! gestin! en! un! primer! momento! pueda! parecernos! correcta,! presenta! un!
problema:!al!capturar!todos!los!mensajes!de!error,!stos!nunca!llegan!a!las!paginas!JSP!
y! por! lo! tanto,! un! usuario! habitual! de! la! aplicacin! no! recibir! ningn! mensaje! por!
muchos!errores!que!se!produzcan!(ver!imagen).!

83
Arquitectura*Java!

Si! los! usuarios! no! reciben! ningn! mensaje! de! error,! no! podrn! avisar! a! los!
desarrolladores! de! los! problemas! que! la! aplicacin! les! presenta;! a! lo! sumo,! podrn!
indicar! que! la! aplicacin! no! realiza! una! funcionalidad! cualquiera,! pero! no! nos! podrn!
aportar!ms!informacin.!Si!deseamos!que!los!usuarios!puedan!aportarnos!informacin!
adicional,! es! necesario! que! reciban! unos! mensajes! de! error! claros.! La! siguiente! tarea!
aborda!esta!problemtica.!

2. Manejo'de'las'clasulas!throw,!throws'y'flujo!de#excepciones.!
Para! conseguir! que! los! usuarios! puedan! recibir! informacin! sobre! los! errores! de! la!
aplicacin!es!esencial!realizar!las!siguientes!modificaciones.!

1. En!la!clase!DataBaseHelper!una!vez!capturada!la!excepcin!y!realizado!log!del!
mensaje! de! error,! volveremos! a! lanzar! las! mismas! ! excepciones! utilizando! la!
clausula!throw.!
2. En!la!clase!Libro!modificaremos!la!firma!de!cada!mtodo!para!que!no!capture!
ninguna!excepcin!y!stas!puedan!fluir!hasta!las!paginas!JSP.!
3. En!cada!una!de!las!paginas!JSP!aadiremos!clausulas!try/catch!para!capturar!las!
excepciones.!

84
www.arquitecturajava.com!

A! continuacin! se! muestra! cmo! queda! el! mtodo! modificarRegistro! de! la! clase!
DataBaseHelper!una!vez!aplicados!los!cambios!.El!resto!de!mtodos!ser!similar.!

Cdigo!5.1:!(DataBaseHelper.java)!

public int modificarRegistro(String consultaSQL) throws ClassNotFoundException,


SQLException {
try {
......................
} catch (SQLException e) {
System.out.println("Error de SQL" + e.getMessage());
throw e;
}
..............

Realizado!el!primer!cambio,!podemos!ver!cmo!la!clusula!throw!relanza!la!excepcin!y!
cmo! la! clausula! throws! define! qu! conjunto! de! excepciones! est! soportada.! Del!
mismo! modo! ! que! hemos! modificado! la! clase! DataBaseHelper! modificaremos! a!
continuacin! los! mtodos! de! la! clase! Libro.! Los! cules! nicamente! marcan! el! mtodo!
con!las!excepciones!que!puede!producir.!

Cdigo!5.2:!(Libro.java)!

public void insertar() throws ClassNotFoundException, SQLException {


...........
}

El!ltimo!!paso!es!modificar!nuestra!pgina!JSP!de!insercin!y!capturar!las!excepciones!
con!un!bloque!try/catch!.!

Cdigo5.3:!(MostrarLibro.jsp)!

try {
LibroAR libro = new LibroAR(isbn, titulo, categoria);
libro.insertar();
} catch (Exception e) {%>
<%=e.getMessage()%>
<%}%>

A! continuacin! se! muestra! un! diagrama! aclaratorio! ! de! cmo! todos! estos! cambios!
trabajan!unidos!para!conseguir!que!los!mensajes!de!error!lleguen!al!usuario.!

85
Arquitectura*Java!

3. Creacin)y)conversin)de)excepciones!
Hemos! avanzado! en! nuestra! gestin! de! excepciones! y! ahora! los! usuarios! reciben!
informacin!sobre!los!errores!que!se!producen.!Sin!embargo,!si!revisamos!la!firma!del!
nuevo!mtodo!insertar!de!la!clase!Libro,!nos!encontraremos!con!lo!siguiente.!

Cdigo!5.4:!(Libro.java)!

public void insertar() throws ClassNotFoundException, SQLException

Como! podemos! ver,! la! clusula! throws! lanza! varios! tipos! de! excepciones.! Estas!
clusulas!se!repetirn!mtodo!tras!mtodo!por!todo!nuestro!cdigo!y!en!algunos!casos!
sern!ms!complejas,!por!ejemplo!en!el!mtodo!buscarTodos:!

!
86
www.arquitecturajava.com!

Cdigo!5.5:!(Libro.java)!

public static List<Libro> buscarTodos() throws ClassNotFoundException, SQLException,


InstantiationException, IllegalAccessException, InvocationTargetException {
}

Para! evitar! este! problema! y! simplificar! el! manejo! de! complicados! conjuntos! de!
excepciones,!construiremos!para!nuestra!aplicacin!una!nueva!excepcin!denominada!!
DataBaseException.!A!continuacin!mostramos!el!diagrama!UML!que!nos!permite!ver!
de!qu!clase!hereda,!as!como!su!cdigo!fuente.!

Cdigo5.6:!(DataBaseException.java)!

package com.arquitecturajava;
public class DataBaseException extends Exception {
private static final long serialVersionUID = 1L;
public DataBaseException() {
super();
}
public DataBaseException(String message, Throwable cause) {
super(message, cause);
}
public DataBaseException(String message) {
super(message);
}
public DataBaseException(Throwable cause) {
super(cause);
}}
!

Una!vez!creada!esta!!nueva!excepcin,!modificaremos!el!cdigo!fuente!de!nuestra!clase!
DataBaseHelper!para!que!convierta!todas!las!excepciones!que!produce!JDBC!a!nuestro!
nuevo!tipo!de!excepcin!(ver!imagen).!

87
Arquitectura*Java!

A! continuacin! se! muestra! el! cdigo! fuente! modificado! de! uno! de! los! mtodos! de! la!
clase!DataBaseHelper.!

Cdigo!5.7:!(DataBaseHelper.java)!

public int modificarRegistro(String consultaSQL) throws DataBaseException {


Connection conexion = null;
Statement sentencia = null;
int filasAfectadas = 0;
try {
Class.forName(DRIVER);
conexion = DriverManager.getConnection(URL, USUARIO,
CLAVE);
sentencia = conexion.createStatement();
filasAfectadas = sentencia.executeUpdate(consultaSQL);
} catch (ClassNotFoundException e) {
System.out.println("Clase no encontrada" + e.getMessage());
throw new DataBaseException("Clase no encontrada");
} catch (SQLException e) {
System.out.println("Error de SQL" + e.getMessage());
throw new DataBaseException("Error de SQL");
} finally {
if (sentencia != null) {
try {sentencia.close();} catch (SQLException e) {
}
if (conexion != null) {
try {conexion.close();} catch (SQLException e) {}
}
}
return filasAfectadas;
}

88
www.arquitecturajava.com!

Una! vez! realizadas! estas! modificaciones,! ! los! ficheros! JSP! simplemente! realizaran! una!
captura!sencilla!(ver!cdigo).!

Cdigo!5.8:!(InsertarLibro.jsp)!

<% try {
String isbn= request.getParameter("isbn");
String titulo= request.getParameter("titulo");
String categoria= request.getParameter("categoria");
Libro libro= new Libro(isbn,titulo,categoria);
libro.insertar();
response.sendRedirect("MostrarLibros.jsp");
} catch (DataBaseException e) {
out.println(e.getMessage());
}
%>
!

A!continuacin!se!muestra!la!imagen!que!aglutina!los!ltimos!cambios.!

89
Arquitectura*Java!

4. Excepciones*anidadas!

Tras! conseguir! homogeneizar! la! gestin! de! excepciones! creando! nuestra! nueva! clase!
DataBaseException,! nos! damos! cuenta! que! cuando! se! produce! un! error! recibimos! el!
mensaje!de!Error!de!SQL!(ver!imagen).!

Sin! embargo,! aunque! aparece! el! mensaje! de! error! no! es! el! mensaje! de! error! original!
que! se! produjo.! sto! se! debe! a! que! hemos! construido! nuevas! excepciones!
substituyendo!las!excepciones!originales!por!stas!,!perdiendo!as!los!mensajes!de!error!
originales! del! api! de! java! .! De! esta! forma! se! complica! sobremanera! saber! cul! es! el!
error! real! que! nuestra! aplicacin! ha! producido.! Para! poder! acceder! a! la! informacin!
original!del!error,!debemos!redisear!nuestro!sistema!de!excepciones!para!que!soporte!
excepciones! anidadas! .! Este! tipo! de! excepciones! es! capaz! de! mostrar! su! mensaje! de!
error,!as!como!el!mensaje!de!error!original!que!las!apis!de!java!produjeron!(ver!cdigo)!

Cdigo!5.9:!(DataBaseHelper.java)!

} catch (ClassNotFoundException e) {
System.out.println("Error de acceso al driver" + e.getMessage());
throw new DataBaseException("Error de SQL",e);
}

A! continuacin! se! muestra! un! diagrama! que! contiene! una! excepcin! de! tipo!
DataBaseException!la!cul!tiene!anidada!una!excepcin!de!SQL!para!ayudar!a!clarificar.!

90
www.arquitecturajava.com!

Una!vez!realizado!este!cambio,!!es!necesario!realizar!una!modificacin!en!el!fichero!JSP!
que! se! encarga! de! capturar! las! excepciones! que! provienen! de! la! capa! de! negocio,! ya!
que!debemos!obtener!la!informacin!de!la!excepcin!original!que!se!produjo.!

91
Arquitectura*Java!

Cdigo5.10:!(InsertarLibro.jsp)!

try {
LibroAR libro = new LibroAR(isbn, titulo, categoria);
libro.insertar();
} catch (DataBaseException e) {%>
<%=e.getMessage()%>
<%=e.getException().getMessage()%>
<%}%>

Las! excepciones! anidadas! nos! han! ayudado! a! guardar! la! informacin! original! de! los!
errores!(ver!imagen).!

5. Excepciones*RunTime!
Queremos! avanzar! en! la! simplificacin! del! manejo! de! excepciones,! para! ello!
modificaremos!nuestra!clase!DataBaseException!para!que,!en!vez!de!que!su!clase!padre!
sea!la!clase!Excepcin,!lo!sea!la!clase!RunTimeException!(ver!imagen).!

92
www.arquitecturajava.com!

Al! hacerlo! de! esta! manera,! podremos! eliminar! todas! las! clusulas! throws! de! nuestras!
clases! ya! que! este! tipo! de! excepciones! java! no! obliga! a! capturarlas! y! pueden! fluir!
libremente!por!todo!el!cdigo!como!muestra!la!figura.

93
Arquitectura*Java!

Una!vez!realizado!este!cambio,!!los!mtodos!de!nuestras!clases!quedarn!definidos!de!
la!siguiente!forma:!

Cdigo5.11:!(DataBaseHelper.jsp)!

public int modificarRegistro(String consultaSQL) // no hay excepciones


public void insertar() //no hay excepciones

6. Crear%Pagina%de%Error!
Parece!que!hemos!terminado,!sin!embargo!si!revisamos!el!estado!de!nuestras!pginas!
JSP!respecto!a!la!captura!de!excepciones,!nos!daremos!cuenta!de!que!todas!las!paginas!
contienen!el!mismo!bloque!try/catch!(ver!imagen).!

94
www.arquitecturajava.com!

Este!es!otro!caso!tpico!de!repeticin!de!cdigo,!donde!podemos!hacer!uso!del!principio!
DRY! para! extraer! la! responsabilidad! de! la! gestin! de! errores! de! la! pgina! JSP! y!
centralizarla!en!otra!nueva!pgina!denominada!pgina!de!error,!la!cul!se!encargar!de!
gestionar!los!errores!(ver!imagen).!

Vamos! a! ver! a! continuacin! el! cdigo! fuente! de! esta! pgina! que! tiene! como!
peculiaridad!el!usar!a!nivel!de!directiva!@page!del!atributo!isErrorPage!que!la!identifica!
como!pagina!de!error.!

Cdigo!5.12:!(Error.jsp)!

<%@ page isErrorPage="true"%>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title></head>
<body>
Ha ocurrido un error en la aplicacion :<%=exception.getMessage()%>
Error Interno:<%=exception.getCause().getMessage()%>
</body></html>

95
Arquitectura*Java!

Una!vez!creada!la!pgina!JSP,!debemos!configurar!nuestra!aplicacin!web!para!que!se!
apoye!en!esta!nueva!pgina!de!error.!Para!ello,!modificaremos!el!fichero!web.xml.!

7. Modificar'fichero'web.xml!
El! fichero! web.xml! es! el! fichero! de! configuracin! de! toda! aplicacin! web! java! y! se!
encuentra! ubicado! en! la! carpeta! WEBtINF! .! A! continuacin! se! muestra! el! bloque! de!
cdigo!que!aadiremos!!a!ste!!para!dar!de!alta!correctamente!la!pgina!de!error!en!la!
aplicacin.!

Cdigo!5.13:!(web.xml)!

<web-app>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/Error.jsp</location>
</error-page>
.............
</web-app>

Realizada!esta!operacin,!las!paginas!ya!no!contendrn!bloques!try/catch!(ver!cdigo)!

Cdigo5.14:!(InsertarLibro.jsp)!

<%
String isbn = request.getParameter("isbn");
String titulo = request.getParameter("titulo");
String categoria = request.getParameter("categoria");
LibroAR libro = new LibroAR(isbn, titulo, categoria);
libro.insertar();
response.sendRedirect("ListaLibros.jsp");
%>
!

Modificado! el! fichero! web.xml! y! las! pginas! jsp,! todas! delegan! ahora! en! la! pgina! de!
error.jsp! a! la! hora! de! gestionar! los! distintos! errores,! cumpliendo! con! el! principio! DRY!
(ver!imagen).!

96
www.arquitecturajava.com!

Resumen!
En! este! captulo! nos! hemos! centrado! en! simplificar! el! manejo! de! excepciones! de! la!
aplicacin,!para!lo!cul!hemos!realizado!bastantes!cambios,!entre!los!que!destacan:!

1. Uso! de! excepciones! de! tipo! RunTimeException! para! simplificar! el! flujo! de!
excepciones!de!la!aplicacin.!
2. Uso!del!principio!DRY!y!construccin!de!una!pagina!de!Error!para!centralizar!la!
gestin!de!excepciones.!

97
Arquitectura*Java!

6.Log4J!

En!el!captulo!anterior!nos!hemos!encargado!de!simplificar!la!gestin!de!excepciones!de!!
nuestra! aplicacin.! Sin! embargo,! siempre! ligado! a! la! gestin! de! excepciones! se!
encuentra!la!gestin!!de!los!ficheros!de!log!.!Hasta!este!momento!no!hemos!tratado!!el!
caso!a!fondo!y!nos!hemos!!limitado!imprimir!mensajes!por!la!consola!con!bloques!de!
cdigo!del!siguiente!estilo.!

Cdigo!6.1:!(DataBaseHelper.jsp)!

System.out.println(e.getMessage())

Es! evidente! que! esta! forma! de! trabajar! no! es! la! adecuada! cuando! se! trata! de!
aplicaciones!reales.!As!pues,!en!este!!captulo!nos!encargaremos!de!introducir!un!API!
de!log!!y!modificaremos!nuestra!aplicacin!para!que!haga!uso!de!ella!.!En!nuestro!caso!
vamos!a!usar!log4j!que!es!un!standard!de!facto!en!la!plataforma!Java.!De!esta!manera,!
los!objetivos!del!captulo!sern:!

Objetivos:!

Introduccin!y!manejo!de!log4j!!
Actualizacin!de!la!aplicacin!para!que!use!log4j.!

Tareas:!

1. Instalacin!del!api!de!log4j.!
2. Introduccin!del!api!de!log4j.!
3. Construccin!de!un!ejemplo!sencillo.!
4. Mensajes!de!error!y!niveles.!

98
www.arquitecturajava.com!

5. Manejo!de!Log4.properties.!
6. Integracin!de!log4j!en!la!aplicacin.!

1. Instalacin*de*log4j!
Para! poder! trabajar! con! el! api! de! log4j! debemos! obtener! el! producto! de! la! web!
descargndolo!de!la!siguiente!url.!

http://www.apache.org/dyn/closer.cgi/logging/log4j/1.2.16/apachetlog4jt
1.2.16.tar.gz!

Una!vez!obtenido!crearemos!un!nuevo!proyecto!Java!(No!java!Web)!en!el!eclipse,!!ya!
que!lo!primero!que!vamos!a!hacer!es!un!conjunto!de!ejemplos!sencillos!para!!introducir!
al!lector!a!este!api.!A!continuacin!se!muestra!una!imagen!del!proyecto.!

Una!vez!creado!el!proyecto,!aadiremos!una!carpeta!lib!a!ste!y!ubicaremos!en!ella!el!
fichero!log4je1.2.16.jar!.!El!cual!obtenemos!del!paquete!tar.gz!que!acabamos!de!bajar!.!
Ubicado!el!fichero!en!la!carpeta,!lo!mapeamos!!como!se!muestra!en!la!figura.!

99
Arquitectura*Java!

Realizada! esta! operacin,! nicamente! deberemos! referenciar! la! librera! en! nuestro!
proyecto!para!tenerla!a!nuestra!disposicin.!Para!ello,!accederemos!a!las!propiedades!
del!proyecto!y!en!el!apartado!de!java!build!path!mapearemos!la!librera!(ver!imagen).!

Una! vez! instalada! la! librera,! podemos! comenzar! a! utilizarla.! La! siguiente! tarea! nos!
introducir!en!ella.

2. Introduccin+a+log4j!
El! API! de! log4j! no! es! complicada! de! manejar! pero! s! que! es! en! muchos! casos! poco!
conocida! por! parte! de! los! desarrolladores.! A! continuacin! realizaremos! una!
introduccin!a!sus!conceptos!principales.!!

Si!nos!preguntamos!cmo!funciona!un!sistema!de!log!mucha!gente!nos!responder!con!
algo! como! lo! siguiente:! un! sistema! de! log! genera! mensajes! con! un! formato!
determinado! y! los! almacena! en! una! ubicacin! para! posterior! anlisis! .La! siguiente!
imagen!muestra!la!idea!a!nivel!conceptual.!!

100
www.arquitecturajava.com!

En!el!caso!del!api!de!log4j!la!estructura!es!muy!similar!y!est!compuesta!por!el!siguiente!
diagrama!de!clases,!que!sirve!para!paralelizar!los!conceptos!anteriores.!

Vamos!a!comentar!a!continuacin!cada!una!de!estas!clases.!

String!:!Clase!del!API!de!JSE!que!representa!el!concepto!de!mensaje!!(o!cadena)!
a!nivel!del!API!de!log4j.!
Layout!:!Clase!del!API!de!log4j!que!se!encarga!de!seleccionar!el!formato!en!el!
cul!los!mensajes!son!impresos.!
Appender:!Clase!del!API!de!log4j!que!hace!referencia!al!recurso!en!el!cul!los!
mensajes!de!error!han!de!ser!escritos!(Consola,!Fichero,Base!de!Datos!etc.).!Se!
apoyar!en!la!clase!Layout!para!asignar!un!formato!a!los!mensajes!
Logger:!Clase!del!API!de!log4j!que!se!encarga!de!la!gestin!de!!los!mensajes!de!
error! y! los! imprime! al! appender! o! appenders! que! se! le! hayan! asignado,!
utilizando!el!formato!que!se!defina!en!el!Layout.!

Aunque!las!definiciones!son!sencillas,!!no!hay!nada!mejor!que!un!ejemplo!concreto!de!
cdigo!para!clarificar!como!funciona!Log4j!.!

3. Construccin+de+un+ejemplo+sencillo!
Vamos!a!construir!un!ejemplo!elemental!de!uso!de!log4j.!Para!ello!hemos!construido!el!
siguiente!bloque!de!cdigo!que!hace!un!uso!del!api!y!que!pasaremos!a!analizar.!

101
Arquitectura*Java!

Cdigo6.2:!(Log2UsandoLog.java)!

package com.arquitecturajava.logs;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class log02UsandoLog {
public static void main(String[] args) {
PatternLayout patron= new PatternLayout("%m %n");
ConsoleAppender consola= new ConsoleAppender(patron);
Logger log= Logger.getLogger("milog");
log.addAppender(consola);
log.info("realizando un log sencillo");
}
}
!

Una!vez!construido!el!cdigo!vamos!a!ver!que!resultado!muestra!su!ejecucin!

Como!podemos!ver,!imprime!una!lnea!de!texto!por!la!consola.!Vamos!a!continuacin!a!
analizar!cada!una!de!las!lneas!de!nuestro!cdigo.!

Cdigo!6.3:!(Log2UsandoLog.java)!

PatternLayout patron= new PatternLayout("%m %n");

Esta!clase!define!el!formato!en!el!cul!el!mensaje!ha!de!ser!impreso.!A!continuacin,!se!
explican!cada!uno!de!los!elementos!%!!o!patrones!que!se!han!utilizado.!

%m!:Obliga!a!que!se!imprima!el!texto!del!mensaje!
%n! :! Obliga! a! que! cada! vez! que! se! imprima! un! mensaje! haya! un! retorno! de!
carro!y!se!salte!de!lnea!

102
www.arquitecturajava.com!

Una!vez!definido!el!tipo!de!!layout,!es!momento!de!construir!el!appender!o!recurso!en!
el!que!se!van!a!imprimir!los!distintos!mensajes!de!error!,!el!appender!recibir!un!layout!
como!parmetro.!

Cdigo6.4:!(Log2UsandoLog.java)!

ConsoleAppender consola= new ConsoleAppender(patron);

En!este!caso!hemos!construido!el!appender!ms!sencillo!que!imprime!los!mensajes!a!la!
consola!cumpliendo!con!el!patron!especificado.!El!siguiente!paso!ser!la!creacin!de!un!
Logger! u! objeto! de! log! que! se! encarga! de! gestionar! estos! mensajes.! Este! logger! debe!
tener!un!nombre!(milog).!

Cdigo!6.!5:!(Log2UsandoLog.java)!

Logger log= Logger.getLogger("milog");

Una!vez!creado!el!objeto!de!log,!es!necesario!asignarle!el!appender!al!cul!va!a!escribir!
en!este!caso!la!consola.!

Cdigo!6.6:!(Log2UsandoLog.java)!

log.addAppender(consola);

Por! ultimo,! nicamente! nos! queda! invocar! al! objeto! de! log! y! mandarle! imprimir! un!
mensaje!a!travs!del!mtodo!info,!que!ms!adelante!explicaremos!detalladamente.!

Cdigo!6.7:!(Log2UsandoLog.java)!

log.info("realizando un log sencillo");

El! resultado! de! todo! este! bloque! de! cdigo! es! que,! ! al! ejecutar! el! programa,! se!
imprimir!un!mensaje!por!la!consola!(ver!imagen).!

103
Arquitectura*Java!

Este!sencillo!ejemplo!nos!ha!servido!para!introducir!el!funcionamiento!del!api!de!log4j!
Ahora! seguiremos! avanzando! y! haremos! especial! hincapi! en! los! niveles! de! mensajes!
de!error.!!

4. Mensajes'de'error'y'niveles.!
Acabamos!de!ver!que!el!objeto!de!log!se!encarga!de!escribir!un!mensaje!en!la!consola!
con!el!siguiente!cdigo.!

Cdigo!6.8:!(Log2UsandoLog.java)!

log.info("realizando un log sencillo");

Sin! embargo,! no! queda! muy! claro! por! qu! el! mtodo! se! denomina! info! y! no! por!
ejemplo!message(),!ya!que!simplemente!imprime!un!mensaje!.!sto!se!debe!a!que!el!api!
de! log4j! soporta! varios! niveles! ! de! impresin! de! mensaje,! dependiendo! de! si! es! un!
mensaje! sin! importancia! o! es! un! mensaje! crtico! para! la! aplicacin.! A! continuacin! se!
muestra!los!distintos!niveles!de!mensaje!soportados!y!su!uso.!

Logger.fatal()! Imprime! informacin! de! errores! que! hacen! fallar!


completamente!a!la!aplicacin.!
Logger.error()! Imprime! informacin! sobre! errores! que! ha! generado!
la!aplicacin!pero!no!son!fatales.!
Logger.warn()! Imprime! informacin! sobre! situaciones! atpicas! en! la!
aplicacin.!
Logger.info()! Imprime!informacin!sobre!el!flujo!de!la!aplicacin.!
Logger.debug()! Almacena! informacin! importante! a! nivel! de! debug!
de!la!aplicacin!

104
www.arquitecturajava.com!

Una! vez! que! tenemos! claros! los! distintos! tipos! de! mensaje! que! una! aplicacin! puede!
imprimir! apoyndose! en! el! api! de! log4j! ,vamos! a! crear! un! nuevo! ejemplo! con! el!
siguiente!bloque!de!cdigo.!

Cdigo!6.9:!(Log2Niveles.java)!

public class Log02Niveles {


public static void main(String[] args) {
PatternLayout patron = new PatternLayout("%m %n");
ConsoleAppender consola = new ConsoleAppender(patron);
Logger log = Logger.getLogger("milog");
log.addAppender(consola);
log.fatal("realizando un log sencillo nivel FATAL");
log.error("realizando un log sencillo nivel ERROR");
log.warn("realizando un log sencillo nivel WARN");
log.info("realizando un log sencillo nivel INFO");
log.debug("realizando un log sencillo nivel DEBUG");
}
}
!

Realizada! esta! operacin,! si! ejecutamos! el! programa,! podremos! ver! por! consola! el!
siguiente!resultado:!

Todos!los!mensajes!de!error!se!han!imprimido!de!forma!correcta.!Ahora!bien,!algo!que!
no!hemos!comentado!al!introducir!el!api!de!log4j!es!que!estos!mensajes!se!encuentran!
relacionados!de!forma!jerrquica!(ver!imagen).!

105
Arquitectura*Java!

De!manera!que!se!puede!configurar!el!sistema!de!log!para!que!slo!se!impriman!por!la!
consola!los!mensajes!que!pertenezcan!a!un!elemento!de!la!jerarqua!o!superior.!Vamos!
a!aadir!el!siguiente!bloque!de!cdigo!a!nuestro!programa.!

Cdigo6.11:!(Log2Niveles.java)!

logger.setLevel(Level.WARN);

Con!este!cdigo!solo!sern!impresos!los!de!nivel!WARN!o!superiores!(ver!imagen)!

sto!nos!permitir!definir!en!nuestro!cdigo!qu!mensajes!y!con!qu!niveles!se!asignan.!
Seguidamente! se! muestra! una! funcin! de! ejemplo! y! algunos! usos! de! los! distintos!
niveles!de!log.!

!
106
www.arquitecturajava.com!

Cdigo6.12:!(Log2Niveles.java)!

public static double calcularImporte(double importe) {


Logger log = crearLog();
log.info("entramos en la funcion");
if (importe < 0) {
log.warn("el importe no puede ser negativo");
throw new RuntimeException("operacion no soportada con el
importe");
} else {
if (importe > 0 && importe < 100) {
log.info("compra con el 10 % de descuento");
return importe * 0.90;
} else {
log.info("compra con el 20% de descuento");
return importe * 0.80;
}
}
log.debug(el importe calculado es :+ importe);
}
!

Es!bastante!probable!que,!cuando!estemos!desarrollando!el!programa,!deseemos!que!
el! nivel! de! log! se! encuentre! en! modo! DEBUG! de! tal! forma! que! ayude! a! los!
desarrolladores! a! solventar! cualquier! tipo! de! problema! a! travs! de! sus! trazas! de!
mensaje.!Ahora!bien,!cuando!el!sistema!se!encuentre!en!produccin,!preferiremos!que!
slo!se!almacenen!trazas!de!errores!crticos!y!modificaremos!el!nivel!de!traza!de!log!!a!
error.!!

Hasta! este! momento! hemos! utilizado! el! API! de! Log4J! a! nivel! de! nuestro! cdigo! tanto!
para!realizar!las!tareas!de!log!como!para!configurar!el!log!en!s!.En!los!entornos!reales!
esta!configuracin!de!log!donde!uno!asigna!el!formato!del!mensaje,!los!appenders!y!en!
nivel!de!log!no!se!realiza!a!nivel!de!cdigo,!sino!que!se!utiliza!un!fichero!de!propiedades!
sencillo!denominado!Log4j.properties.!En!la!siguiente!tarea!se!aborda!el!manejo!de!este!
fichero.!

5. Manejo'de#Log4j.properties!

!
Una! vez! que! hemos! entendido! como! funciona! el! api! de! log4j! es! mucho! ms! sencillo!
hablar! del! fichero! log4j.properties,! que! es! el! encargado! de! asignar! los! niveles! de! log!
,appenders!y!layouts!en!una!aplicacin!real!de!tal!forma!que!esta!configuracin!pueda!
ser! modificada! por! un! administrador! sin! tener! que! tocar! el! cdigo! de! la! aplicacin!
Vamos!a!examinar!detalladamente!!el!siguiente!!fichero!log4j.properties,!que!usaremos!
en!nuestra!aplicacin.!
107
Arquitectura*Java!

Cdigo!6.13:!(log4j.properties)!

log4j.rootLogger = DEBUG, AppenderDeConsola


log4j.appender.AppenderDeConsola=org.apache.log4j.ConsoleAppender
log4j.appender.miAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.miAppender.layout.conversionPattern=%m%n
!

En! este! punto! ya! es! mucho! mas! sencillo! entender! cada! lnea,! ! aun! as! las! vamos! a! ir!
comentando!una!por!una.!

Cdigo!6.14:!(log4j.properties)!

log4j.rootLogger = DEBUG, AppenderDeConsola

La! primera! lnea! define! el! logger! principal! ! a! nivel! de! DEBUG! y! le! asigna! un! appender!
denominado!AppenderDeConsola!!.Vamos!a!analizar!la!siguiente!linea.!

Cdigo!6.15:!(log4j.properties)!

log4j.appender.AppenderDeConsola=org.apache.log4j.ConsoleAppender

Esta!lnea!se!encarga!de!definir!qu!tipo!de!appender!usa!nuestro!log.!En!este!caso!se!
trata!de!un!sencillo!appender!de!consola!que!imprimir!los!mensajes!por!la!consola!de!
la!aplicacin.!Las!ltimas!dos!lneas!se!encargan!de!definir!el!tipo!de!layout!que!se!va!a!
utilizar!(ver!imagen).!

Cdigo!6.16!(log4j.properties)!

log4j.appender.miAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.miAppender.layout.conversionPattern=%m%n
!

En!nuestro!caso!el!!Layout!es!de!tipo!Pattern!el!cul!define!un!!patrn!a!aplicar!sobre!
la! estructura! del! mensaje! .! En! este! caso! %m! es! un! patrn! que! indica! que! el! texto! del!
mensaje! ha! de! ser! impreso! y! por! ultimo! %n! define! que! una! vez! impreso! el! texto! del!
mensaje,!se!imprima!un!retorno!de!carro!.Existen!muchas!ms!opciones!de!formato!con!
este!Layout,!pero!no!las!vamos!a!tratar!aqu.!

Lo!ltimo!que!nos!queda!por!comentar!es!que!el!nombre!log4j!que!aparece!en!cada!una!
de!las!lneas!hace!referencia!al!nombre!de!nuestro!logger!log4j!.Este!nombre!puede!
ser!cambiado!por!cualquier!otro,!como!por!ejemplo.!

108
www.arquitecturajava.com!

Cdigo!6.17!(log4j.properties)!

com.arquitecturajava

El!cul!hace!referencia!al!nombre!de!los!packages!de!nuestro!proyecto!y!ser!el!nombre!
que! se! utilizar! a! nivel! de! la! aplicacin.! La! siguiente! tarea! se! encarga! de! configurar!
Log4j!en!nuestra!aplicacin.!

6. Uso$de$log4j$en$nuestra$aplicacin.!
Una!vez!que!hemos!visto!como!funciona!el!api!de!log4j!,podremos!hacer!uso!del!mismo!
en!nuestra!aplicacin.!!Para!ello!instalaremos!la!librera!de!log4j!en!el!directorio!lib!de!
nuestra!aplicacin!web!(ver!imagen).!

Aadida! la! librera,! hay! que! aadir! el! fichero! de! configuracin! de! log4j! con! sus!
parametrizaciones! .! Este! fichero! se! ubicar! en! la! carpeta! src! de! nuestro! proyecto! de!
eclipse!(ver!imagen).!!

Realizada! esta! operacin,! definimos! el! contenido! del! fichero! que! en! este! caso,! por!
simplificar,!ser!idntico!al!anteriormente!comentado.!

109
Arquitectura*Java!

Cdigo!6.18!(log4j.properties)!

log4j.rootLogger = DEBUG, miappender


log4j.logger.milog = com.arquitecturajava.logs
log4j.appender.miappender=org.apache.log4j.ConsoleAppender
log4j.appender.miappender.layout=org.apache.log4j.PatternLayout
log4j.appender.miappender.layout.conversionPattern=%m%n

Una! vez! realizada! esta! operacin,! simplemente! nos! queda! modificar! nuestra! clase!
DataBaseHelper!para!que!se!encargue!de!substituir!las!lneas!de!System.out!por!el!uso!
del!api!de!log!(ver!imagen).!

Cdigo!6.19!(DataBaseHelper.java)!

public class DataBaseHelper<T> {


private static final Logger log = Logger.getLogger(DataBaseHelper.class
.getPackage().getName());
public int modificarRegistro(String consultaSQL) {

try {
.
} catch (ClassNotFoundException e) {
log.error("Error de acceso al driver" + e.getMessage());
throw new DataBaseException("Error de SQL", e);
} catch (SQLException e) {
log.error("Error de SQL" + e.getMessage());
throw new DataBaseException("Error de SQL", e);
} finally {
if (sentencia != null) {
try {
sentencia.close();
} catch (SQLException e) {
log.error("Error con la sentencia" +
e.getMessage());}
}if (conexion != null) {
try {
conexion.close();
} catch (SQLException e) {
log.error("Error cerrando la conexion"
+e.getMessage());
}}}return filasAfectadas;}

110
www.arquitecturajava.com!

Resumen!
En! este! captulo! hemos! tomado! contacto! con! el! funcionamiento! ! del! API! de! log4j! ,! el!
estndar!de!facto!de!la!plataforma!JEE!a!la!hora!de!gestionar!los!mensajes!de!log!de!una!
aplicacin!.!Lo!hemos!configurado!para!que!funcione!en!nuestro!proyecto.!

! !

111
Arquitectura*Java!

7.El#principio#SRP#y#el#modelo#MVC!
!

Hemos! ! avanzando! en! estos! captulos! en! la! construccin! de! nuestra! aplicacin,!
realizando! diversos! refactorings! que! han! mejorado! su! diseo.! En! estos! momentos!
disponemos!de!los!siguientes!componentes:!

Paginas!JSP!:!Se!encargan!de!crear!la!capa!de!presentacin!
Clases!Java!:!Se!encargan!de!crear!la!capa!de!negocio!y!persistencia!

El!uso!del!principio!DRY!nos!ha!servido!de!gua!en!el!diseo!de!nuestra!aplicacin.!Aun!
as,! quedan! ! muchas! cosas! por! hacer! y! el! principio!DRY! no! podr! ayudarnos! en! todas!
ellas.!Es!momento!de!seguir!progresando!!en!el!diseo!.Para!ello,!vamos!a!introducir!un!
nuevo!principio:!!el!principio!SRP.!

SRP! (Simple! Responsability! Principle):! toda! clase! o! componente! debe! tener! una! nica!
responsabilidad! y! todas! sus! funciones! deben! orientarse! hacia! sta.! Otra! forma! de!
enfocarlo! es! :! una! clase,! al! tener! una! nica! responsabilidad,! slo! debe! ser! alterada! a!
travs! de! un! cambio! en! dicha! responsabilidad.! Esta! definicin! puede! parecer! confusa!
en! un! primer! momento! pero! el! concepto! se! ir! aclarando! paulatinamente! con! las!
explicaciones!del!captulo.!!

112
www.arquitecturajava.com!

Objetivos!

Aplicar!el!principio!SRP!a!nuestra!aplicacin!!

Tareas!:!

1. Responsabilidades!de!la!aplicacin!y!el!principio!SRP!
2. Construccin!de!un!servlet!controlador!
3. Mapeo!de!Servlet!
4. Servlet!Controlador!y!funcionalidad!
5. Insercin!en!modelo!MVC!
6. Borrar!en!el!modelo!MVC!
7. Editar!en!el!modelo!MVC!
8. Filtrar!en!el!modelo!MVC!

1. Responsabilidades!de!la!aplicacin!y!el!principio!SRP!

Si!revisamos!!las!responsabilidades!nuestro!cdigo!fuente,!podremos!encontrarnos!con!
lo!siguiente!:!

1. Paginas!JSP!(Capa!Presentacin)!:!Responsabilidad!de!presentar!
informacin!al!usuario!
2. Clases!Java!(Capa!de!Persistencia)!:!Responsabilidad!de!persistir!los!datos!
en!la!base!de!datos.!

Parece!que!nuestras!clases!cumplen!con!los!requisitos!del!principio!SRP!ya!que!tienen!
asociada!una!nica!responsabilidad.!Ahora!bien,!si!repasamos!las!distintas!pginas!JSP!
de!nuestra!aplicacin,!podremos!encontrarnos!con!la!pgina!BorrarLibro.jsp!y!su!cdigo!
fuente:!

Cdigo!7.1!(BorrarLibro.jsp)!

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<%@page import="com.arquitecturajava.Libro"%>
<%@ page import="com.arquitecturajava.DataBaseException" %>
<%
String isbn= request.getParameter("isbn");
Libro libro= new Libro(isbn);
libro.borrar();
response.sendRedirect("MostrarLibros.jsp");
%>

113
Arquitectura*Java!

En! principio! al! ser! una! pgina! JSP! se! debera! encargar! de! presentar! informacin! al!
usuario.!Sin!embargo,!es!evidente!que!esta!pgina!no!incluye!ni!una!sola!etiqueta!html!
y! no! presenta! ninguna! informacin,! por! tanto,! su! responsabilidad! no! es! presentar!
datos.! Puede! parecernos! que! se! trata! de! una! clase! cuya! responsabilidad! es! borrar!
datos,!sin!embargo,!si!revisamos!el!propio!cdigo!de!la!pgina,!veremos!como!la!pgina!
instancia!un!objeto!de!tipo!Libro!y!es!ste!el!encargado!de!borrar!el!registro!de!la!base!
de!datos!(ver!cdigo).!

Cdigo!7.2!!(BorrarLibro.jsp)!

Libro libro= new Libro(isbn);


libro.borrar();
! !

!As! pues! cul! es! realmente! la! ! responsabilidad! de! esta! pgina?! Aparentemente! no!
tiene! responsabilidades,! pero! si! as! fuera,! podramos! eliminarla! sin! perjuicio! para!
nuestra! aplicacin.! Es! evidente! que! si! eliminamos! la! pgina,! no! podremos! borrar! los!
registros.! sto! se! debe! a! que! la! pagina! s! tiene! una! responsabilidad! y! sta! es! la! de!
control.!Es!decir!,se!encarga!de!definir!qu!pgina!se!carga!en!cada!momento,!as!como!
qu!clase!y!qu!mtodo!se!invoca!(ver!cdigo).!

As! ,nos! encontramos! con! una! nueva! responsabilidad! dentro! de! nuestra! aplicacin:! el!
control.!Esta!responsabilidad!no!es!expresada!nicamente!por!la!pgina!BorrarLibro.jsp.!
sino! que! prcticamente! por! todas! las! pgina! de! nuestra! aplicacin.! Por! ejemplo! la!
pgina! MostrarLibros.jsp! se! encarga! de! controlar! a! qu! mtodos! de! la! clase! Libro!
debemos! invocar! para! presentar! los! datos.! As! pues! la! responsabilidad! de! control! se!
encuentra!distribuida!entre!distintas!pgina!de!diversas!maneras!(ver!imagen).!

114
www.arquitecturajava.com!

Ahora! bien,! en! el! caso! de! la! pgina! MostrarLibros.jsp! nos! encontramos! ante! un! claro!
incumplimiento! del! principio! SRP! ya! que! la! pgina! en! cuestin! se! hace! cargo! de! dos!
responsabilidades! claramente! independientes:! la! de! control! y! la! de! presentacin! (ver!
imagen).!

Para! solventar! este! problema,! debemos! extraer! la! responsabilidad! de! la! pgina! ! y!
ubicarla! en! otro! componente;! pero! no! podr! ser! ninguno! de! los! componentes! que!
actualmente! tenemos! definidos! ya! que! stos! ya! tienen! asociada! una! responsabilidad:!
las! pginas! la! presentacin! y! las! clases! la! de! persistencia.! Para! poder! extraer! esta!
responsabilidad! tendremos! que! apoyarnos! en! un! nuevo! tipo! de! componente! :! un!!
Servlet.!

115
Arquitectura*Java!

2. Construir!un!servlet!controlador!

Un! servlet! es! una! clase! Java! que! es! capaz! de! generar! cdigo! html! como! lo! hace! una!
pginas!JSP!pero!tambin!es!capaz!de!gestionar!la!comunicacin!entre!varias!de!estas!
pginas.!Esta!capacidad!es!la!que!vamos!a!utilizar!en!nuestro!caso!a!la!hora!de!reubicar!
la!responsabilidad!de!control!(ver!imagen).!

Una! vez! clarificado! que! el! servlet! ser! el! encargado! de! la! responsabilidad! de! control,!
estaremos!cumpliendo!con!el!principio!SRP!en!el!cul!cada!componente!slo!tiene!una!
nica! responsabilidad.! Vamos! a! pasar! ya! a! construir! el! servlet! e! implementar! una!
primera!versin!de!su!mtodo!doGet()!que!ser!el!encargado!de!la!comunicacin!entre!
las!distintas!pginas.!

Cdigo!7.3!(ControladorLibros.java)!

package com.arquitecturajava.aplicacion;
//omitimos imports
public class ControladorLibros extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws
ServletException,IOException {
RequestDispatcher despachador = null;
List<Libro> listaDeLibros = Libro.buscarTodos();
List<String> listaDeCategorias = Libro.buscarTodasLasCategorias();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
despachador = request.getRequestDispatcher("MostrarLibros.jsp");
despachador.forward(request, response);

}
}
!

116
www.arquitecturajava.com!

3. Mapeo!de!Servlet!

Una! vez! creado! el! servlet,! debemos! aadir! un! mapeo! de! ste! a! travs! del! fichero!
web.xml! para! dejarlo! completamente! configurado! y! poder! acceder! al! mismo! desde! la!
siguiente!url!/ControladorLibros.do!

Cdigo!7.4!(web.xml)!

<servlet>
<description></description>
<display-name>ControladorLibros</display-name>
<servlet-name>ControladorLibros</servlet-name>
<servlet-class>com.arquitecturajava.aplicacion.ControladorLibros</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ControladorLibros</servlet-name>
<url-pattern>/ControladorLibros</url-pattern>
</servlet-mapping>
!

4.!Servlet!Controlador!y!funcionalidad!

Realizadas!estas!dos!operaciones!(construccin!y!mapeo),!es!momento!de!explicar!cada!
una!de!las!lneas!que!este!servlet!contiene,!las!cules!se!encargan!de!la!funcionalidad!
de!control!.!Vamos!!a!!comenzar!!con!las!dos!primeras:!

Cdigo!7.5!(ControladorLibros.java)!

List<Libro> listaDeLibros = Libro.buscarTodos();


List<String> listaDeCategorias = Libro.buscarTodasLasCategorias();
!

Estas!lneas!!delegan!en!la!capa!de!persistencia!y!cargan!la!informacin!que!la!pgina!
MostrarLibros.jsp! necesita! en! dos! variables:! listaDeLibros! y! listaDeCategorias,!
definiendo! parte! de! la! responsabilidad! de! control.! ! Vamos! a! analizar! las! siguientes!
lneas.!

Cdigo!7.6!(ControladorLibros.java)!

request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
!

117
Arquitectura*Java!

Estas! lneas! se! encargan! de! almacenar! ambas! listas! en! el! objeto! request,! que! es!
accesible!tanto!por!el!servlet!controlador!como!por!las!paginas!JSP!y!hace!una!funcin!
de!intermediario!(ver!imagen).!

Una!vez!el!objeto!request!incluye!ambas!listas!,!usaremos!el!siguiente!bloque!de!cdigo!
para!redirigir!la!peticin!hacia!la!pagina!MostrarLibros.jsp.!

Cdigo!7.7!(ControladorLibros.java)!

despachador = request.getRequestDispatcher("MostrarLibros.jsp");
despachador.forward(request, response);
!

Realizado!este!ultimo!paso!,!las!paginas!jsp!no!necesitan!ya!usar!para!nada!la!capa!de!
persistencia!y!pueden!obtener!la!informacin!que!necesitan!mostrar!del!propio!objeto!
request!que!sirve!de!intermediario!(ver!imagen).!

118
www.arquitecturajava.com!

Cdigo!7.8!(MostrarLibro.jsp)!

<select name="categoria">
<option value="seleccionar">seleccionar</option>
<%
List<String> listaDeCategorias=null;
listaDeCategorias=(List<String>)request.getAttribute("listaDeCategorias")
for(String categoria:listaDeCategorias) {
if (categoria.equals(request.getParameter("categoria"))){
%>
<option value="<%=categoria%>" selected ><%=categoria%></option>
<% } else { %>
<option value="<%=categoria%>"><%=categoria%></option>
<%} }%>
</select>
<input type="submit" value="filtrar">
</form>
<br/>
<%
List<Libro> listaDeLibros
=(List<Libro>)request.getAttribute("listaDeLibros");
for(Libro libro:listaDeLibros){ %>
<%=libro.getIsbn()%>
<%=libro.getTitulo()%>
<%=libro.getCategoria()%>
<a href="BorrarLibro.do?isbn=<%=libro.getIsbn()%>">Borrar</a>
<a href="FormularioEditarLibro.do?isbn=<%=libro.getIsbn()%>">Editar</a>
<br/>
<% }
%>
!

Una!vez!realizados!estos!refactorings!hemos!aadido!un!nuevo!componente!a!nuestra!
aplicacin! que! se! encarga! del! control! de! la! misma.! A! continuacin! se! muestra! un!
diagrama!con!la!nueva!arquitectura!de!la!aplicacin!y!las!distintas!responsabilidades.!

119
Arquitectura*Java!

Hemos! usado! el! principio! SRP! para! separar! responsabilidades! en! la! aplicacin! y! de!
forma!indirecta!hemos!diseado!una!arquitectura!que!cumple!con!el!patrn!MVC!en!el!
cul!cada!componente!tiene!un!rol!cerrado!(ver!imagen).!

Vamos! a! seguir! avanzando! en! la! construccin! de! un! Modelo! MVC! para! nuestra!
aplicacin.!

120
www.arquitecturajava.com!

4. Insercin!con!modelo!MVC!

En!esta!tarea!vamos!a!modificar!la!aplicacin!para!que!tanto!la!parte!de!mostrar!como!
la! de! insertar! estn! construidas! sobre! un! modelo! MVC.! Para! ello! definiremos! las!
siguientes!tres!URLs!asociadas!al!controlador.!

MostrarLibros.do!
FormularioLibroInsertar.do!
InsertarLibro.do!

Dependiendo! de! la! URL! que! se! solicite! al! Controlador! por! ejemplo!
ControladorLibros/MostrarLibros.do!!el!controlador!realizara!una!operacin!u!otra.!Para!
clarificar!el!funcionamiento!del!controlador!vamos!a!mostrar!un!diagrama!con!el!flujo!
de!trabajo!cuando!el!usuario!pulsa!el!botn!de!insertar!en!la!pagina!MostrarLibros.jsp!

Vamos!a!comentar!el!diagrama!paso!a!paso!para!clarificar!del!todo!cul!es!la!lgica!que!
define!la!funcionalidad!de!mostrar!y!insertar!libros.!!

1. Pulsamos! en! el! botn! de! insertar! libro! y! solicitamos! la! siguiente! url! al!
controlador!FormularioLibroInsertar.do!
2. El!controlador!invoca!a!la!clase!Libro!y!carga!la!lista!de!categoras!!

121
Arquitectura*Java!

3. El!controlador!nos!redirige!a!la!pagina!FormularioLibro.jsp!y!muestra!la!lista!
de!categoras!cargada.!
4. Rellenamos! el! formulario! e! invocamos! al! controlador! pasando! como! url!
insertarLibro.do!
5. El! controlador! invoca! la! la! clase! Libro! e! inserta! los! datos! en! la! base! de!
datos.! Una! vez! realizada! esta! operacin,! invoca! los! mtodos! de!
buscarTodos!y!buscarCategorias!
6. El! controlador! nos! redirige! a! MostrarLibros.do! que! carga! la! pagina!
MostrarLibros.jsp!con!los!datos!que!acabamos!de!cargar!

Una!vez!aclaradas!cules!son!las!distintas!peticiones!que!realizaremos!en!esta!tarea!al!
servlet!Controlador,!vamos!a!ver!el!cdigo!fuente!del!mtodo!doGet()!modificado!para!
incluir!las!distintas!opciones:!

Cdigo!7.!9!(ControladorLibros.java)!

RequestDispatcher despachador = null;


if (request.getServletPath().equals("/MostrarLibros.do")) {
List<Libro> listaDeLibros = Libro.buscarTodos();
List<String> listaDeCategorias =
Libro.buscarTodasLasCategorias();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
despachador = request.getRequestDispatcher("MostrarLibros.jsp");
} elseif (request.getServletPath().equals("/FormularioInsertarLibro.do")) {
List<String> listaDeCategorias=null;
listaDeCategorias=Libro.buscarTodasLasCategorias();
request.setAttribute("listaDeCategorias", listaDeCategorias);
despachador=request.getRequestDispatcher("FormularioInsertarLibro.jsp");
} else {
String isbn = request.getParameter("isbn");
String titulo = request.getParameter("titulo");
String categoria = request.getParameter("categoria");
Libro libro = new Libro(isbn, titulo, categoria);
libro.insertar();
despachador = request.getRequestDispatcher("MostrarLibros.do");
}
!

Tras!modificar!el!servlet,!podremos!darnos!cuenta!de!que!toda!la!funcionalidad!que!se!
encontraba!ubicada!en!la!pgina!InsertarLibro.jsp!se!ha!reubicado!a!nivel!del!servlet!y!la!
pgina!insertarLibro.jsp;!as!podr!ser!eliminada!(ver!imagen).!

122
www.arquitecturajava.com!

5. Borrar!en!modelo!MVC!

Es!el!momento!de!progresar!y!aplicar!el!modelo!MVC!a!la!funcionalidad!de!borrar.!Para!
ello!aadiremos!una!nueva!URL!a!nuestro!modelo.!

BorrarLibro.do!!

El!cdigo!que!se!encargar!de!gestionar!la!peticin!de!esta!url!es!el!siguiente:!!

Cdigo!!7.10!(ControladorLibros.java)!

else {
String isbn = request.getParameter("isbn");
Libro libro = new Libro(isbn);
libro.borrar();
despachador = request.getRequestDispatcher("MostrarLibros.do");
}
!

Para!que!el!cdigo!funcione!correctamente,!debemos!modificar!el!enlace!de!la!pagina!
MostrarLibros.jsp!(ver!imagen).!
123
Arquitectura*Java!

Cdigo!7.11!(ControladorLibros.java)!

<a href="BorrarLibro.do?isbn=<%=libro.getIsbn()%>">Borrar</a>
!

A!continuacin!se!muestra!el!nuevo!flujo!de!la!aplicacin.!

Esta!es!la!explicacin!detallada!de!!cada!una!de!las!peticiones:!

1. Pulsamos!en!el!botn!de!borrar!a!nivel!de!uno!de!los!registros!e!invocamos!al!
controlador!con!BorrarLibro.do!
2. El! controlador! invoca! a! la! clase! active! record! a! su! mtodo! borrar! y! borra! el!
registro.! Una! vez! hecho! sto,! invoca! buscarTodos! y! buscarCategorias! para!
cargar!los!datos!necesarios.!
3. El!controlador!nos!redirige!a!la!pgina!MostrasLibros.jsp!

Una!vez!completada!la!tarea!de!borrar!a!travs!del!modelo!MVC!,!nos!daremos!cuenta!
de!que!la!pagina!BorrarLibro.jsp!ya!no!es!necesaria!(ver!imagen).!!

124
www.arquitecturajava.com!

6. Editar!en!modelo!MVC!

La!tarea!de!editar!presenta!grandes!similitudes!con!la!tarea!de!insertar!y!nos!permitir!
de! nuevo! eliminar! otra! pgina! (EditarLibro.jsp)! de! la! aplicacin.! Para! construir! la!
funcionalidad! de! edicin! necesitaremos! aadir! una! nueva! URL! a! la! gestin! del!
controlador! FormularioEditarLibro.do! que! nos! redirigir! a! la! pagina!
FormularioEditarLibro.do.!Vamos!a!ver!a!continuacin!el!cdigo:!

Cdigo!!7.12!(ControladorLibros.java)!

} else if (request.getServletPath().equals("/FormularioEditarLibro.do")){
String isbn = request.getParameter("isbn");
List<String> listaDeCategorias = Libro.buscarTodasLasCategorias();
Libro libro = Libro.buscarPorClave(request.getParameter("isbn"));
request.setAttribute("listaDeCategorias", listaDeCategorias);
request.setAttribute("libro", libro);
despachador = request.getRequestDispatcher("FormularioEditarLibro.jsp");
!

Una! vez! creado! este! bloque! de! cdigo! la! aplicacin! ha! de! ser! capaz! de! modificar! los!
datos!existentes!en!el!formulario!y!salvar!los!cambios!(ver!imagen).!

125
Arquitectura*Java!

A! continuacin! se! muestra! el! bloque! de! cdigo! que! se! encargara! de! aceptar! los!
cambios!y!salvarlos.!

}else {

String isbn = request.getParameter("isbn");


String titulo = request.getParameter("titulo");
String categoria = request.getParameter("categoria");
Libro libro = new Libro(isbn, titulo, categoria);
libro.salvar();
despachador = request.getRequestDispatcher("MostrarLibros.do");

}
!

Vamos!a!!explicar!minuciosamente!cada!una!de!las!peticiones!de!la!tarea!de!edicin.!

1. Pulsamos!en!el!botn!de!editar!!a!nivel!de!uno!de!los!registros!e!invocamos!al!
controlador!con!FormularioEditarLibro.do!

126
www.arquitecturajava.com!

2. El!controlador!invoca!a!la!clase!Libro!a!su!mtodo!buscarPorClave!
3. El!controlador!nos!redirige!a!la!pagina!FormularioEditarLibro.jsp,!mostrando!los!
datos!a!modificar.!
4. Modificamos!los!datos!del!formulario,!pulsamos!al!botn!de!salvar!e!invocamos!
a!SalvarLibro.do.!
5. El! controlador! invoca! al! mtodo! salvar! para! actualizar! los! datos! del! Libro.!
Despus! de! hacer! esto,! como! siempre! invoca! buscarTodos! y! buscarCategorias!
para!cargar!los!datos!que!la!pgina!MostrarLibros.jsp!necesita.!
6. El!controlador!nos!redirige!a!MostrarLibros.jsp!

Una! vez! hemos! terminado! de! gestionar! la! tarea! de! edicin,! nos! sovrar! la! pagina!
SalvarLibro.jsp!ya!que!su!funcionalidad!la!cubre!el!controlador,!por!lo!tanto!podremos!
eliminarla!(ver!imagen).!

7. Filtrado!en!Modelo!MVC!

Complementando! a! las! modificaciones! anteriores! nos! encontramos! con! la! tarea! de!
filtrado.! sta! permite! organizar! y! seleccionar! los! libros! por! categora! para! ello!
aadiremos!una!nueva!url!que!acceda!al!controlador!y!sea!la!encargada!de!filtrar.!

Filtrar.do!
127
Arquitectura*Java!

Una!vez!aadida!esta!url!y!modificada!la!pagina!MostrarLibros.jsp,!podremos!aadir!el!
siguiente!bloque!de!cdigo!al!controlador! de! tal! forma! que! se! encargue! de! realizar! el!
filtrado.!

Cdigo!7.13!(ControladorLibros.java)!

List<Libro> listaDeLibros = null;


List<String> listaDeCategorias = Libro.buscarTodasLasCategorias();
if (request.getParameter("categoria") == null ||
request.getParameter("categoria").equals("seleccionar")) {
listaDeLibros = Libro.buscarTodos();
} else {
listaDeLibros = Libro.buscarPorCategoria(request
.getParameter("categoria"));
}
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
despachador = request.getRequestDispatcher("MostrarLibros.jsp");
}
!

A!continuacin!se!muestra!un!diagrama!de!flujo!con!la!lgica!que!se!ejecuta!durante!la!
operacin!de!filtrado.!

128
www.arquitecturajava.com!

Cada!una!de!las!peticiones!de!la!tarea!de!edicin!en!explicacin!pormenorizada:!

1. Pulsamos!en!el!botn!de!filtrar!!!a!nivel!del!desplegable.!
2. El!controlador!invoca!a!la!clase!Libro!a!su!mtodo!buscarPorCategora.!Una!vez!
hemos!esto,!!el!Controlador!invoca!al!mtodo!buscarCategorias!para!cargar!los!
datos!necesarios!para!la!pra!MostrarLibros.jsp.!
3. El!controlador!nos!redirige!a!la!pgia!MostrarLibros.jsp,!aplicando!el!filtro.!

Hemos!terminado!de!modificar!las!paginas!y!de!construir!nuestro!controlador!usando!el!
principio! SRP! y! reubicando! las! responsabilidades! de! control! a! nivel! del! servlet!
controlador! .A! continuacin! se! muestra! el! cdigo! fuente! del! servlet! completo! para!
ayudar!a!clarificar!todas!las!modificaciones!realizadas.!

public class ControladorLibros extends HttpServlet {


protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher despachador = null;

if (request.getServletPath().equals("/MostrarLibros.do")) {

List<Libro> listaDeLibros = Libro.buscarTodos();


List<String> listaDeCategorias = Libro.
buscarTodasLasCategorias();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
despachador = request.
getRequestDispatcher("MostrarLibros.jsp");
} else if (request.getServletPath().equals(
"/FormularioInsertarLibro.do")) {

List<String> listaDeCategorias = null;


listaDeCategorias = Libro.buscarTodasLasCategorias();
request.setAttribute("listaDeCategorias", listaDeCategorias);
despachador = request
.getRequestDispatcher("FormularioInsertarLibro.jsp");
} else if (request.getServletPath().equals("/InsertarLibro.do")) {

String isbn = request.getParameter("isbn");


String titulo = request.getParameter("titulo");
String categoria = request.getParameter("categoria");
Libro libro = new Libro(isbn, titulo, categoria);
libro.insertar();
despachador = request.
getRequestDispatcher("MostrarLibros.do");
} else if (request.getServletPath().equals("/BorrarLibro.do")) {
String isbn = request.getParameter("isbn");
Libro libro = new Libro(isbn);
libro.borrar();

129
Arquitectura*Java!

despachador = request.
getRequestDispatcher("MostrarLibros.do");
} else if (request.getServletPath().equals("/FormularioEditarLibro.do")) {
String isbn = request.getParameter("isbn");
List<String> listaDeCategorias = Libro.
buscarTodasLasCategorias();
Libro libro = Libro
.buscarPorClave(request.getParameter("isbn");
request.setAttribute("listaDeCategorias", listaDeCategorias);
request.setAttribute("libro", libro);

despachador = request
.getRequestDispatcher("FormularioEditarLibro.jsp");

} else if (request.getServletPath().equals("/SalvarLibro.do")) {

String isbn = request.getParameter("isbn");


String titulo = request.getParameter("titulo");
String categoria = request.getParameter("categoria");
Libro libro = new Libro(isbn, titulo, categoria);
libro.salvar();
despachador = request.
getRequestDispatcher("MostrarLibros.do");
} else {
List<Libro> listaDeLibros = null;
List<String> listaDeCategorias =
.Libro.buscarTodasLasCategorias();
if (request.getParameter("categoria") == null
||
..request.getParameter("categoria").equals("seleccionar")) {
listaDeLibros = Libro.buscarTodos();
} else {
listaDeLibros = Libro.buscarPorCategoria(request
.getParameter("categoria"));
}
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
despachador = request.
getRequestDispatcher("MostrarLibros.jsp");
}
despachador.forward(request, response);
}
}
!
!

!!
!
130
www.arquitecturajava.com!

Resumen!
Una! vez! finalizado! el! controlador,! hemos! reubicado! las! responsabilidades! de! nuestra!
aplicacin,!organizndolas!de!acuerdo!al!principio!SRP.!Como!resultado,!hemos!podido!
separar!mejor!cada!una!de!las!capas!y!eliminar!parte!de!los!ficheros!JSP!que!tenamos.!
Por! ultimo,! queda! por! ver! como! ha! quedado! la! estructura! fsica! de! ficheros! una! vez!
completada!la!evolucin!!a!un!modelo!MVC!.!La!siguiente!imagen!muestra!el!resultado.!

!
131
Arquitectura*Java!

8.JSTL!
!

Acabamos!de!aplicar!el!patrn!MVC!a!nuestra!aplicacin,!apoyndonos!en!el!principio!
SRP! ,aun! as! un! desarrollador! puede! decidir! no! usar! este! patrn! de! diseo! y! seguir!
usando! ! scriptlet! de! JSP! en! sus! pginas.! Para! evitar! este! problema,! en! este! nuevo!
captulo!!modificaremos!las!pginas!de!nuestra!aplicacin!para!que!use!Java!Standard!
Tag! Library! (JSTL)! como! librera! de! etiquetas,! la! cul! nos! ayudar! a! simplificar! el!
desarrollo!y!evitar!el!uso!de!scriptlet,!obteniendo!unas!paginas!ms!claras.!

Objetivos:!

Utilizar!JSTL!en!la!aplicacin!

Tareas:!

1. Instalacin!de!JSTL!
2. Introduccin!a!JSTL!
3. Etiquetas!Bsicas!JSTL!
4. Modificar!MostrarLibro.jsp!
5. Modificar!FormularioInsertarLibro.jsp!
6. Modificar!FormularioEditarLibro.jsp!

132
www.arquitecturajava.com!

1. Instalacin!de!JSTL!

Antes!de!comenzar!a!introducirnos!en!JSTL,!necesitamos!instalar!libreras!adicionales!a!
nuestro!servidor!Tomcat.!Para!ello!accederemos!a!la!siguiente!url.!

http://jstl.java.net/download.html!

De!la!cul!podremos!obtener!las!siguientes!libreras!

jstl.jar!
standard.jar!

Una!vez!obtenidas!las!libreras,!las!ubicaremos!en!el!directorio!WEBtINF/lib!de!nuestra!
aplicacin!(ver!imagen).!

Realizado! este! paso,! habremos! terminado! de! instalar! JSTL! en! nuestra! aplicacin! y!
podremos!comenzar!a!trabajar!con!ello.!

2. Introduccin!a!JSTL!

En!estos!momentos!nuestras!paginas!JSP!mezclan!el!uso!de!etiquetas!con!scriptlet.!JSTL!
nos!permitir!homogeneizar!este!comportamiento,!permitindonos!!el!uso!de!etiquetas!
html! y! la! substitucin! del! scriptlet! por! un! conjunto! de! etiquetas! de! servidor,! de! tal!
forma!que!las!nuevas!paginas!JSP!nicamente!estarn!compuestas!por!etiquetas!!(ver!
imagen).!

133
Arquitectura*Java!

A! continuacin! se! muestra! un! ejemplo! sencillo! de! las! diferencias! entre! ambas!
tecnologas!a!la!hora!de!imprimir!informacin!html!

JSP!!

Cdigo!8.1:!!

<%if (edad>18) {%>


Eres una persona adulta con edad <%=edad%>
<%}%>
!

JSTL!!

Cdigo!8.2:!!

<c:if test=${edad>18}>
Eres una persona adulta ${edad}
</c:if>
!

Como!podemos!ver!con!JSTL!nicamente!tenemos!grupos!de!etiquetas!y!texto!plano!lo!
que!har!ms!sencillo!a!los!maquetadores!trabajar!con!las!pginas.!

3. Etiquetas!Bsicas!JSTL!

Antes! de! modificar! nuestra! aplicacin! para! que! soporte! JSTL,! vamos! a! explicar! las!
etiquetas!elementales!de!JSTL!que!nuestra!aplicacin!va!a!necesitar.!

134
www.arquitecturajava.com!

La!siguiente!etiqueta!imprime!!una!variable!JSP!en!la!pgina:!

Cdigo8.!3:!!

${variable}
!

La!etiqueta!<forEach>!recorre!coleccin!de!objetos!ubicados!en!una!lista!e!imprime!sus!
propiedades!!

Cdigo!8.4:!!

<c:forEach var="objeto" items="${lista}">


${objeto.propiedad}
</c:forEach>
!

Se! encarga! de! imprimir! un! bloque! de! informacin! dependiente! de! una! condicin!
predeterminada.!

Cdigo!8.5:!!

<c:if test=${edad>30}>
Eres una persona adulta ${edad}
</c:if>
!

Una!vez!vistas!las!etiquetas!esenciales,!vamos!a!modificar!nuestras!pginas.!

4. Modificar!MostrarLibro.jsp!

A! continuacin! vamos! a! usar! dos! etiquetas! <c:forEach>! para! modificar! la! pagina! y!
eliminar!completamente!el!scriptlet.!A!continuacin!se!muestra!el!cdigo.!

135
Arquitectura*Java!

Cdigo!8.6:!(MostrarLibro.jsp)!

<form name="filtroCategoria" action="filtrar.do"><select


name="categoria">
<option value="seleccionar">seleccionar</option>
<c:forEach var="categoria" items="${listaDeCategorias}">
<option value="${categoria}">${categoria}</option>
</c:forEach>
</select><input type="submit" value="filtrar"></form>
<br />
<c:forEach var="libro" items="${listaDeLibros}">
${libro.isbn}${libro.titulo}${libro.categoria}
<a href="BorrarLibro.do?isbn=${libro.isbn}">borrar</a>
<a href="FormularioEditarLibro.do?isbn=${libro.isbn}">editar</a>
<br />
</c:forEach>
<a href="FormularioInsertarLibro.do">InsertarLibro</a>
!

Despus!de!realizar!esta!tarea,!pasaremos!a!modificar!la!pgina!FormularioInsertar.jsp.!

5. Modificar!Formulario!Insertar!

Ser! suficiente! con! crear! otro! bucle! <c:forEach>! encargado! de! cargar! la! lista! de!
categoras.!

Cdigo!8.7:!(FormularioLibro.jsp)!

<form id="formularioInsercion" action="InsertarLibro.do">


<fieldset><legend>Formularioaltalibro</legend>
<p><label for="isbn">ISBN:</label>
<input type="text" id="isbn" name="isbn" /></p>
<p><label for="titulo">Titulo:</label>
<input type="text" id="titulo" name="titulo" /></p>
<p><label for="categoria">Categoria :</label>
<select name="categoria">
<c:forEach var="categoria" items="${listaDeCategorias}">
<option value="${categoria}">${categoria}</option>
</c:forEach>
</select><br />
</p><p><input type="submit" value="Insertar" /></p>
</fieldset>
</form>
!

136
www.arquitecturajava.com!

Finalizada!esta!operacin,!nos!queda!una!ltima!pgina!por!modificar!!

6. Modificar!FormularioEditarLibro.jsp!

Esta!pgina!es!muy!similar!a!la!pgina!anterior,!aunque!tendr!ms!bloque!!de!cdigo!
JSTL!al!tener!que!presentar!el!formulario!con!la!informacin!para!editar!ya!cargada.!

Cdigo!8!8:!(FormularioLibroEdicion.jsp)!

<form id="formularioEdicion" action="ModificarLibro.do">


<fieldset><legend>Formularioaltalibro</legend>
<p><label for="isbn">ISBN:</label><input type="text" id="isbn"
name="isbn" value="${libro.isbn}" /></p>
<p><label for="titulo">Titulo:</label><input type="text"
id="titulo" name="titulo" value="${libro.titulo}" /></p>
<p><label for="categoria">Categoria :</label><select
name="categoria">
<c:forEach var="categoria" items="${listaDeCategorias}">
<option value="${categoria}">${categoria}</option>
</c:forEach>
</select><br />
</p>
<p><input type="submit" value="Salvar" /></p>
</fieldset>
</form>
!

Resumen!
Una!vez!finalizadas!las!modificaciones,!nuestra!aplicacin!ha!dejado!de!usar!scriptlet!en!
el! cdigo! de! las! pginas! JSP! y! utiliza! etiquetas! JSTL,! reforzando! el! modelo! MVC! que!
construimos!en!el!captulo!anterior.!

137
Arquitectura*Java!

9.El#principio#OCP#y#modelo#MVC#2!
!
!
!
!
!
!
!
!
!
!
!
!
En!los!dos!captulos!anteriores!hemos!modificado!nuestra!aplicacin!para!que,!usando!
el! principio! SRP,! la! divisin! de! responsabilidades! sea! mas! natural! y! use! ! JSTL! como!
tecnologa! de! capa! de! presentacin.! En! este! captulo! introduciremos! ! otro! principio!
importante:!el!principio!OCP!o!principio!de!apertura!y!cierre!cuya!definicin!es:!
!
OCP!(Open!Closed!Principle):El!principio!OCP!o!principio!de!apertura!y!cierre,!se!define!
como:! todo! cdigo! desarrollado! para! una! aplicacin! debe! estar! cerrado! a! las!
modificaciones!y!abierto!a!la!extensibilidad.!Expresado!de!otra!manera:!debemos!poder!
aadir!nueva!funcionalidad!!a!la!aplicacin!sin!tener!que!alterar!el!cdigo!ya!construido.!
Seguidamente!nos!encargaremos!de!aplicar!este!principio!en!nuestra!aplicacin.!
!
Objetivos!!
Aplicar!el!principio!OCP!a!nuestra!aplicacin!
!
!
!
Tareas!!!
1. El!principio!OCP!y!el!Controlador!!
2. El!principio!OCP!y!el!patron!Command!
3. Creacin!de!una!accion!principal!
4. Crear!una!jerarquia!de!acciones!
5. Api!de!reflection!y!principio!OCP!
!
!
!

138
www.arquitecturajava.com!

1. El!principio!OCP!y!el!Controlador!

!
En! estos! momentos! tenemos! construida! una! aplicacin! sobre! el! modelo! MVC! y! su!
diseo! es! bastante! slido.! Despus! de! conocer! la! definicin! del! principio! OCP! nos!
percatamos!de!que!cada!vez!que!aadimos!una!mnima!funcionalidad!nueva!a!nuestra!
aplicacin!estamos!obligados!a!modificar!el!Servlet!controlador!de!esta!y!aadir!una!o!
varias!sentencias!if!else!if!!que!implementen!la!nueva!funcionalidad!(ver!imagen).!
!

!
!
As!pues!parece!claro!que!el!controlador!es!un!elemento!que!no!est!para!nada!cerrado!
a! las! modificaciones,! sino! ms! bien! al! contrario:! cualquier! modificacin! por! pequea!
que! sea! de! la! aplicacin! afecta! directamente! al! controlador! y! clarifica! que! no! cumple!
con!el!principio!OCP!(ver!imagen).!
!

139
Arquitectura*Java!

!
!
!
!

2. El!principio!OCP!y!el!patrn!Command!

!
Vamos!a!apoyarnos!en!el!principio!OCP!para!comenzar!a!redisear!el!controlador!de!tal!
forma! que! podamos! aadir! nueva! funcionalidad! a! la! aplicacin! sin! que! ste! ! se! vea!
afectado.!Para!redisear!el!controlador!y!que!pueda!cumplir!con!el!principio!OCP!vamos!
extraer! el! concepto! de! Accin/Tarea! del! mismo! y! ubicarlo! en! una! jerarqua! de! clases!
completamente!nueva!.!Cada!una!de!estas!clases!tendr!las!siguientes!caractersticas:!
!
1. Heredarn!de!una!clase!comn!denominada!Accin.!
2. Todas!dispondrn!del!mtodo!ejecutar!en!el!cual!ejecutaran!la!funcionalidad!a!
ellas!asignada.!
3. Tendrn!un!nombre!que!haga!referencia!a!la!funcionalidad!que!se!encargan!de!
ejecutar.!
!
A!continuacin!se!muestra!la!imagen!con!una!parte!de!la!jerarqua!de!las!acciones.!
!
!

140
www.arquitecturajava.com!

!
!
En!principio!nos!puede!parecer!que!se!trata!de!un!sencillo!grupo!de!clases!sin!embargo!
la! jerarqua! de! acciones! se! construir! apoyndonos! en! un! patrn! de! diseo!
denominado!Comando.!Este!patrn!obliga!cada!clase!a!definir!un!mtodo!ejecutar!en!el!
cul!ubicaremos!la!funcionalidad!que!deseamos!(ver!imagen).!

!
!
Definida! la! jerarqua! de! clases,! podremos! extraer! la! funcionalidad! que! se! encuentra!
ubicada!en!el!controlador!y!reubicarla!en!el!mtodo!ejecutar!de!cada!una!de!las!clases!.!
A!partir!de!este!momento,!el!controlador!delegar!en!las!acciones!(ver!imagen).!
!

141
Arquitectura*Java!

!
!
!

3. Creacin!de!una!accin!principal!

!
Definido!el!nuevo!funcionamiento!del!controlador,!vamos!a!ver!el!cdigo!fuente!de!la!
clase!Accin.!
!
Cdigo!9.1:!(Accion.java)!

package com.arquitecturajava.aplicacion.controlador.acciones;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public abstract class Accion {


public abstract String ejecutar(HttpServletRequest request,
HttpServletResponse response);
}

!
!
Creada!esta!clase,!podemos!ver!como!el!mtodo!ejecutar!recibe!dos!parmetros.!
!
HttpServletRequest!
HttpServletResponse!

142
www.arquitecturajava.com!

!
Son! los! mismos! parmetros! que! utilizamos! a! nivel! del! servlet.! De! esta! forma! nuestro!
servlet! controlador! podr! delegar! en! el! conjunto! de! acciones! que! vemos! a!
continuacin.!
!

!
!

4. Crear!jerarqua!de!acciones!

!
A!partir!de!ahora!usaremos!acciones!para!implementar!la!funcionalidad!de!cada!una!de!
los!distintos!bloques!de!cdigo.!Vamos!a!ver!el!cdigo!fuente!de!una!accin!en!concreto!
que!nos!ayude!a!entender!qu!parte!de!la!funcionalidad!existente!cubren!las!acciones!y!
que! otra! funcionalidad! cubre! el! controlador.! A! continuacin! se! muestra! el! cdigo!
fuente!de!la!Accion!InsertarLibro.!
!
Cdigo!9.2:!(InsertarLibroAccion.java)!

public class InsertarLibroAccion extends Accion{


public String ejecutar(HttpServletRequest request,
HttpServletResponse response) {
String isbn = request.getParameter("isbn");
String titulo = request.getParameter("titulo");
String categoria = request.getParameter("categoria");
Libro libro = new Libro(isbn, titulo, categoria);
libro.insertar();
return "MostrarLibros.do";
}

143
Arquitectura*Java!

!
Hemos!creado!cada!una!de!las!distintas!acciones!extrayendo!el!cdigo!que!exista!en!las!
clusulas! iftelseiftelse! del! mtodo! doGet()! del! controlador,! quedando! ste! muy!
simplificado! ya! que! nicamente! tiene! que! decidir! qu! accin! crea! y! luego! invocar! al!
mtodo!ejecutar!de!sta!(ver!cdigo).!
!
Cdigo!9.3:!(ControladorLibros.java)!

protected void doGet(HttpServletRequest request,


HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher despachador = null;
Accion accion = null;
if (request.getServletPath().equals("/MostrarLibros.do")) {
accion = new MostrarLibrosAccion();
} elseif (request.getServletPath().equals(
"/FormularioInsertarLibro.do")) {
accion = new FormularioInsertarLibroAccion();
} elseif (request.getServletPath().equals("/InsertarLibro.do")) {
accion = new InsertarLibroAccion();
} elseif (request.getServletPath().equals("/BorrarLibro.do")) {
accion = new BorrarLibroAccion();
} elseif (request.getServletPath().equals("/FormularioEditarLibro.do")) {
accion = new FormularioEditarLibroAccion();
} elseif (request.getServletPath().equals("/ModificarLibro.do")) {
accion = new ModificarLibroAccion();
} else {
accion = new FiltrarLibrosPorCategoriaAccion();
}
despachador = request.getRequestDispatcher(
.accion.ejecutar(request,response));
despachador.forward(request, response);
}
!
Con! este! refactoring! hemos! mejorado! bastante! nuestra! aplicacin! y! aunque! cada! vez!
que! aadimos! una! nueva! funcionalidad,! debemos! modificar! el! controlador,! la! mayor!
parte!del!nuevo!cdigo!se!encuentra!en!cada!una!de!las!acciones.!!
!
El! siguiente! paso! a! realizar! ser! extraer! el! propio! bloque! if! else! del! controlador! ! y!
ubicarlo! en! la! clase! Accin! de! tal! forma! que! el! controlador! ya! no! tenga! ninguna!
responsabilidad! en! cuanto! a! qu! accin! ha! de! crear! y! esta! responsabilidad! quede!
completamente!delegada!a!la!clase!Accin.!!
!
Para! este! paso! construiremos! un! nuevo! mtodo! en! la! clase! Accin! denominado!
getAccion()! que! se! encargue! de! crear! las! distintas! acciones.! ! Estos! mtodos!
habitualmente! se! les! denominan! mtodos! factora! ya! que! cumplen! con! el! patrn!
factory.!A!continuacin!se!muestra!un!diagrama!aclaratorio!as!como!el!cdigo!fuente!
de!este!mtodo.!
144
www.arquitecturajava.com!

!
!
Cdigo!9.!4:!(Accion.java)!

publicstatic Accion getAccion(String tipo) {


Accion accion=null;
if (tipo.equals("/MostrarLibros.do")) {
accion = new MostrarLibrosAccion();
} elseif (tipo.equals(
"/FormularioInsertarLibro.do")) {
accion = new FormularioInsertarLibroAccion();
} elseif (tipo.equals("/InsertarLibro.do")) {
accion = new InsertarLibroAccion();
}
..............................
return accion;
}
!

145
Arquitectura*Java!

Como! podemos! ver,! es! este! mtodo! ahora! el! encargado! de! ! crear! cada! una! de! las!
acciones,!simplificando!sobremanera!el!controlador!que!tenemos!desarrollado,!ya!que!
a!partir!de!este!momento!el!controlador!queda!con!el!siguiente!cdigo:!
!
Cdigo!9.5:!(ControladorLibros.java)!

protected void doGet(HttpServletRequest request,


HttpServletResponse response) throws ServletException,
IOException {
RequestDispatcher despachador = null;
Accion accion = null;
String url= request.getServletPath();
accion= Accion.getAccion(url.substring(1,url.length()-3));
despachador = request.getRequestDispatcher(accion.ejecutar(request,
response));
despachador.forward(request, response);
}
!
!
Una! vez! realizados! estos! cambios,! ! no! tenemos! que! modificar! el! servlet! nunca! ms!!
para! poder! aadir! nuevas! acciones! a! nuestra! aplicacin:! por! lo! tanto! el! servlet!
controlador! cumple! con! el! principio! OCP,! aunque! no! ocurre! lo! mismo! con! la! clase!
action,!como!se!muestra!en!el!siguiente!diagrama.!

146
www.arquitecturajava.com!

!
!
En! estos! momentos! debemos! modificar! la! clase! Accin! y! su! mtodo! esttico!
getAccion()! cada! vez! que! deseemos! aadir! nuevas! acciones! .! Es! por! esto! que! todava!
nos! queda! trabajo! que! realizar! para! que! tambin! esta! clase! cumpla! con! el! principio!
OCP.!
!

5. Api!de!reflection!y!el!principio!OCP!

!
Para!solventar!este!problema!es!necesario!fijarse!en!el!nombre!de!las!distintas!URL!que!
pasamos!al!controlador,!como!es!por!ejemplo!la!siguiente:!
!
Cdigo!9.7!

FormularioInsertarLibro.do
!

147
Arquitectura*Java!

Despus!de!obtener!esta!URL,!podemos!transformarla!en!el!siguiente!texto!ejecutando!
un!par!de!funciones!de!formato,!con!lo!cual!nos!queda!un!texto!idntico!al!nombre!de!
una!clase!Accin!concreta.!
!
Cdigo!9.8:!!

FormularioInsertarLibroAcccion
!
Obtenido!el!nombre!de!la!accin,!!usaremos!el!api!de!reflection!que!ya!conocemos!de!
captulos!anteriores!y!crearemos!un!objeto!basado!en!el!nombre!de!la!clase.!Para!ello!
usaremos!el!siguiente!mtodo!del!api:!
!
Cdigo!9.9:!!

Class.forName.newInstance(String nombreClase)
!
A!continuacin!se!muestra!un!diagrama!aclaratorio:!

!
!

148
www.arquitecturajava.com!

Una! vez! creado! el! objeto,! invocaremos! a! su! mtodo! ejecutar.! A! continuacin! se!
muestra!el!cdigo!de!cmo!!el!API!de!reflection!permite!ir!insertando!nuevas!acciones!
sin!modificar!el!cdigo!previamente!construido.!
!
Cdigo!9.10:!!

public static Accion getAccion(String tipo) {


Accion accion = null;
try {
accion = (Accion) Class.forName(getPackage()
+"."+tipo+"Accion").newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return accion;
}
!
Terminado!este!cambio,!podemos!ir!aadiendo!nuevas!acciones!a!nuestra!aplicacin!sin!
impactar! en! las! anteriormente! construidas,! cumpliendo! con! el! principio! OCP! (ver!
imagen).!
!

149
Arquitectura*Java!

Resumen!
!
Hemos! terminado! de! modificar! nuestra! aplicacin! que! ahora! se! apoya! en! el! principio!
OCP! para! ir! aadiendo! nueva! funcionalidad! sin! afectar! a! la! anteriormente! construida.!
Este!diseo!es!muy!habitual!a!da!de!hoy!en!frameworks!web!como!ha!sido!el!caso!de!
struts!o!es!el!caso!de!JSF!y!Spring!MVC.!Al!tratarse!de!una!modificacin!importante!del!
Modelo! MVC! a! este! modelo! se! le! suele! denominar! Modelo! MVC! 2! o! de! Controlador!
Frontal.!!
!
! !

150
www.arquitecturajava.com!

!
!
!
!
!
!
!
!
!

! !

151
Arquitectura*Java!

10.Hibernate!
!

Acabamos!de!aplicar!el!principio!OCP!y!hemos!migrado!nuestra!aplicacin!a!un!modelo!
MVC2.!sta!ha!sido!la!ltima!versin!de!la!aplicacin!que!no!hace!uso!en!alguna!de!sus!
partes!de!un!framework!JEE.!!

A!partir!de!este!captulo!comienza!la!segunda!parte!del!libro!orientada!a!la!utilizacin!
de! distintos! frameworks! que! nos! sern! tiles! para! acelerar! el! desarrollo.! En! este!
captulo!introduciremos!Hibernate!como!framework!de!persistencia!y!substituiremos!la!
capa!de!persistencia!actual!(DataBaseHelper.java)!por!!Hibernate.!!

Objetivos!:!

Introduccin!a!Hibernate!
Utilizar!Hibernate!en!nuestra!aplicacin!

Tareas!:!

1. Concepto!de!Framework!de!persistencia.!
2. Instalacin!de!Hibernate.!
3. Introduccin!a!Hibernate!
4. Configuracin!de!Hibernate!
5. Insertar!!objetos!en!la!base!de!datos!con!Hibernate.!
6. Seleccin!de!objetos!de!la!base!de!datos!!con!Hibernate.!
7. Seleccionar!un!nico!objeto!con!Hibernate!
8. Borrar!objetos!de!la!base!de!datos!con!Hibernate.!
9. Filtrar!objetos!de!la!base!de!datos!con!Hibernate!
10. Construccin!de!la!clase!Hibernate!Helper.!
11. Mapeo!del!fichero!de!configuracin.!
12. El!principio!de!Convencin!sobre!configuracin!
152
www.arquitecturajava.com!

1. Introducion!al!concepto!de!framework!de!persistencia!

Hasta! este! momento! hemos! usado! la! clase! DataBaseHelper! para! que! se! encargara! de!
las!operaciones!ligadas!con!la!base!de!datos!(ver!imagen).!

Sin!embargo!la!clase!!aunque!funcional,!tiene!muchas!limitaciones!tales!como:!

No!soporta!transacciones!que!agrupen!varios!mtodos!ya!que!la!conexin!no!es!
compartida!y!cada!mtodo!es!totalmente!independiente.!
No!soporta!uso!de!!pool!de!conexiones!y!cada!vez!!se!construye!una!conexin!
nueva!!
No! soporta! consultas! preparadas! y! usa! consultas! SQL! estndar! con! los!
problemas!de!inyeccin!de!SQL!que!sto!genera!
No!soporta!varios!tipos!de!motores!de!bases!de!datos!y!se!centra!en!MySQL!

Podramos! continuar! con! la! lista! de! limitaciones,! pero! parece! claro! que! si! queremos!
construir!una!solucin!Enterprise,!la!clase!que!hemos!construido!no!es!el!mejor!camino.!
Nos!ha!sido!til!hasta!el!momento!!y!ha!ayudado!a!ir!asentando!conceptos.!As!pues,!si!
queremos!evolucionar!nuestra!solucin!a!algo!mas!serio,!deberemos!apoyarnos!en!un!
framework!de!persistencia!que!elimine!las!limitaciones!que!nuestra!clase!actual!tiene!y!
aporte!caractersticas!adicionales!(ver!imagen).!

153
Arquitectura*Java!

En! nuestro! caso! utilizaremos! Hibernate! ya! que! es! el! ! framework! de! persistencia! ms!
conocido!por!la!comunidad,!la!siguiente!tarea!abordara!su!instalacin.!

2. Instalacin!de!Hibernate!

Para! poder! instalar! Hibernate! lo! primero! que! tendremos! que! hacer! es! bajarnos! las!
libreras!de!las!cuales!se!compone,!que!estn!disponibles!en!la!siguiente!url:!

http://sourceforge.net/projects/hibernate/files/hibernate3/!

154
www.arquitecturajava.com!

Obtenidas!las!libreras,!!pasaremos!a!instalarlas!en!un!proyecto!Java!Estndar!de!Eclipse!
en! el! cul! construiremos! unos! sencillos! ejemplos! para! aprender! a! manejar! el!
framework.! A! continuacin! se! muestran! las! libreras! que! debemos! aadir! a! nuestro!
proyecto!para!que!los!siguientes!ejemplos!se!puedan!ejecutar!correctamente.!!

Tras!instalar!el!framework,!es!momento!de!comenzar!a!trabajar!con!l.!

3. Introduccin!a!Hibernate!

Hibernate! es! un! framework! ORM! (Object! Relational! Mapping)! cuya! tarea! es! la! de!
permitir!a!un!desarrollador!mapear!objetos!!contra!registros!de!una!base!de!datos!(ver!
imagen).!

155
Arquitectura*Java!

Todos! los! frameworks! de! persistencia! trabajan! de! forma! similar,! pero! cada! uno! tiene!
sus!propios!ficheros!de!configuracin.!En!el!caso!del!framework!Hibernate!existen!una!
serie! de! ficheros! y! conceptos! claves! a! la! hora! de! comenzar! a! trabajar! con! l.! Los!
enumeramos!a!continuacin!basndonos!en!la!clase!Libro.!

Hibernate.cfg.xml:! Es! el! fichero! principal! de! configuracin! del! framework,! es!
donde!se!configura!el!driver!JDBC!de!acceso!a!datos!!la!Ip!del!servidor!!de!base!
de!datos,!!el!usuario!y!la!password!!,as!como!los!ficheros!de!mapeo!que!van!a!
utilizar!las!distintas!clases.!
Libro.xml:! Es! el! fichero! de! mapeo! que! almacena! la! informacin! relevante!
referida! a! ! cmo! un! objeto! que! pertenece! a! una! clase! determinada,! en! este!
caso!un!Libro,!es!mapeado!a!una!fila!de!!la!tabla!Libros!
Libro.java!:!Clase!java!que!es!mapeada!!

A! continuacin! se! muestra! un! diagrama! de! alto! nivel! ! sobre! cuales! son! los! ficheros! y!
pasos! generales! que! realiza! el! framework! Hibernate! a! la! hora! de! trabajar! con! los!
objetos!java!que!se!encarga!de!persistir.!

156
www.arquitecturajava.com!

A!continuacin!vamos!a!explicar!cada!uno!de!los!pasos!del!diagrama:!

1. Leer! Hibernate.cfg.xml:! Como! primera! tarea,! el! framework! busca! y! lee! el!
fichero!de!configuracin!donde!se!encuentra!la!informacin!de!usuario,! clave,!
driver!y!url!de!conexin.!De!esta!forma!se!conecta!a!la!base!de!datos.!Junto!a!
esta!informacin!se!encuentra!tambin!la!lista!de!ficheros!de!mapeo!que!leer!
posteriormente.!
!
2. Leer!Fichero!de!mapeo:!Se!encarga!de!leer!todos!los!ficheros!de!mapeo!de!la!
aplicacin! para! saber! como! mapear! un! objeto! determinado! contra! alguna! de!
las!tablas!existentes!en!la!base!de!datos.!
!
3. Carga! la! clase! :! El! programa! que! estemos! construyendo! carga! las! clases! en!
memoria!

157
Arquitectura*Java!

4. Crear!Objeto!:!El!programa!que!estemos!construyendo!crea!varios!objetos!de!la!
clase!
5. Salvar:!Hibernate!se!encarga!de!guardar!los!datos!en!la!base!de!datos!
!

Una! vez! realizada! una! introduccin! a! cmo! Hibernate! trabaja! en! lneas! generales,! es!
momento!de!construir!nuestro!primer!ejemplo.!

4. Configuracin!Hibernate!

Una! vez! creado! un! proyecto! Java! estndar! y! aadidas! las! libreras! necesarias! para!
trabajar! con! Hibernate,! lo! primero! que! necesitaremos! ser! configurar! el! fichero!
hibernate.cfg.xml.! Este! fichero! estar! ubicado! dentro! de! nuestro! classpath,! como! la!
imagen!muestra:!

Clarificada!la!necesidad!de!este!fichero,!vamos!a!ver!!un!ejemplo!con!su!contenido:!

Cdigo!10.1(hibernate.cfg.xml)!

<?xml version='1.0' encoding='utf-8'?>


<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/arquitecturajava</property>
<property name="connection.username">root</property>
<property name="connection.password">java</property>
<property name="connection.pool_size">5</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="show_sql">true</property>
<mapping resource="com/arquitecturajava/aplicacion/bo/Libro.xml"/>
</session-factory>
</hibernate-configuration>
!

158
www.arquitecturajava.com!

Como! antes! hemos! comentado,! el! fichero! contiene! la! informacin! de! conexin! y! los!
ficheros! de! mapeo! a! utilizar! (mappingtresources).! Vamos! a! comentar! detalladamente!
cada!una!de!las!propiedades!que!este!fichero!contiene.!

Cdigo!10.2(hibrnate.cfg.xml):!!

<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
!

Esta! lnea! se! encarga! de! seleccionar! el! driver! nativo! de! conexin! a! la! base! de! datos!
.Para!ello!necesitaremos!aadir!el!driver!tipo!4!de!MySQL!a!nuestra!aplicacin.!

Cdigo!10.3(hibrnate.cfg.xml):!!

<property name="connection.url">jdbc:mysql://localhost/arquitecturajava</property>
!

Esta!lnea!define!la!URL!de!acceso!al!servidor!de!base!de!datos!y!a!una!de!sus!bases!de!
datos!en!concreto.!

Cdigo!10.4(hibrnate.cfg.xml):!!

<property name="connection.username">root</property>
<property name="connection.password">java</property>
!

Estas!dos!lneas!configuran!el!usuario!y!password!de!acceso!a!la!base!de!datos.!

Cdigo!10.5(hibrnate.cfg.xml):!!

<property name="connection.pool_size">5</property>
!

Esta!lnea!configura!el!tamao!del!pool!de!conexiones!del!framework!a!5.!

Cdigo!10.6(hibrnate.cfg.xml):!!

<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
!

Esta!lnea!selecciona!el!dialecto!que!usara!Hibernate!a!la!hora!de!realizar!las!distintas!
operaciones! contra! la! base! de! datos! .En! este! caso! el! dialecto! elegido! es! el! de! MySQL!
aunque!Hibernate!soporta!muchos!ms!!como!SQLServer,!Oracle!etc!y!permite!que!una!

159
Arquitectura*Java!

misma!aplicacin!basada!en!Hibernate!pueda!cambiar!de!forma!transparente!el!motor!
de!base!de!datos!utilizado!.Esta!es!una!de!las!ventajas!fundamentales!de!hacer!uso!de!
un!framework!de!persistencia.!

Cdigo!10.7(hibrnate.cfg.xml):!!

<property name="show_sql">true</property>
!

Configura! Hibernate! para! que! muestre! todas! las! consultas! ! SQL! que! genera.! Este!
parmetro! suele! ser! una! ayuda! importante! a! la! hora! de! valorar! si! Hibernate! est!
funcionando!de!forma!correcta!o!no.!

Cdigo!10.8(hibrnate.cfg.xml):!!

<mapping resource="com/arquitecturajava/aplicacion/bo/Libro.xml"/>
!

Esta!ltima!lnea!es!la!que!se!encarga!de!dar!de!alta!los!distintos!ficheros!que!mapean!
las!clases!a!las!tablas!de!la!base!de!datos!.En!nuestro!ejemplo!introductorio!nicamente!
tenemos!un!fichero!el!fichero!Libro.xml!(ver!imagen).!

Vamos!a!mostrar!a!continuacin!el!contenido!de!este!fichero!y!analizar!su!contenido.!

Cdigo!10.11(Libro.xml):!!

<?xml version="1.0"?>
<hibernate-mapping package="com.arquitecturajava.aplicacion.bo">
<class name="Libro" table="Libros">
<id name="isbn" type="string" />
<property name="titulo" type="string" column="titulo" />
<property name="categoria" type="string" column="categoria" />
</class>
</hibernate-mapping>
!

160
www.arquitecturajava.com!

Como!podemos!ver!el!fichero!xml!no!es!difcil!de!entender!,!ya!que!simplemente!mapea!
cada!una!de!las!propiedades!que!tiene!nuestra!clase!con!una!columna!de!la!tabla!de!la!
base!de!datos.!En!este!caso!nicamente!disponemos!de!las!siguientes!propiedades.!

Cdigo!10.12(Libro.xml):!!

<property name="titulo" type="string" column="titulo" />


<property name="categoria" type="string" column="categoria" />
!

Para! complementar! el! mapeo! Hibernate! necesita! saber! cul! de! las! propiedades! de! la!
clase!es!definida!como!clave!primaria.!Para!ello!el!framework!usa!la!etiqueta!<id>!que!
identifica!una!propiedad!como!clave!primaria.!

Cdigo!10.13(Libro.xml):!!

<id name="isbn" type="string" />


!

Una! vez! realizados! estos! pasos,! podemos! pasar! a! construir! un! programa! sencillo! que!
use!Hibernate!como!framework!de!persistencia.!

5. Insertar!Libro!con!Hibernate!

Como!punto!de!partida!vamos!a!crear!un!programa!que!se!encarga!de!crear!un!objeto!
Libro!y!salvarlo!en!la!base!de!datos!Hibernate,!a!continuacin!se!muestra!el!cdigo:!

Cdigo!10.14(Principal.java):!!

public static void main(String[] args) {


Session session=null;
Transaction transaccion =null;
try {
SessionFactory factoria = new Configuration().configure()
.buildSessionFactory();
session = factoria.openSession();
transaccion = session.beginTransaction();
Libro l= new Libro("1","java","programacion");
session.saveOrUpdate(l);
transaccion.commit();
} catch (HibernateException e) {
System.out.println(e.getMessage());
transaccion.rollback();
} finally {
session.close();}

161
Arquitectura*Java!

Vamos!a!explicar!lnea!a!lnea!el!bloque!de!cdigo!construido!para!que!paulatinamente!!
nos!vayamos!familiarizando!con!los!distintos!conceptos.!

Cdigo!10.15(Principal.java):!!

SessionFactory factoria =new Configuration().configure().buildSessionFactory();


!

Esta!primera!lnea!de!cdigo!se!encarga!de!leer!el!fichero!hibernate.cfg.xml!y!configurar!
el!acceso!a!datos!para!el!framework.!Una!vez!configurado!el!acceso,!nos!devuelve!un!
objeto! SessionFactory! que! es! un! objeto! nico! a! nivel! del! ! framework! y! ser! el!
encargado! de! darnos! acceso! al! resto! del! API! de! Hibernate.! Una! vez! disponemos! del!
objeto! SessionFactory,! invocamos! el! mtodo! openSession(),! como! se! muestra! a!
continuacin.!

Cdigo!10.16(Principal.java):!!

Session session = factoriaSession.openSession();


!

Este! mtodo! nos! devuelve! una! sesin! que! se! puede! ! entender! como! una! conexin!
clsica! a! la! base! de! datos.! Una! vez! construida! una! sesin,! ya! disponemos! de! una!
conexin! que! nos! permitir! salvar! objetos! en! la! base! de! datos.! Para! ello! nos!
construiremos!un!primer!objeto.!

Cdigo!10.17(Principal.java):!!

Libro libro= new Libro (1,java,programacion);


!

Creado! este! nuevo! objeto,! usaremos! el! objeto! sesin! para! comenzar! una! nueva!
transaccin.!

Cdigo!10.18(Principal.java):!!

transaccion= session.beginTransaction();
!

Una!vez!que!nos!encontramos!dentro!de!una!transaccin,!solicitamos!al!objeto!session!
que!salve!el!objeto!usando!el!mtodo!saveOrUpdate.!

162
www.arquitecturajava.com!

Cdigo!10.19(Principal.java):!!

session.saveOrUpdate(libro);
!

Para! ello! el! framework! Hibernate! se! apoyar! en! los! ficheros! de! mapeo! construidos!
(Libro.xml)!y!que!estn!disponibles!a!travs!del!objeto!Session,!encargndose!de!aplicar!
el!mapeo!definido.!Una!vez!realizada!la!operacin,!finalizamos!la!transaccin.!

Cdigo!10.20(Principal.java):!!

session.getTransaction().commit();
!

Hemos!salvado!el!objeto!en!la!base!de!datos!y!hemos!visto!las!clases!fundamentales!del!
framework.!A!continuacin!el!diagrama!nos!lo!resume.!

Una!vez!realiza!esta!operacin!de!insercin!de!libros!en!la!base!de!datos,!vamos!a!ver!
cmo!podemos!usar!Hibernate!para!realizar!otras!operaciones!complementarias.!

163
Arquitectura*Java!

6. Seleccionar!Objetos!con!Hibernate!

Vamos!a!construir!un!nuevo!ejemplo!con!el!framework!Hibernate!que!se!encargue!de!
seleccionar! todos! los! libros! de! la! base! de! datos,! para! ello! construiremos! el! siguiente!
programa!main.!

Cdigo!10.21(Principal.java):!!

public static void main(String[] args) {


Session session=null;
try {
SessionFactory factoria = new Configuration().configure()
.buildSessionFactory();
session= factoria.openSession();
Query consulta= session.createQuery("from Libro libro");
List<Libro> lista= consulta.list();
for(Libro l: lista) {
System.out.println(l.getIsbn());
System.out.println(l.getTitulo());
System.out.println(l.getCategoria());
}
}catch(HibernateException e) {
System.out.println(e.getMessage());
}finally {
session.close();
}
}
! ! !

Este! ejemplo! tiene! fuerte! similitudes! con! el! ejemplo! anterior! la! nica! diferencia!
importante!es!que!aparece!un!nuevo!concepto!el!de!Query.!

Query! :! El! objeto! Query! hace! referencia! en! Hibernate! a! una! consulta! que! lanzamos!
contra!la!base!de!datos!.Eso!si!en!vez!de!ser!una!consulta!SQL!se!trata!de!una!consulta!
HQL! (Hibernate! Query! Language)! lenguaje! propietario! de! Hibernate! que! nos! permite!
trabajar!con!el!mismo!tipo!de!sentencias!sin!importarnos!el!motor!de!base!de!datos!que!
utilicemos! .Ms! adelante,! esta! consulta! ser! transformada! en! consulta! SQL! para! el!
motor! de! base! de! datos! que! se! haya! seleccionado! como! dialecto! en! el! fichero!
hibernate.cfg.xml.! Una! vez! tenemos! claro! cul! es! el! concepto! de! Query,! vamos! a!
analizar!nuestra!consulta!

Cdigo!10.22(Principal.java):!!

Query consulta= session.createQuery("from Libro libro");


!

164
www.arquitecturajava.com!

En!este!caso!se!trata!de!una!consulta!sencilla!que!usa!HQL!para!seleccionar!todos!los!
libros! de! la! tabla! usando! un! alias.! Una! vez! hemos! creado! la! consulta,! invocamos! al!
mtodo!list()!del!objeto!Query!!que!nos!devuelve!una!lista!de!objetos!a!recorrer.!

Cdigo!10.23(Principal.java):!!

List<Libro> lista= consulta.list();


!

Dicha!lista!la!recorreremos!con!un!sencillo!buble!for!!

Cdigo!10.24(Principal.java):!!

for(Libro l: lista) {
System.out.println(l.getIsbn());
System.out.println(l.getTitulo());
System.out.println(l.getCategoria());
}
!

Este!bucle!for!nos!presentar!la!informacin!por!la!consola.!

Hasta!este!momento!hemos!visto!cmo!insertar!libros!o!cmo!seleccionar!una!lista!de!
stos!;!ahora!vamos!a!seguir!trabajando!con!el!framework.!

7. Seleccionar!un!nico!Objeto!

El! siguiente! ejemplo! nos! mostrar! cmo! seleccionar! un! nico! registro! de! la! tabla!
usando!Hibernate.!

165
Arquitectura*Java!

Cdigo!10.25(Principal.java):!!

public static void main(String[] args) {


Session session=null;
try {
SessionFactory factoria = new Configuration().configure()
.buildSessionFactory();
session= factoria.openSession();
Libro libro=(Libro) session.get(Libro.class,"1");
System.out.println(libro.getTitulo());
}catch(HibernateException e) {
System.out.println(e.getMessage());
}finally {
session.close();
}
}
!

En!este!ejemplo!que!acabamos!de!construir!lo!nico!destacable!es!cmo!Hibernate!se!
encarga!de!seleccionar!un!nico!objeto!a!travs!de!la!siguiente!lnea.!

Cdigo!10.26(Principal.java):!!

Libro libro=(Libro) session.get(Libro.class,"1");


! !

Una!vez!seleccionado,!simplemente!imprimimos!sus!datos!por!pantalla.!

Cdigo!10.27(Principal.java):!!

System.out.println(libro.getTitulo());
!

Quedan!por!construir!nicamente!dos!operaciones!ms!que!nos!vayan!a!ser!tiles!a!la!
hora!de!hacer!evolucionar!nuestra!aplicacin:!las!operaciones!de!borrar!y!filtrar.!

8. Borrar!un!objeto!

En! el! caso! de! borrar! no! vamos! a! profundizar! mucho! porque! es! tan! sencillo! como!
invocar! el! mtodo! delete! del! objeto! sesin! una! vez! obtenido! el! objeto! a! travs! de!
Hibernate;!!a!continuacin!se!muestra!el!cdigo:!

!
166
www.arquitecturajava.com!

Cdigo!10.28(Principal.java):!!

Session session=null;
try {
SessionFactory factoria = new Configuration().configure()
.buildSessionFactory();
session= factoria.openSession();
Libro libro=(Libro) session.get(Libro.class,"1");
session.delete(libro);
}catch(HibernateException e) {
System.out.println(e.getMessage());
}finally {
session.close();
}
!

9. Filtrar!objetos!con!Hibernate!

Por! ltimo,! como! introduccin! al! framework,! vamos! a! ver! cmo! se! puede! lanzar! una!
consulta!con!HQL!que!reciba!parmetros!y!filtre!la!seleccin!de!datos.!

Cdigo!10.29(Principal.java):!!

public static void main(String[] args) {


Session session = null;
try {
SessionFactory factoria = new Configuration().configure()
.buildSessionFactory();
session = factoria.openSession();
Query consulta = session
.createQuery(" from Libro libro where
libro.categoria=:categoria");
consulta.setString("categoria", "programacion");
List<Libro> lista = consulta.list();
for (Libro l : lista) {
System.out.println(l.getIsbn());
System.out.println(l.getTitulo());
System.out.println(l.getCategoria());
}
} catch (HibernateException e) {
System.out.println(e.getMessage());
} finally {
session.close();
}
}
!

167
Arquitectura*Java!

Como! podemos! ver,! esta! consulta! se! encarga! de! localizar! todos! los! libros! que! estn!
dentro!de!una!categora!determinada.!Para!ello!se!construye!una!consulta!en!HQL!y!se!
le!asigna!un!parmetro:!categora!a!la!cual!se!le!asigna!un!valor.!

Cdigo!10.30(Principal.java):!!

Query consulta = session.createQuery(" from Libro libro where


libro.categoria=:categoria");
consulta.setString("categoria", programacion);
!

Una! vez! hecho! esto,! invocamos! como! en! casos! anteriores! al! mtodo! list()! del! objeto!
Query!y!recorremos!la!lista.!

Cdigo!10.31(Principal.java):!!

List<Libro> lista = consulta.list();


for (Libro l : lista) {
System.out.println(l.getIsbn());
System.out.println(l.getTitulo());
System.out.println(l.getCategoria());
}
!

Con! esta! breve! introduccin! al! framework! Hibernate! tendremos! suficiente! para! hacer!
frente!a!los!cambios!de!nuestra!aplicacin,!que!se!abordarn!a!continuacin.!

10. Migrar!nuestra!aplicacin!a!Hibernate!

Es!momento!de!ver!cmo!podemos!encajar!el!framework!dentro!de!nuestra!aplicacin.!
En! primer! lugar! vamos! a! construir! una! nueva! clase! que! substituya! a! la! clase!
DataBaseHelper! y! se! encargue! de! inicializar! el! framework! Hibernate.! Esta! clase! se!
denominar!HibernateHelper!y!inicializar!el!framework.!A!continuacin!se!muestra!su!
cdigo.!

!
168
www.arquitecturajava.com!

Cdigo!10.32!(Principal.java):!!

package com.arquitecturajava.aplicacion;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateHelper {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
return new Configuration().configure().buildSessionFactory();
}
catch (Throwable ex) {
System.err.println("Error creando una factoria de session." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
!

Esta!sencilla!clase!nos!permitir!obtener!de!forma!directa!el!objeto!SessionFactory,!que!
inicializa!el!framework!,!como!se!muestra!a!continuacin.!

Cdigo!10.33!(Principal.java):!!

SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
Libro libro=(Libro) session.get(Libro.class,isbn);
session.close();
!

Una! vez! construida! la! clase! HibernateHelper,! es! momento! de! cambiar! nuestra! clase!
Libro! ! para! que! se! apoye! completamente! en! el! API! de! Hibernate.! Despus! de! esto,!
podremos! eliminar! la! clase! DataBaseHelper! de! nuestra! aplicacin.! A! continuacin! se!
muestra!el!cdigo!fuente!de!la!clase!Libro!actualizado!para!que!se!apoye!en!Hibernate.!

169
Arquitectura*Java!

Cdigo!10.34!(Libro.java):!!

package com.arquitecturajava.aplicacion;
//omitimos imports
public class Libro {

private String isbn;


private String titulo;
private String categoria;

@Override
public int hashCode() {
return isbn.hashCode();
}
@Override
public boolean equals (Object o) {
String isbnLibro= ((Libro)o).getIsbn();
return isbnLibro.equals(isbn);

}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public String getCategoria() {
return categoria;
}
public void setCategoria(String categoria) {
this.categoria = categoria;
}
public Libro(String isbn) {
super();
this.isbn = isbn;
}
public Libro() {
super();
}
public Libro(String isbn, String titulo, String categoria) {
super();
this.isbn = isbn;
this.titulo = titulo;
this.categoria = categoria;

170
www.arquitecturajava.com!

}
@SuppressWarnings("unchecked")
public static List<Libro> buscarTodasLasCategorias() {

SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
String consulta="select distinct libro.categoria from Libro libro";
List<Libro> listaDeCategorias = session.createQuery(consulta).list();
session.close();
return listaDeCategorias;
}
public void insertar() {

SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
session.beginTransaction();
session.save(this);
session.getTransaction().commit();
}
public void borrar(){

SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
session.beginTransaction();
session.delete(this);
session.getTransaction().commit();
}
public void salvar() {

SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
session.beginTransaction();
session.saveOrUpdate(this);
session.getTransaction().commit();
}
@SuppressWarnings("unchecked")
public static List<Libro> buscarTodos() {
SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
List<Libro> listaDeLibros = session.createQuery(" from Libro libro").list();
session.close();
return listaDeLibros;
}
public static Libro buscarPorClave(String isbn) {
SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
Libro libro=(Libro) session.get(Libro.class,isbn);
session.close();
return libro;
}

171
Arquitectura*Java!

@SuppressWarnings("unchecked")
public static List<Libro> buscarPorCategoria(String categoria) {

SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
Query consulta=session.createQuery(" from Libro libro where
libro.categoria=:categoria");
consulta.setString("categoria", categoria);
List<Libro> listaDeLibros = consulta.list();
session.close();
return listaDeLibros;
}

}
!

Una!vez!realizadas!estas!modificaciones,!nuestra!clase!Libro!!se!apoya!completamente!
en!el!framework!de!persistencia!para!realizar!cualquier!operacion.!La!estructura!fsica!
del!proyecto!ha!aadido!los!siguientes!elementos!en!un!nuevo!paquete!denominado!bo!
(business!objects).!

11. Hibernate!y!Convencin!sobre!Configuracin.!

Hemos!migrado!nuestra!aplicacin!de!un!sistema!de!persistencia!elemental!que!usaba!
una! clase! java! (DataBaseHelper)! al! uso! de! Hibernate.! Para! ello! hemos! tenido! que!
modificar!la!implementacin!de!parte!de!nuestras!clases,!as!como!aadir!una!serie!de!
ficheros!de!configuracin!del!framework!adicionales,!como!se!muestra!en!la!siguiente!
figura.!

172
www.arquitecturajava.com!

Aunque!nos!pueda!parecer!que!estamos!usando!Hibernate!de!la!forma!adecuada!y!que!
prcticamente!no!tenemos!cdigo!repetido!en!nuestra!aplicacin,!vemos!que!lo!que!si!
tenemos!repetido!es!la!informacin!respecto!a!los!conceptos!que!estamos!manejando!
a!nivel!de!capa!de!persistencia!.En!este!caso!estamos!repitiendo!la!informacin!sobre!el!
concepto!de!libro!en!las!siguientes!ubicaciones.!

Clase!Java!
Fichero!de!configuracin!(Libro.xml)!
Tabla!Libro!(Mysql)!

Este!problema!est!ligado!con!el!principio!DRY!ya!que,!aunque!no!se!trata!de!repeticin!
de! cdigo,! si! se! trata! de! repeticin! de! informacin! a! nivel! de! nuestra! aplicacin! (ver!
imagen).!

173
Arquitectura*Java!

El!objetivo!principal!de!la!siguiente!tarea!ser!eliminar!las!repeticiones!de!informacin!
de!nuestra!aplicacin!en!cuanto!a!la!capa!de!persistencia!se!refiere.!

12. DRY!e!Hibernate!

En! principio! no! podemos! aplicar! una! solucin! sencilla! a! la! repeticin! de! informacin!
que!tenemos!entre!la!aplicacin!JEE!y!la!base!de!datos,!ya!que!al!tratarse!de!sistemas!
independientes!ambos!deben!almacenar!la!informacin!relativa!a!nuestro!negocio!(ver!
imagen).!

174
www.arquitecturajava.com!

Sin! embargo! s! que! podemos! avanzar! en! solventar! la! repeticin! de! informacin! que!
existe! a! nivel! de! nuestra! aplicacin! JEE! en! la! cul! tenemos! la! misma! informacin!
almacenada! a! nivel! de! las! clases! Java! y! de! los! ficheros! xml! de! configuracin! del!
framework!(ver!imagen).!

La! repeticin! de! cdigo,! ya! sabemos! por! captulos! anteriores,! conlleva! graves!
problemas!de!mantenimiento!.Lo!mismo!sucede!con!la!repeticin!de!informacin.!Nos!
basta!por!ejemplo!con!referirnos!a!las!clsicas!reglas!de!normalizacin!de!una!base!de!
datos!para!saber!los!problemas!que!se!generan.!Sin!embargo!aqu!no!podemos!aplicar!
estas!reglas!de!normalizacin,!ya!que!nos!encontramos!no!con!una!base!de!datos!sino!
con! cdigo! Java.! ! As! pues! es! momento! de! introducir! otro! principio! de! ingeniera! de!
software!que!apoya!al!principio!DRY.!El!principio!de!Convencin!sobre!Configuracin!o!
COC!(Convention!Over!Configuration).!

175
Arquitectura*Java!

COC! :El! principio! COC! define! que,! antes! de! abordar! el! desarrollo,! un! programador!
puede! declarar! una! serie! de! convenciones! que! le! permiten! asumir! una! configuracin!
por!defecto!del!sistema.!

Quiz! esta! definicin! sea! algo! abstracta! y! difcil! de! entender! en! un! principio! .! Un!
ejemplo! es! la! forma! de! percibirlo! ms! claramente.! Vamos! a! usar! el! principio! COC! en!
nuestra!aplicacin!definiendo!la!siguiente!convencin.!

Los! campos! de! nuestras! clases! java! de! negocio! (Libro)! siempre! sern! idnticos! a! los!
campos!de!la!tabla!de!la!base!de!datos!donde!se!guarden!los!objetos!de!sta.!

El!hecho!de!aplicar!este!concepto!a!nuestra!aplicacin!implicar!que!el!fichero!XML!que!
construimos!por!cada!clase!de!persistencia!no!ser!a!partir!de!ahora!necesario,!ya!que!
al! aplicar! esta! convencin! se! sobreentiende! que! los! campos! y! propiedades! coinciden.!
Consecuentemente,!como!la!imagen!muestra,!este!fichero!ya!no!es!necesario.!

Sin!embargo!recordemos!que!este!fichero!no!se!encargaba!nicamente!de!mapear!los!
campos,!sino!que!adems!se!encargaba!de!definir!cul!de!todas!las!propiedades!de!la!
clase! se! identificada! como! clave! primaria! .! A! continuacin! se! muestra! el! fichero! en!
forma!de!recordatorio.!

176
www.arquitecturajava.com!

Cdigo!10.35!(Libro.xml):!!

<class name="Libro" table="Libros">


<id name="isbn" type="string" />
<property name="titulo" type="string" column="titulo" />
<property name="categoria" type="string" column="categoria" />
</class>
!

As!pues!no!podemos!eliminar!este!fichero!hasta!que!reubiquemos!la!informacin!sobre!
las! claves! primarias! en! algn! otro! lugar.! Para! ello! haremos! uso! del! sistema! de!
anotaciones! que! soporta! java! y! que! permite! aadir! informacin! adicional! a! nuestras!
clases.!!

Un! ejemplo! claro! de! este! tipo! de! informacin! es! la! anotacin! @Override,! que! nos!
permite!definir!cmo!un!mtodo!ha!de!ser!sobrecargado!.!A!continuacin!se!muestra!
un!ejemplo!de!cdigo.!!

Cdigo!10.36:!!

@Override
public void metodo() {
}
!

Apoyndonos! en! esta! idea,! podemos! volver! a! Hibernate.! Hibernate! soporta! otro!
conjunto! de! anotaciones! orientadas! a! facilitar! la! persistencia! de! nuestros! objetos.!
Vamos!a!hacer!uso!de!estas!anotaciones.!

@Entity!:!Identifica!a!una!clase!como!clase!a!persistir!
@Id:!Identifica!la!propiedad!de!la!clase!como!clave!primaria!de!la!tabla!
@Table:!Identifica!cul!es!el!nombre!de!la!tabla!contra!la!que!se!mapea!la!
clase.!

El! uso! de! este! conjunto! de! anotaciones! nos! permitir! eliminar! los! ficheros! xml! de!
mapeo!que!hemos!usado!hasta!ahora!.!

177
Arquitectura*Java!

A!continuacin!se!muestra!el!cdigo!fuente!de!nuestra!clase.!

Cdigo!10.37!(Libro.xml):!!

@Entity
@Table(name="Libros")
public class Libro {
@Id
private String isbn;
private String titulo;
private String categoria;
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitulo() {
return titulo;
}
publicvoid setTitulo(String titulo) {
this.titulo = titulo;
}
public String getCategoria() {
return categoria;
} //resto de metodos
!

Como!podemos!ver,!ya!no!necesitamos!el!fichero!de!mapeo,!es!suficiente!con!el!uso!de!
anotaciones.! El! modelo! de! anotaciones! nos! obliga! tambin! a! realizar! algunas!
modificaciones!a!nivel!del!fichero!Hibernate.cfg.xml!,!vamos!a!verlo.!

178
www.arquitecturajava.com!

Cdigo!10.38!(Hibernate.cfg.xml):!!

<hibernate-configuration><session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">
jdbc:mysql://localhost/arquitecturaJavaORM
</property>
<property name="connection.username">root</property>
<property name="connection.password">java</property>
<property name="connection.pool_size">5</property>
<property name="dialect">
org.hibernate.dialect.MySQL5Dialect
</property>
<mapping class="com.arquitecturajava.aplicacion.bo.Libro" />
</session-factory>
</hibernate-configuration>
!

Resumen!

Este! captulo! ha! servido! de! introduccin! al! framework! Hibernate! .! Hemos! aplicado! el!
principio! COC! para! configurar! de! una! forma! mas! cmoda! el! framework! a! la! hora! de!
usarlo!en!nuestra!aplicacin.!

! !

179
Arquitectura*Java!

11.Hibernate)y)Relaciones!
!

Hemos!modificado!nuestra!aplicacin!para!que!se!apoye!en!el!framework!Hibernate!a!
la! hora! de! gestionar! la! capa! de! persistencia.! Sin! embargo! an! nos! quedan! bastantes!
puntos! a! la! hora! de! trabajar! con! un! framework! de! persistencia! .Quizs! lo! mas!
destacable! del! uso! de! un! framework! de! persistencia! es! que! nos! permite! construir!
modelos! ms! complejos! y! flexibles! donde! existan! varias! clases! y! se! construyan!
relaciones! entre! las! mismas.! En! estos! momentos,! nuestro! caso! parte! de! un! modelo!
elemental! donde! nicamente! tenemos! una! tabla! en! la! base! de! datos! ,! tal! ! como! se!!
muestra!en!la!siguiente!imagen.!

Es! momento! de! construir! un! modelo! ms! slido! entidadtrelacin! en! el! cul! el!
framework!Hibernate!se!pueda!apoyar.!As!pues!modificaremos!la!estructura!de!la!base!
de!datos!para!que!aparezca!una!nueva!tabla,!la!tabla!Categoras!(ver!imagen).!

180
www.arquitecturajava.com!

De!esta!forma,!ambos!conceptos!estn!relacionados!a!travs!del!id!de!la!tabla!categora!
y! del! campo! categora! de! la! tabla! Libros.! Una! vez! construidas! ambas! tablas,! stas!
quedarn!relacionadas!a!travs!de!una!clave!externa!(ver!imagen).!

Una! vez! modificado! el! modelo! de! tablas,! debemos! encargarnos! de! realizar! las!
modificaciones! oportunas! en! nuestra! aplicacin! para! que! soporte! un! modelo! ms!
complejo!donde!las!!entidades!se!relacionan,!ste!ser!el!objetivo!principal!del!captulo.!
A!continuacin!se!listan!los!objetivos!y!tareas!del!mismo.!!

181
Arquitectura*Java!

Objetivos:!

Evolucionar!la!aplicacin!JEE!para!que!soporte!un!modelo!de!objetos!complejo!a!nivel!
de!capa!de!persistencia.!

Tareas:!

1. Construir!la!clase!Categora!y!mapearla!
2. Modificar!la!capa!de!presentacin!para!soportar!la!clase!Categora!
3. Creacin!de!relaciones!entre!clases!
4. Relaciones!y!persistencia!con!Hibernate!!
5. Relaciones!y!capa!de!presentacin!

1. Construir!la!clase!categora!y!mapearla!

Nos!encontraremos!que,!igual!que!existen!dos!tablas!en!la!base!de!datos,!!deberemos!
tener! tambin! en! principio! dos! clases! en! nuestro! modelo! de! objetos! de! negocio! (ver!
imagen)!

As! pues! debemos! crear! una! nueva! clase! en! nuestra! aplicacin! que! se! encargar! de!
gestionar!el!concepto!de!Categora.!Vamos!a!ver!su!cdigo.!!

182
www.arquitecturajava.com!

Cdigo!11.1:!(Categoria.java)!

package com.arquitecturajava.aplicacion.bo;
//omitimos imports
@Entity
@Table(name = "Categorias")
public class Categoria {
@Id
private String id;
private String descripcion;
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals (Object o) {
String categoriaId= ((Categoria)o).getId();
return id.equals(categoriaId);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public static List<Categoria> buscarTodos() {
SessionFactory factoriaSession =
HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
List<Categoria> listaDeCategorias = session.createQuery(
" from Categoria categoria").list();
session.close();
return listaDeCategorias;
}
}
!

Una! vez! creada! esta! clase,! observaremos! que! comparte! el! mismo! sistema! de!
anotaciones!que!tiene!la!clase!libro!y!deberemos!aadirla!a!la!zona!de!clases!mapeadas!
que!tiene!el!fichero!hibernate.cfg.xml!para!que!sea!incluida!como!clase!de!persistencia.!
Hemos!adems!sobrecargado!el!mtodo!equals!y!hashcode,!lo!cul!evitar!problemas!a!
la! hora! de! comparar! objetos! de! la! misma! clase.! A! continuacin! se! muestra! el! cdigo!
que! debemos! aadir! a! nuestro! fichero! de! configuracin! para! dar! de! alta! esta! nueva!
clase.!
183
Arquitectura*Java!

Cdigo!11.2:!(hibernate.cfg.xml)!

<hibernate-configuration>
<session-factory>
<!--resto de propiedades-->
<mapping class="com.arquitecturajava.aplicacion.bo.Libro" />
<mapping class="com.arquitecturajava.aplicacion.bo.Categoria" />
</session-factory>
</hibernate-configuration>
!

2. Modificar!la!!Capa!de!presentacin!y!soportar!la!clase!Categora!

Una! vez! hecho! esto,! es! necesario! modificar! algunas! de! nuestras! acciones! para! que! se!
hagan!eco!de!los!cambios!recin!introducidos,!ya!que!ahora!el!mtodo!de!buscar!todas!
las! categoras! ! se! encuentra! ubicado! en! la! clase! Categora.! Vamos! a! ver! como! este!
cambio!afecta!!a!la!clase!!!FormularioInsertarLibroAccion.!

Cdigo!11.3:!(formularioInsertarLibroAccion.xml)!

public class FormularioInsertarLibroAccion extends Accion {


@Override
public String ejecutar(HttpServletRequest request,
HttpServletResponse response) {
List<Categoria> listaDeCategorias = null;
listaDeCategorias = Categoria.buscarTodos();
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "FormularioInsertarLibro.jsp";
}
}
!

Como!podemos!ver,!la!clase!de!accin!!hace!uso!de!la!nueva!clase!Categora!a!la!hora!
de! buscar! todas! las! categoras! de! la! aplicacin.! Este! cambio! afectar! de! igual! modo! a!
otras! acciones! .Una! vez! modifiquemos! todas! las! acciones! afectadas,! deberemos!
tambin! modificar! las! distintas! paginas! JSP! que! hacen! uso! de! la! lista! de! categoras.! A!
continuacin!se!muestra!cmo!vara!el!cdigo!de!la!pgina!FormularioInsertarLibro.jsp.!

184
www.arquitecturajava.com!

Cdigo!11.4:!(MostrarLibros.jsp)!

<form id="formularioInsercion" action="InsertarLibro.do">


<fieldset><legend>Formularioaltalibro</legend>
<p><label for="isbn">ISBN:</label><input type="text" id="isbn"
name="isbn" /></p>
<p><label for="titulo">Titulo:</label><input type="text"
id="titulo" name="titulo" /></p>
<p><label for="categoria">Categoria :</label>
<select name="categoria">
<c:forEach var="categoria" items="${listaDeCategorias}">
<option value="${categoria.id}">
${categoria.descripcion}
</option>
</c:forEach>
</select><br />
</p>
<p><input type="submit" value="Insertar" /></p>
</fieldset>
</form>
!

Este! cambio! afectar! tanto! a! los! formularios! de! edicin! como! a! la! pagina!
MostrarLibros.jsp!.Ahora!bien,!en!esta!pgina!tendremos!algunos!problemas!aadidos!
con!el!siguiente!bloque!de!cdigo.!

Cdigo!11.5:!(MostrarLibros.jsp)!

<c:forEach var="libro" items="${listaDeLibros}">


${libro.isbn}
${libro.titulo}
${libro.categoria}
<a href="BorrarLibro.do?isbn=${libro.isbn}">borrar</a>
<a href="FormularioEditarLibro.do?isbn=${libro.isbn}">editar</a>
<br />
</c:forEach>
!

Aunque! en! un! principio! nos! parezca! que! no! existe! ningn! cambio! a! este! nivel,! si!
ejecutamos! la! pgina,! podremos! percatarnos! de! que! el! resultado! es! distinto! a! los!
ejemplos!del!captulo!anterior,!ya!que!no!aparece!el!nombre!de!la!categora!sino!su!id!
tal!como!!se!ve!en!la!siguiente!imagen.!

185
Arquitectura*Java!

Es! aqu! donde! podemos! observar! que,! aunque! hemos! construido! un! modelo! ms!
slido,! quedan! pasos! por! realizar.! El! modelo! tiene! sus! limitaciones! y! tendremos! que!
avanzar! un! paso! ms! para! superarlas.! Para! ello,! la! siguiente! tarea! se! encargar! de!
definir!relaciones!entre!las!distintas!clases.!

3. Creacin!de!relaciones!entre!clases!

En!estos!momentos!nuestras!dos!clases!Categora!y!Libro!!no!estn!relacionadas!entre!
s.! Es! momento! de! modificar! nuestro! cdigo! fuente! y! crear! las! siguientes! relaciones!
entre!ambas!clases:!

t Una! Categoria! contiene! varios! Libros:! Relacin! de! 1! a! n! en! la! que! una! categora!
contiene!un!conjunto!de!libros!
!
t Un! Libro! pertenece! a! una! categora:! Relacin! de! n! a! 1! en! la! que! cada! Libro!
pertenece!a!una!categora!concreta!

El!siguiente!diagrama!muestra!cmo!se!relacionan!ambas!clases.!!

186
www.arquitecturajava.com!

Para!que!esta!relacin!exista!a!nivel!de!cdigo!Java,!!la!clase!Categora!debe!incluir!un!
List<>!!de!Libros!y!la!clase!Libro!debe!incluir!una!variable!de!tipo!Categora,!!como!!el!
siguiente!diagrama!muestra.!

Una!vez!tenemos!claras!estas!ideas,!es!momento!de!pasar!a!mostrar!el!cdigo!fuente!
de!ambas!clases!para!ver!como!estas!dos!relaciones!se!implementan.!

Cdigo!11.6:!(Categoria.java)!

@Entity
@Table(name = "Categorias")
public class Categoria {
@Id
private int id;
private String descripcion;
private List<Libro> listaDeLibros;
public List<Libro> getListaDeLibros() {
return listaDeLibros;
}
public void setListaDeLibros(List<Libro> listaDeLibros) {
this.listaDeLibros = listaDeLibros;
}
// resto de codigo
!

187
Arquitectura*Java!

Cdigo!11.7:!(Libro.java)!

@Entity
@Table(name="Libros")
public class Libro {
@Id
private String isbn;
private String titulo;
private Categoria categoria;

public Categoria getCategoria() {


return categoria;
}
public void setCategoria(Categoria categoria) {
this.categoria = categoria;
}
//resto de codigo
!

Este!es!un!primer!paso!a!la!hora!de!crear!relaciones!entre!nuestras!clases.!Sin!embargo!
esta! primera! parte! no! crea! relaciones! a! nivel! de! persistencia,! sino! nicamente! a! nivel!
de! memoria.! La! siguiente! tarea! se! apoyar! en! el! uso! de! anotaciones! para! que! las!
relaciones!que!hayamos!construido!tengan!sentido!tambin!a!este!otro!nivel.!

4. Relaciones!y!persistencia!con!Hibernate!

Hibernate! nos! provee! de! un! conjunto! nuevo! de! anotaciones! orientadas! a! crear!
relaciones!entre!las!distintas!clases!java!!y!asegurar!su!persistencia.!Vamos!a!!enumerar!
a!continuacin!algunas!de!las!anotaciones!ms!importantes:!

t! @OneToMany! :! Anotacin! que! se! encarga! de! crear! una! relacin! de! 1! a! n! entre! dos!
clases!predeterminadas!(Categora!y!Libro!en!nuestro!ejemplo).!

t! @ManyToOne! :Anotacin! que! se! encarga! de! crear! una! relacin! de! muchos! a! uno!
entre!dos!clases!predeterminadas!(Libro!y!Categora!en!nuestro!ejemplo).!

t!@JoinColumn:!Anotacin!que!sirve!a!para!discernir!qu!columna!de!la!tabla!de!la!base!
de!datos!se!usa!como!clave!externa!o!fornea!a!la!hora!de!aplicar!la!relacin.!!

Aclarado!este!punto!,!vamos!a!ver!como!se!aplican!las!anotaciones!!a!nivel!de!cdigo.!

188
www.arquitecturajava.com!

Cdigo!11.8:!(Libro.java)!

@Entity
@Table(name="Libros")
public class Libro {
@Id
private String isbn;
private String titulo;
@ManyToOne
@JoinColumn (name="categoria")
private Categoria categoria;
}
!

Cdigo!11.9:!(Categoria.java)!

@Entity
@Table(name="Categorias")
public class Categoria {
@Id
private int id;
private String descripcion;
@OneToMany
@JoinColumn(name = "categoria")
private List<Libro> listaDeLibros;
!

Tras! construir! ! las! relaciones! a! nivel! de! persistencia! usando! las! anotaciones! de!
Hibernate,!vamos!a!construir!un!ejemplo!sencillo!que!muestra!cmo!utilizarlas.!

Cdigo!11.10:!(Principal.java)!

SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
List<Libro> listaDeLibros = session.createQuery("from Libro libro).list();
for(Libro l :listaDeLibros) {
System.out.println(l.getTitulo());
//accedemos a la categoria a traves de la relacion.
System.out.println(l.getCategoria().getDescripcion());
}
session.close();
!

Como! podemos! ver,! en! un! primer! momento! usamos! el! framework! Hibernate! y! el!
lenguaje!HQL!para!seleccionar!todos!los!libros!de!los!disponemos.!

!!
189
Arquitectura*Java!

Cdigo!11.11:!(Principal.java)!

List<Libro> listaDeLibros = session.createQuery("from Libro libro).list();


!

Una!vez!obtenidos!los!libros,!recorremos!la!lista!con!un!buble!y!vamos!mostrando!los!
distintos!contenidos.!

Cdigo!11.12:!(Principal.java)!

for(Libro l :listaDeLibros) {
System.out.println(l.getIsbn());
}
!

Ahora!bien!si!revisamos!la!siguiente!lnea.!

Cdigo!11.13:!(Principal.java)!

System.out.println(l.getCategoria().getDescripcion());
!

Nos!podemos!dar!cuenta!de!que!nos!!obliga!a!acceder!a!la!informacin!de!descripcin!
de! nuestra! categora,! informacin! que! previamente! no! hemos! seleccionado! con! la!
consulta!HQL!.Recordemos!que!la!consulta!nicamente!selecciona!el!concepto!de!Libro.!

!Cdigo!11.14:!(Principal.java)!

from Libro libro


!

Para! cumplir! con! nuestra! peticin! Hibernate! usar! la! informacin! relativa! a! las!
relaciones! que! acabamos! de! construir! y! obtendr! los! datos! necesarios! de! la! base! de!
datos,!como!se!muestra!en!la!imagen!al!ejecutar!el!cdigo.!

190
www.arquitecturajava.com!

Aunque!la!aplicacin!funciona!correctamente,!no!es!sencillo!entender!cmo!Hibernate!
consigue!realizar!esta!operacin!.Vamos!a!comentar!a!grosso!modo!como!funciona!este!
framework!de!persistencia!a!la!hora!de!realizar!esta!operacin:!Hibernate!es!capaz!de!
realizar! esta! operacin! a! travs! del! concepto! de! Proxy! que! crean! las! anotaciones!
relativas!a!las!relaciones!.Un!proxy!es!un!objeto!falseo!que!simula!ser!un!objeto!real.!En!
nuestro!caso,!Hibernate!lee!los!datos!de!la!clase!Categora!!y!crea!un!objeto!Categora!
Proxy!que!simula!ser!el!objeto!original,!como!se!muestra!en!el!siguiente!diagrama.!

191
Arquitectura*Java!

Vamos!a!comentar!a!continuacin!el!diagrama!

1. Hibernate!accede!al!objeto!Categora,!la!cul!es!un!proxy!
2. Hibernate!crea!un!objeto!Categora!real!accediendo!a!la!base!de!datos!
3. Hibernate!accede!a!los!datos!el!objeto!real!y!se!los!devuelve!al!Libro!!

Una!vez!tenemos!claro!como!funciona!el!concepto!de!CategoriaProxy!y!que!no!se!trata!
de! un! objeto! real! ,vamos! a! mostrar! cul! es! la! estructura! bsica! de! memoria! que! se!
construye! cuando! ejecutamos! la! consulta! ! select! libro! from! libro! .A! continuacin! se!
muestra!una!imagen.!

Es! visible! que! se! carga! en! memoria! una! lista! de! Libros! ,sin! embargo! esta! lista! no!
contiene! ningn! objeto! Categora! Real! sino! simplemente! un! conjunto! de!
ProxiesCategoria! que! dan! la! sensacin! de! ser! los! objetos! reales.! Ahora! bien,! cuando!
ejecutemos!la!siguiente!lnea!de!cdigo!

192
www.arquitecturajava.com!

Cdigo!11.15:!(Principal.java)!

System.out.println(l.getCategoria().getDescripcion());
!

Hibernate!responder!a!la!llamada!al!mtodo!getCategoria().getDescripcion(),!como!se!
muestra!en!la!figura.!

Vamos!a!explicar!detalladamente!cada!uno!de!los!pasos!

1. En! el! primer! paso,! el! objeto! Libro! invoca! al! mtodo! getCategoria(),! el! cul! en!
principio!nos!devuelve!un!ProxyCategoria!
2. Nuestro!objeto!libro!invoca!al!mtodo!getDescripcion()!del!ProxyCategoria.!

193
Arquitectura*Java!

3. Al! no! estar! ligado! a! un! objeto! Categora! real! sino! a! un! ProxyCategoria,! ste!
recibe!la!peticin!y!delega!en!Hibernate.!
4. El!framework!Hibernate!revisa!las!relaciones!construidas!y!lanza!una!consulta!de!
seleccin!que!selecciona!la!categora!a!la!que!el!libro!pertenece!!
5. Una!vez!hecho!esto,!construye!un!objeto!real!Categora!con!los!datos!obtenidos!
de!la!base!de!datos!y!lo!vincula!al!ProxyCategoria!
6. Por!ultimo,!el!ProxyCategoria!delega!la!invocacin!original!del!objeto!Libro!en!la!!
Categora!que!se!acaba!de!construir!en!memoria,!devolviendo!la!descripcin!al!
Libro!que!la!solicit.!

Esta! forma! de! trabajar! de! Hibernate! se! conoce! comnmente! como! carga! vaga! o!
lazyload,!ya!que!nicamente!accede!a!la!base!de!datos!para!obtener!informacin!sobre!
las!relaciones!entre!los!objetos!cuando!la!aplicacin!cliente!lo!solicita!y!nunca!antes.!!

5. Relaciones!y!capa!de!presentacin!

Una!vez!hecho!esto!!modificaremos!el!cdigo!de!la!capa!de!presentacin!para!que!se!
apoye!en!el!uso!de!relaciones!como!se!muestra!a!continuacin.!

Cdigo!11.16:!(Principal.java)!

<c:forEach var="libro" items="${listaDeLibros}">


${libro.isbn}${libro.titulo}${libro.categoria.descripcion}
<a href="BorrarLibro.do?isbn=${libro.isbn}">borrar</a>
<a href="FormularioEditarLibro.do?isbn=${libro.isbn}">editar</a>
<br />
</c:forEach>
!

Como! podemos! ver,! ahora! usamos! JSTL! para! acceder! a! la! relacin!
${libro.categoria.descripcion}! Una! vez! realizada! esta! operacin,! los! datos! de! libros! y!
categorias!se!mostrarn!correctamente.!

194
www.arquitecturajava.com!

Ahora! bien,! si! revisamos! las! consultas! SQL! que! Hibernate! ha! tenido! que! ejecutar,!
veremos! que! pueden! ser! mejorables! .A! continuacin! se! muestra! una! imagen! con! las!
consultas!ejecutadas.!

Como! podemos! ver,! se! realiza! una! consulta! ! adicional! por! cada! categora! que! debe!
obtener!de!la!base!de!datos.!As!pues!si!tuviramos!cien!categoras!se!ejecutaran!cien!
consultas.!En!este!caso!hubiera!sido!mejor!ejecutar!una!nica!consulta!de!tipo!join!que!
obtenga!los!datos!de!las!dos!tablas!simultneamente.!Para!ello!vamos!a!usar!la!sintaxis!
de!HQL!para!modificar!!la!consulta!y!dejarla!con!el!siguiente!cdigo.!

Cdigo!11.17:!(Principal.java)!

List<Libro> listaDeLibros = session.createQuery("from Libro libro right join fetch


libro.categoria").list();
!

Esta!clausula!rigth!join!fetch!obliga!a!Hibernate!a!ejecutar!una!consulta!de!joins!entre!
las!dos!tablas,!cargando!todos!los!datos!en!una!nica!consulta!(ver!imagen).!

195
Arquitectura*Java!

Una! vez! optimizada! esta! consulta,! es! momento! de! volver! a! mirar! hacia! el! cdigo! de!
nuestra!aplicacin!y!modificar!el!mtodo!que!busca!todos!los!libros!para!que!cargue!a!
travs!de!un!join!todos!los!datos!en!una!nica!consulta.!Vamos!a!verlo.!

Cdigo!11.18:!(Libro.java)!

publicstatic List<Libro> buscarTodos() {


SessionFactory factoriaSession=HibernateHelper.getSessionFactory();
Session session = factoriaSession.openSession();
List<Libro> listaDeLibros = session.createQuery("from Libro libro right join fetch
libro.categoria").list();
session.close();
return listaDeLibros;
}
!

Una!vez!creada!esta!consulta!HQL,!modificaremos!la!pgina!MostrarLibros.jsp!para!que!
se! encargue! de! mostrar! las! descripciones! de! las! categoras! apoyndose! en! las!
relaciones!creadas!con!Hibernate!y!en!la!consulta!optimizada!que!acabamos!de!definir.!
A!continuacin!se!muestra!como!queda!el!nuevo!bloque!de!cdigo.!

Cdigo!11.19:!(MostrarLibros.jsp)!

<c:forEach var="libro" items="${listaDeLibros}">


${libro.isbn}
${libro.titulo}
${libro.categoria.descripcion}
<a href="BorrarLibro.do?isbn=${libro.isbn}">borrar</a>
<a href="FormularioEditarLibro.do?isbn=${libro.isbn}">editar</a>
<br />
</c:forEach>
!

A!continuacin!se!muestra!el!resultado.!

196
www.arquitecturajava.com!

Resumen!
En! este! captulo! hemos! mostrado! como! construir! un! modelo! de! persistencia! ms!
flexible!construyendo!relaciones!entre!los!distintos!objetos.!Aunque!hemos!aumentado!
la! flexibilidad,! tambin! hemos! incrementado! la! complejidad! a! la! hora! de! abordar! un!
desarrollo,!introduciendo!caractersticas!avanzadas!de!los!frameworks!de!persistencia.!

! !

197
Arquitectura*Java!

12.Java$Persistence$API!

Durante! muchos! aos! en! la! plataforma! J2EE! han! existido! distintos! frameworks! de!
persistencia!como!!Ibatis,!Hibernate!,!TopLink!etc!(ver!imagen).!

Cada!uno!de!estos!frameworks!de!persistencia!ha!utilizado!una!filosofa!propia!a!la!hora!
de!decidir!de!qu!forma!se!almacena!la!informacin!en!la!base!de!datos.!De!este!amplio!
conjunto! de! frameworks! hay! un! subconjunto! que! son! frameworks! ORM! (Object!
Relational!Mapping)!!como!TopLink!y!Hibernate.!Algunos!otros!frameworks!no!pueden!
ser!incluidos!dentro!de!esta!categora,!caso!de!IBatis!o!Spring!JDBC,!que!no!realizan!un!
mapeo!propiamente!dicho!(ver!imagen).

198
www.arquitecturajava.com!

A!da!de!hoy!la!plataforma!JEE!se!ha!encargado!de!estandarizar!la!capa!de!persistencia!a!
travs! de! la! creacin! del! estndar! JPA! (Java! Persistence! API).! Este! estndar! se! ha!
basado!fundamentalmente!en!las!experiencias!que!los!distintos!fabricantes!han!tenido!
con! los! frameworks! ! de! ORM,! dejando! fuera! a! aquellos! que! no! lo! son.! Por! esa! razn!
prcticamente! la! totalidad! de! los! frameworks! de! ORM! soportan! el! uso! del! api! de! JPA!
(ver!imagen).!

As!pues!el!siguiente!paso!que!abordaremos!en!nuestra!aplicacin!ser!la!migracin!de!
la! capa! de! persistencia! del! uso! del! API! de! Hibernate! al! uso! del! API! de! ! JPA! sobre!
Hibernate.!As!ser!prcticamente!transparente!migrar!una!aplicacin!de!un!framework!
de! persistencia! a! otro! como! por! ejemplo! de! Hibernate! a! TopLink.! sto! nos! aportar!
flexibilidad! a! la! hora! de! elegir! fabricante! para! nuestro! servidor! de! aplicaciones.!
Podemos!empezar!con!una!aplicacin!instalada!en!JBoss!!con!!Hibernate!y!!migrarla!de!
una!forma!relativamente!sencilla!a!WebLogic!con!TopLink!(ver!imagen).!

199
Arquitectura*Java!

Seguidamente!se!detallan!los!objetivos!y!tareas!de!este!captulo.!

Objetivos!:!

Migrar!la!capa!de!persistencia!de!nuestra!aplicacin!a!JPA!!

Tareas:!

1. Introduccin!al!API!de!JPA!!
2. Migracin!de!la!aplicacin!a!JPA.!
3. Manejo!de!Excepciones!y!JPA!!

1. Introduccin!al!API!de!JPA!

Esta! tarea! se! centrra! en! hacer! evolucionar! nuestra! capa! de! persistencia! creada! con!
Hibernate!a!una!nueva!capa!de!persistencia!que!delega!en!Hibernate!pero!se!apoya!en!
el!API!de!JPA!para!trabajar.!El!API!de!JPA!es!muy!similar!al!API!de!Hibernate,!ya!que!el!
estndar! de! JPA! se! apoy! en! el! xito! de! Hibernate! como! framework! para! grandes!
partes!de!su!diseo.!A!continuacin!se!explican!cules!son!las!clases!fundamentales!que!
usa!el!API!de!JPA.!

Persistence:! Hace! referencia! a! la! configuracin! de! JPA! y! es! similar! a! la! clase!
Configurator!de!Hibernate.!
EntityManagerFactory:!Factora!que!se!encarga!de!inicializar!el!framework,!!su!
rol!es!similar!al!SessionFactory!!de!Hibernate!que!hemos!utilizado!!en!captulos!
anteriores.!
EntityManager:! Clase! que! se! encarga! de! gestionar! la! persistencia! de! un!
conjunto!de!entidades!similar!al!objeto!Session!del!API!de!Hibernate.!!
EntityTransaction:!Clase!que!se!encarga!de!definir!el!concepto!de!transaccin,!
similar!a!Transaction!en!Hibernate.!

200
www.arquitecturajava.com!

TypedQuery:!Identifica!una!consulta!definida!con!JPQL!(Java!Persistence!Query!
Language)! similar! a! la! clase! Query! de! Hibernate! con! la! nica! salvedad! que!
soporta!el!uso!de!genricos.!
Persistence.xml:! Fichero! que! reemplaza! al! fichero! clsico! de! Hibernate!
Hibernate.cfg.xml! y! que! contiene! todos! los! parmetros! necesarios! para!
conectarnos!contra!un!servidor!de!base!de!datos.!!

Una!vez!explicadas!las!clases!principales,!vamos!a!ver!un!ejemplo!sencillo!de!!cmo!el!
api! de! JPA! se! encarga! de! buscar! todos! los! libros! de! nuestra! aplicacin! a! travs! de! un!
programa!de!consola.!

Cdigo!12.1:!(Principal.java)!

public static void main (String args[]) {


EntityManagerFactory emf=
Persistence.createEntityManagerFactory("arquitecturaJava");
EntityManager em=emf.createEntityManager();
TypedQuery<Libro> consulta= em.
createQuery("Select l from Libro l",Libro.class);
List<Libro> lista= consulta.getResultList();
for(Libro l: lista) {
System.out.println(l.getTitulo());
}
}

Como! podemos! ver,! el! cdigo! es! muy! similar! al! usado! en! Hibernate.! Vamos! a!
comentarlo!lnea!a!lnea.!

Cdigo!12.2:!(Principal.java)!

EntityManagerFactory
emf=Persistence.createEntityManagerFactory("arquitecturaJava");
!

Esta! parte! del! cdigo! se! encarga! de! crear! un! EntityManagerFactory,! que! es! el! objeto!
que!inicializa!todo!lo!necesario!para!que!el!estndar!de!JPA!pueda!trabajar.!Para!ello!se!
apoyar! en! el! fichero! persistence.xml,! que! se! muestra! a! continuacin.! Este! fichero! se!
encuentra!ubicado!en!!el!directorio!METAtINF!de!nuestra!aplicacin!(ver!imagen).!

201
Arquitectura*Java!

A!continuacin!se!muestra!el!contenido!de!este!fichero.!

Cdigo!12.3:!(persistence.xml)!

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<persistence-unit name="arquitecturaJava">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.arquitecturajava.aplicacion.bo.Libro</class>
<class>com.arquitecturajava.aplicacion.bo.Categoria</class>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="javax.persistence.transactionType"
value="RESOURCE_LOCAL" />
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://localhost/arquitecturaJavaORM" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="java" />
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQL5Dialect" />
</properties>
</persistence-unit>
</persistence>
!

202
www.arquitecturajava.com!

Como! podemos! ver! el! fichero! es! muy! similar! al! fichero! clsico! de! configuracin! del!
framework! Hibernate! .Una! vez! configurado,! ya! podemos! comenzar! a! usar! JPA.! Es!
momento!!hablar!del!el!objeto!!EntityManager!(ver!cdigo).!

Cdigo!12.4:!(Principal.java)!

EntityManager em=emf.createEntityManager();

Este! objeto! es! el! encargado! de! gestionar! el! ciclo! de! vida! de! las! entidades! y! es! capaz!
tanto! de! guardar! objetos! en! la! base! de! datos! como! de! seleccionarlos! a! travs! de! la!
creacin!de!consultas!JPQL!(Java!Persistence!Query!Language),!como!se!muestra!en!la!
siguiente!lnea.!

Cdigo!12.5:!(Principal.java)!

TypedQuery<Libro> consulta= em.


createQuery("Select l from Libro l",Libro.class);
List<Libro> lista= consulta.getResultList();

Una!vez!creada!la!consulta! invocados!al!mtodo!getResultList()!que!nos!devuelve!una!
lista!de!Libros!genrica.!Por!ultimo!!simplemente!recorremos!la!lista!!y!presentamos!por!
consola!el!titulo!de!cada!libro.!

Cdigo!12.6:!(Principal.java)!

for(Libro l: lista) {
System.out.println(l.getTitulo());
}

Como!complemento!al!ejemplo!anterior,!vamos!a!ver!un!ejemplo!en!el!cual!usamos!JPA!
para!persistir!un!objeto!en!la!base!de!datos.!

203
Arquitectura*Java!

Cdigo!12.7:!(Principal.java)!

public static void main(String[] args) {


EntityManagerFactory emf=
Persistence.createEntityManagerFactory("arquitecturaJava");
EntityManager manager = emf.createEntityManager();
Libro libro= new Libro ("2","java","programacion");
EntityTransaction tx = null;
tx=manager.getTransaction();
tx.begin();
manager.merge(libro);
tx.commit();
manager.close();
}
}
!

Como!podemos!ver,!aparece!un!nuevo!tipo!de!Objeto!EntityTransaction!que!se!encarga!
de!ejecutar!transacciones!sobre!JPA!.La!nica!diferencia!con!el!ejemplo!anterior!es!que!
usamos!el!metodo!merge!()!de!la!clase!EntityManager!para!guardar!el!objeto!en!la!base!
de!datos!,!mtodo!que!es!similar!al!saveOrUpdate!que!en!captulos!anteriores!usamos!
para!Hibernate.!

2. Migracin!de!Aplicacin!a!JPA!

Vista!una!introduccin!al!api!de!JPA,!vamos!a!migrar!nuestra!aplicacin!al!uso!de!JPA.!
Para! ello! construiremos,! como! hicimos! en! el! caso! de! Hibernate,! una! clase! Helper! que!
nos!ayude!a!trabajar!con!el!API!de!JPA!,!a!continuacin!se!muestra!su!cdigo!fuente.!

Cdigo!12.8:!(JPAHelper.java)!

package com.arquitecturajava.aplicacion;
//omitimos imports
public class JPAHelper {
private static final EntityManagerFactory emf = buildEntityManagerFactory();
private static EntityManagerFactory buildEntityManagerFactory() {
try {
return Persistence.createEntityManagerFactory("arquitecturaJava");
}catch (Throwable ex) {
throw new RuntimeException("Error al crear la factoria de JPA");
}}
public static EntityManagerFactory getJPAFactory() {
return emf;}
}
!

204
www.arquitecturajava.com!

Una! vez! construida! la! clase! helper! y! definido! el! fichero! persistence.xml,! podemos!
modificar!nuestra!aplicacin!y!que!nuestras!clases!de!negocio!utilicen!el!API!de!JPA!de!
forma! sencilla.! A! continuacin! se! muestra! el! cdigo! fuente! de! la! clase! Libro! una! vez!
migrada!a!JPA!,el!cdigo!de!la!clase!Categora!es!muy!similar.!!!!

Cdigo!12.9:!(Categoria.java)!

package com.arquitecturajava.aplicacion;
import java.util.List;
// imports omitidos
@Entity
@Table(name = "Libros")
public class Libro {
//!omitimos!propiedades!

! public!void!insertar()!{!

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
tx = manager.getTransaction();
tx.begin();
manager.persist(this);
tx.commit();

}
public void borrar() {

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
tx = manager.getTransaction();
tx.begin();
manager.remove(manager.merge(this));
tx.commit();
manager.close();
}
public void salvar() {

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
tx = manager.getTransaction();
tx.begin();
manager.merge(this);
tx.commit();
manager.close();
}

205
Arquitectura*Java!

public static List<Libro> buscarTodos() {

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
TypedQuery<Libro> consulta = manager.createQuery(
"SELECT l FROM Libro l JOIN FETCH l.categoria",
Libro.class);
List<Libro> listaDeLibros = null;
listaDeLibros = consulta.getResultList();
manager.close();
return listaDeLibros;
}

public static Libro buscarPorClave(String isbn) {

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
TypedQuery<Libro> consulta = manager.createQuery(
"Select l from Libro l JOIN FETCH l.categoria where l.isbn=?1",
Libro.class);
consulta.setParameter(1, isbn);
Libro libro = null;
libro = consulta.getSingleResult();
manager.close();
return libro;
}

public static List<Libro> buscarPorCategoria(Categoria categoria) {


EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
TypedQuery<Libro> consulta = manager.createQuery(
"Select l from Libro l where l.categoria=?1",
Libro.class);
consulta.setParameter(1, categoria);
List<Libro> listaDeLibros = null;
listaDeLibros = consulta.getResultList();
manager.close();
return listaDeLibros;
}
}

Acabamos! de! migrar! los! mtodos! de! persistencia! de! la! clase! Libro! al! standard! JPA.! La!
siguiente!tarea!se!tratar!de!abordar!otro!tema!que!tenamos!pendiente:!la!gestin!de!
excepciones!a!nivel!de!capa!de!persistencia.!

206
www.arquitecturajava.com!

3. Manejo!de!Excepciones!

En!estos!momentos!!si!!en!alguna!ocasin!una!consulta!produce!una!excepcin,!no!se!
garantiza! que! las! conexiones,! sentencias! etc.! se! cierren! correctamente! y! por! lo! tanto!
podemos!acabar!teniendo!problemas.!En!esta!tarea!vamos!a!encargarnos!de!modificar!
los!mtodos!de!la!capa!de!persistencia!para!que!se!encarguen!de!una!correcta!gestin!
de!excepciones.!Para!ello!comenzaremos!modificando!el!mtodo!borrar!de!la!clase!libro!
aadindole! las! clusulas! try/catch/finally! necesarias.! Seguidamente! se! muestra! su!
cdigo.!

Cdigo!12.10:!(Libro.java)!

public void borrar() {


EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
try {
tx=manager.getTransaction();
tx.begin();
manager.remove(manager.merge(this));
tx.commit();
} catch (PersistenceException e) {
manager.getTransaction().rollback();
throw e;
} finally {
manager.close();
}

Como! podemos! ver,! el! manejo! de! excepciones! es! muy! similar! al! cdigo! que!
anteriormente!se!albergaba!a!nivel!de!JDBC!y!no!vamos!a!comentarlo!con!ms!detalle.!
A! continuacin! se! muestra! como! complementario! el! mtodo! buscaTodos()! como!
mtodo!de!seleccin!.!

207
Arquitectura*Java!

Cdigo!12.11:!(Libro.java)!

public static List<Libro> buscarTodos() {


EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
TypedQuery<Libro> consulta = manager.createQuery(
"SELECT l FROM Libro l JOIN FETCH l.categoria",
Libro.class);
List<Libro> listaDeLibros = null;
try {
listaDeLibros = consulta.getResultList();
} finally {
manager.close();
}
return listaDeLibros;
}

As,!el!cdigo!es!similar,!con!la!nica!diferencia!que!no!utilizamos!clusula!catch!ya!que!
no!es!necesario!realizar!un!rollback!de!ninguna!excepcin.!El!mismo!cdigo!hubiera!sido!
necesario!en!Hibernate,!pero!hemos!preferido!obviarlo!y!centrarnos!en!JPA.!

Resumen!
En! este! captulo! no! hemos! realizado! grandes! cambios! a! nivel! de! la! arquitectura! de! la!
aplicacin! pero! s! en! cuanto! a! cmo! se! implementa! la! capa! de! persistencia! utilizando!
JPA!como!standard.!

!
!

!
!
!

208
www.arquitecturajava.com!

209
Arquitectura*Java!

13.El$principio$ISP$y$el$patrn$DAO!

En!el!captulo!anterior!hemos!hecho!evolucionar!nuestra!aplicacin!para!que!soporte!el!
estndar! de! JPA.! Es! momento! de! seguir! progresando! en! su! diseo.! Para! esto,! es!
necesario! salir! momentneamente! del! entorno! web! a! fin! de! poder! explicar! ! algunos!
nuevos! conceptos.! Vamos! a! suponer! que! nuestra! aplicacin! necesita! de! un! nuevo!
mdulo!que!se!encargue!de!leer!una!lista!de!libros!almacenada!en!un!fichero!de!texto.!
La!estructura!del!fichero!es!la!siguiente:!!

1,Java,1,Programacin
2,JSP ,2, Web

En! principio! construir! un! programa! para! leer! estos! datos! e! imprimir! la! ! lista! de! libros!!
por! consola! es! sencillo,! tenemos! adems! construidas! las! clases! de! negocio! que! se!
adaptan!a!estos!datos.!

Libro!
Categoria!

As! pues! vamos! a! construir! un! nuevo! proyecto! Java! que! denominaremos! ! LeerLibros!
usando! eclipse! (proyecto! java! standard)! que! use! nuestras! clases! de! negocio! .A!
continuacin!se!muestra!una!imagen!de!los!elementos!requeridos.!

210
www.arquitecturajava.com!

Una! vez! importadas! estas! clases,! nos! percatamos! de! que! no! es! posible! trabajar! con!
ellas! de! forma! directa! sin! incluir! la! clase! JPAHelper,! as! pues! aadimos! esta! clase! a!
nuestro! proyecto.! Despus! estaremos! tambin! obligados! a! aadir! la! librera! de!
Hibernate! y! JPA,! ! ya! que! nuestras! clases! hacen! uso! de! anotaciones! de! este! tipo.! As!
pues!nuestras!clases!Libro!y!categora!tienen!las!siguientes!dependencias.!!

JPAHelper!(Clase)!
Hibernatetjpa.2.0!(Libreria)!

Vamos!a!ver!el!cdigo!fuente!del!programa!que!se!encarga!de!leer!la!lista!de!libros:!!

Cdigo!13.1:!(Principal.java)!

public class Principal {


public static void main(String[] args) throws IOException {

String texto="";
Reader l= new FileReader("libros.txt");
BufferedReader lector= new BufferedReader(l);
List<Libro> lista= new ArrayList<Libro>();
Libro libro=null;
Categoria categoria=null;
while ((texto=lector.readLine())!=null ){
String[] datos= texto.split(",");
categoria= new Categoria(Integer.parseInt(datos[2]),datos[3]);
libro = new Libro(datos[0],datos[1],categoria);
lista.add(libro);
}
for(Libro l1 :lista) {
System.out.println(l1.getTitulo());
}
}
}

211
Arquitectura*Java!

El!programa!es!muy!sencillo:!lee!el!fichero,!lo!recorre!lnea!a!lnea,!crea!una!nueva!lista!
de!libros!la!cul!finalmente!recorre!e!imprime!por!pantalla.!Ahora!bien:!van!a!aparecer!!
algunos!problemas.!En!primer!lugar!nuestro!programa!no!necesita!para!nada!ninguno!
de! los! mtodos! de! persistencia! de! la! clase! Libro! o! de! la! clase! Categora,! ni! mucho!
menos! hace! uso! de! la! clase! JPAHelper! y! de! las! libreras! de! JPA.! Sin! embargo,! no!
tenemos! ms! remedio! que! importarlas! a! nuestro! proyecto.! Esto! claramente! no! tiene!
ningn!sentido!.Vamos!a!centrar!el!objetivo!de!este!captulo!en!solventar!este!tipo!de!
problemas! .Para! ello! vamos! a! introducir! otro! principio! denominado! principio! ISP! o!
Interface!Segregation!Principle!cuya!definicin!se!muestra!seguidamente:!

ISP! :! Una! clase! cliente! A! que! tiene! una! dependencia! con! la! clase! B! no! debe!
verse!forzada!a!depender!de!mtodos!de!la!clase!B!que!no!vaya!a!usar!jams.!

En!nuestro!caso!parece!claro!que!tenemos!un!problema!relativo!a!este!principio,!ya!que!
nuestra! clase! cliente! (clase! Principal)! depende! de! mtodos! que! nunca! va! a! utilizar.!
Mtodos!que!estn!en!la!clase!libro,!concretamente!los!relativos!al!uso!de!persistencia,!
como!se!muestra!en!la!figura.!

As,! nos! encontramos! con! un! problema! de! diseo! en! el! cul! no! hemos! aplicado! el!
principio!ISP,!como!se!muestra!en!la!siguiente!figura.!

212
www.arquitecturajava.com!

He!aqu!los!objetivos!del!presente!captulo:!

Objetivos!:!
Aplicar!el!principio!ISP!a!la!capa!de!Persistencia.!

Tareas:!

1. Crear!las!clases!LibroDAO!y!PersonaDAO!que!cumplan!con!el!principio!ISP!
2. Uso!de!interfaces!a!nivel!DAO!para!permitir!varias!implementaciones!!
3. Creacin!de!DAOs!Genricos!
4. Rendimiento!

1. Crear!las!clases!LibroDAO!y!CategoriaDAO.!

Vamos!a!usar!a!continuacin!el!principio!ISP!para!eliminar!dependencias!entre!la!clase!
Main! (cliente)! y! los! mtodos! de! la! clase! Libro.! Para! ello! la! clase! Libro! externalizar!
todos!los!mtodos!de!persistencia!a!una!nueva!clase!denominada!LibroDAO.!DAO(!Data!
Access!Object)!hace!referencia!a!un!patrn!de!diseo!de!la!capa!de!persistencia!que!se!
encarga! de! cumplir! con! el! principio! ISP! y! separar! las! responsabilidades! de! negocio! y!
persistencia.!As!pues,!la!clase!Libro!se!encargar!de!los!mtodos!set/get!(Negocio)!y!la!
clase! LibroDAO! de! todos! los! mtodos! de! persistencia! (insertar/borrar! etc.).! A!
continuacin!se!muestra!una!figura!aclaratoria:!

213
Arquitectura*Java!

Una! vez! creadas! las! nuevas! clases,! se! ubicaran! en! un! nuevo! paquete! de! la! aplicacin!
denominado!DAO!(ver!imagen).!

Acabamos!de!separar!los!mtodos!de!nuestra!clase!Libro!en!dos!clases!independientes!
cada!una!de!las!cules!se!encarga!de!una!determinada!funcionalidad.!Hemos!aplicado!el!
principio!ISP,!ya!que!era!el!que!de!forma!ms!directa!encajaba!.Igualmente!podramos!
haber! aplicado! el! principio! SRP! (Simple! Responsability! Principle)! ya! que! tambin!
estamos!separando!las!distintas!responsabilidades!!de!muestra!clase.!El!hecho!de!que!
dos! principios! encajen! con! el! refactoring! que! deseamos! aplicar! a! nuestro! cdigo! nos!
ayuda! a! fortalecer! la! idea! de! que! podemos! obtener! una! solucin! mejor.!
Frecuentemente! el! ver! que! dos! principios! de! ingeniera! nos! orientan! hacia! la! misma!

214
www.arquitecturajava.com!

solucin! refuerza! el! concepto! de! que! los! refactorings! van! en! la! direccin! adecuada.!
Ahora! nuestro! programa! Principal! ! nicamente! depender! de! la! clase! Libro,! como! se!
muestra!en!la!figura!y!no!tendr!necesidad!de!usar!nada!de!la!capa!de!persistencia.!

Despus! de! tener! claro! cmo! dividir! las! clases,! vamos! a! ver! detalladamente! cmo!
queda!el!cdigo!fuente!de!la!clase!Libro!as!como!el!de!la!clase!LibroDAO.!

Cdigo!13.2:!(Libro.java)!

@Entity
@Table(name = "Libros")
public class Libro {
@Id
private String isbn;
private String titulo;
@ManyToOne
@JoinColumn(name = "categoria")
private Categoria categoria;
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public Categoria getCategoria() {
return categoria;
}
publicvoid setCategoria(Categoria categoria) {
this.categoria = categoria;
} //omitimos constructores
}

215
Arquitectura*Java!

A continuacin se muestra el codigo de la clase LibroDAO:

Cdigo!13.3:!(LibroDAO.java)!

public class LibroDAO {


public void insertar(Libro libro) {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
try {
tx=manager.getTransaction();
tx.begin();
manager.merge(libro);
tx.commit();
} catch (PersistenceException e) {
manager.getTransaction().rollback();
throw e;
} finally {
manager.close();
}
}
public void borrar(Libro libro) {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
try {
tx=manager.getTransaction();
tx.begin();
manager.remove(manager.merge(libro));
tx.commit();
} catch (PersistenceException e) {
manager.getTransaction().rollback();
throw e;
} finally {
manager.close();
}}
public void salvar(Libro libro) {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
try {
tx=manager.getTransaction();
tx.begin();
manager.merge(libro);
tx.commit();
} catch (PersistenceException e) {
manager.getTransaction().rollback();
throw e;

216
www.arquitecturajava.com!

} finally {
manager.close();
}
}
public List<Libro> buscarTodos() {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
TypedQuery<Libro> consulta = manager.createQuery(
"Select l from Libro l", Libro.class);
List<Libro> listaDeLibros = null;
try {
listaDeLibros = consulta.getResultList();
} finally {
manager.close();
}
return listaDeLibros;
}
public Libro buscarPorClave(String isbn) {

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
TypedQuery<Libro> consulta = manager.createQuery(
"Select l from Libro l where l.isbn=?1", Libro.class);
consulta.setParameter(1, isbn);
Libro libro = null;
try {
libro = consulta.getSingleResult();
} finally {
manager.close();
}
return libro;
}
public List<Libro> buscarPorCategoria(Categoria categoria) {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
TypedQuery<Libro> consulta = manager.createQuery(
"Select l from Libro l where l.categoria=?1", Libro.class);
consulta.setParameter(1, categoria);
List<Libro> listaDeLibros = null;
try {
listaDeLibros = consulta.getResultList();
} finally {
manager.close();
}
return listaDeLibros;
}
}
!

217
Arquitectura*Java!

El!cdigo!fuente!de!ambas!clases!es!prcticamente!idntico!a!lo!que!tenamos!antes!de!
separarlas,! exceptuando! que! los! mtodos! de! la! clase! LibroDAO! reciben! ahora! como!
parmetros!Libros!y!han!dejado!de!ser!estticos.!Una!vez!visto!este!refactoring,!vamos!
a!ver!como!quedara!el!cdigo!en!nuestras!acciones;!a!continuacin!mostramos!una!de!
ellas.!

Cdigo!13.4:!MostrarLibroAccion.java)!

@Override
public String ejecutar(HttpServletRequest request,
HttpServletResponse response) {
LibroDAO libroDAO = new LibroDAO();
CategoriaDAO categoriaDAO = new CategoriaDAO();
List<Libro> listaDeLibros = libroDAO.buscarTodos();
List<Categoria> listaDeCategorias =
categoriaDAO.buscarTodos();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";
}
!

Hemos! terminado! de! aplicar! el! principio! ISP! a! nuestra! aplicacin.! Seguidamente!
avanzaremos!en!el!diseo!de!la!capa!DAO!para!aportar!flexibilidad.!

2. Uso!de!interfaces!en!componentes!DAO!

Acabamos!de!separar!de!forma!clara!la!capa!de!persistencia!de!la!capa!de!negocio!en!
nuestra!aplicacin.!En!estos!momentos!la!capa!de!persistencia!esta!construida!con!JPA!
pero!en!ejemplos!anteriores!ha!estado!construida!con!Hibernate!o!con!JDBC!.As!pues!
hemos!tenido!una!evolucin!en!cuanto!a!cmo!construimos!esta!capa!de!persistencia!
(ver!imagen).!

218
www.arquitecturajava.com!

Muchas! aplicaciones! enterprise! tienen! un! tiempo! de! vida! amplio.! Es! habitual! que! la!
capa! de! persistencia! evolucione! con! el! paso! del! tiempo! y! de! las! versiones! de! la!
aplicacin.!As!pues,!es!interesante!disear!esta!capa!de!forma!que,!en!caso!de!migrar!
de!JDBC!a!Hibernate!o!de!Hibernate!a!JPA,!los!cambios!a!realizar!en!el!cdigo!sean!los!
mnimos! posibles.! As! pues! vamos! a! construir! un! interface! LibroDAO! y! un! Interface!
CategoraDAO! de! los! cules! se! puedan! generar! varias! implementaciones! (ver!
imagen).

Para! poder! generar! estos! interfaces! hay! que! redisear! el! conjunto! de! paquetes! que!
estamos! utilizando! .A! partir! de! ahora! usaremos! los! siguientes! ! en! cuanto! a! capa! de!
persistencia:!

com.arquitecturajava.dao! :! Paquete! que! contiene! nicamente! los! interfaces!


DAO!!
com.arquitecturajava.dao.jpa:! Paquete! que! contiene! la! implementacin! para!
JPA.!

219
Arquitectura*Java!

Vamos!a!ver!a!continuacin!una!imagen!que!clarifica!la!estructura. !

Una!vez!clara!la!estructura!de!la!capa!de!persistencia,!vamos!a!ver!el!cdigo!fuente!de!
uno! de! estos! interfaces,! concretamente! el! interface! LibroDAO,! el! caso! del! interface!
CategoraDAO!es!muy!similar.!

Cdigo!13.5:!(LibroDAO.java)!

package com.arquitecturajava.aplicacion.dao;
import java.util.List;
import com.arquitecturajava.aplicacion.bo.Categoria;
import com.arquitecturajava.aplicacion.bo.Libro;

public interface LibroDAO {

public abstract void borrar(Libro libro);


public abstract void salvar(Libro libro);
public abstract List<Libro> buscarTodos();
public abstract Libro buscarPorClave(String isbn);
public abstract List<Libro> buscarPorCategoria(Categoria categoria);
}
!

Una! vez! creado! el! interface! podemos! ! hacer! que! nuestra! clase! LibroDAOJPAImpl!
implemente!el!interface.!

Cdigo!13.6:!(LibroDAOJPAImpl.java)!

public class LibroDAOJPAImpl implements LibroDAO {


// el resto del codigo no varia
}
!

220
www.arquitecturajava.com!

Con! esta! tarea! hemos! ganado! en! flexibilidad! a! la! hora! de! poder! evolucionar! nuestra!
aplicacin!de!una!forma!sencilla!entre!un!sistema!de!persistencia!y!otro.!Es!momento!
de! revisar! la! estructura! de! nuestras! clases! DAO! referentes! ! a! JPA!!
(LibroDAOJPAImpl,CategoriaDAOJPAImpl)! ! para! que! nos! demos! cuenta! de! que! todas!
ellas!comparten!la!misma!estructura!incluso!si!aadimos!nuevas!clases!(ver!imagen).!

Este!es!un!claro!sntoma!de!que!quizs!nuestras!clases!de!persistencia!no!cumplen!del!
todo! con! el! principio! DRY! y! mucha! funcionalidad! est! repetida.! La! siguiente! tarea! se!
encargar!de!abordar!este!problema.!

3. El!principio!DRY!y!!el!patrn!GenericDAO!

En!primer!lugar!vamos!a!disear!un!nuevo!interface!que!incluya!las!funciones!que!sern!
compartidas! por! todas! las! clases! de! forma! idntica! (borrar,! salvar,! buscarPorClave,!
buscarTodos).!Para!ello!vamos!a!construir!un!interface!distinto!a!los!anteriores,!ya!que!
se!tratar!de!un!interface!de!tipo!Genrico!de!tal!forma!que!sean!luego!ms!adelante!
cada! una! de! las! clases! las! que! definan! ! a! qu! tipo! hace! referencia! ! .Vamos! a! ver! un!
diagrama!aclaratorio:!

221
Arquitectura*Java!

Una! vez! tenemos! claro! cul! es! el! interface! definido! como! genrico,! vamos! a! ver! su!
cdigo.!

Cdigo!13.7:!(GenericDAO.java)!

package com.arquitecturajava.aplicacion.dao;

import java.io.Serializable;
import java.util.List;
public interface GenericDAO<T,Id extends Serializable> {
T buscarPorClave (Id id);
List<T>buscarTodos();
void salvar(T objeto);
void borrar(T objeto);
}
!

Creada!este!interface,!construiremos!una!clase!!Genrica!que!implemente!el!interface!
implementando!los!mtodos!de!forma!genrica!(ver!imagen).!

222
www.arquitecturajava.com!

Al!hacer!uso!de!genricos!podremos!eliminar!una!gran!parte!de!la!repeticin!de!cdigo!
que! tenemos! en! nuestras! clases! DAO! de! JPA! .A! continuacin! se! muestra! la! clase!
completa!con!todos!sus!mtodos.!

223
Arquitectura*Java!

Cdigo!13.8:!(GenericDAOJPAImpl)!

//omitimos imports etc


public abstract class GenericDAOJPAImpl<T, Id extends Serializable> implements
GenericDAO<T, Id> {
private Class<T> claseDePersistencia;
@SuppressWarnings("unchecked")
public GenericDAOJPAImpl() {
this.claseDePersistencia = (Class<T>) ( (ParameterizedType)
getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
@Override
public T buscarPorClave(Id id) {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
T objeto = null;
try {
objeto = (T) manager.find(claseDePersistencia, id);
return objeto;
} finally {
manager.close();
}
}
@Override
public List<T> buscarTodos() {

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
List<T> listaDeObjetos = null;
try {

TypedQuery<T> consulta = manager.createQuery("select o from "


+ claseDePersistencia.getSimpleName()+ " o",
claseDePersistencia);

listaDeObjetos = consulta.getResultList();
return listaDeObjetos;
} finally {
manager.close();
}
}
public void borrar(T objeto) {

EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();


EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
try {
tx = manager.getTransaction();
tx.begin();
manager.remove(manager.merge(objeto));

224
www.arquitecturajava.com!

tx.commit();
} catch (PersistenceException e) {
tx.rollback();
throw e;
} finally {
manager.close();
}
}
public void salvar(T objeto) {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
try {
tx = manager.getTransaction();
tx.begin();
manager.merge(objeto);
tx.commit();
} catch (PersistenceException e) {
tx.rollback();
throw e;
} finally {
manager.close();
}
}
public void insertar(T objeto) {
EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
EntityTransaction tx = null;
try {
tx = manager.getTransaction();
tx.begin();
manager.persist(objeto);
tx.commit();
} catch (PersistenceException e) {
tx.rollback();
throw e;
} finally {
manager.close();
}
}
}
!

El!cdigo!de!esta!clase!genera!las!operaciones!de!!persistencia!elementales!para!todas!
las!clases!DAO.!Por!lo!tanto!no!es!necesario!implementar!estos!mtodos!en!las!clases!
hijas.,ya! que! si! estas! clases! extienden! de! la! clase! GenericDAOJPAImpl! es! suficiente.! A!
continuacin!se!muestra!una!imagen!aclaratoria.!

225
Arquitectura*Java!

Una! vez! que! tenemos! claro! como! la! clase! GenericDAOJPAImpl! nos! ayuda! en! el!!
desarrollo! de! nuestra! aplicacin,! es! momento! de! ver! el! cdigo! fuente! de! la! clase!
LibroJPAImpl!y!de!la!Clase!CategoriaJPAImpl!para!ver!como!quedan!simplificadas.!!

226
www.arquitecturajava.com!

Cdigo!13.9:!(LibroDAOJPAImpl.java)!

package com.arquitecturajava.aplicacion.dao.jpa;

public class LibroDAOJPAImpl extends GenericDAOJPAImpl<Libro, String>


implements LibroDAO {

public List<Libro> buscarPorCategoria(Categoria categoria) {


EntityManagerFactory factoriaSession = JPAHelper.getJPAFactory();
EntityManager manager = factoriaSession.createEntityManager();
CategoriaDAO cdao= new CategoriaDAOJPAImpl();

TypedQuery<Libro> consulta = manager.createQuery(


"Select l from Libro l where l.categoria=?1",
Libro.class);
consulta.setParameter(1, categoria);
List<Libro> listaDeLibros = null;
try {
listaDeLibros = consulta.getResultList();
} finally {
manager.close();
}
return listaDeLibros;
}

Cdigo!13.10:!(CategoriaDAOJPImpl.java)!

package com.arquitecturajava.aplicacion.dao.jpa;

import com.arquitecturajava.aplicacion.bo.Categoria;
import com.arquitecturajava.aplicacion.dao.CategoriaDAO;

public class CategoriaDAOJPAImpl extends GenericDAOJPAImpl<Categoria,


Integer> implements CategoriaDAO {
//no hay nada que aadir todo lo aporta la clase GenericDAO de la cual extendemos
}
!

Como!podemos!ver,!el!caso!de!la!clase!CategoriaDAOImpl!es!el!ms!exagerado!de!todos!
ya!que!la!clase!genrica!consigue!eliminar!todos!los!mtodos!que!tenia!e!incluso!aadir!
algunos! que! nos! podrn! ser! tiles.! Tras! construir! estas! clases,! podemos! ver! como!
queda!la!estructura!de!clases!de!persistencia!en!nuestro!proyecto.!

227
Arquitectura*Java!

4. Rendimiento!

En!muchos!casos!el!uso!bsico!de!Hibernate!acaba!en!soluciones!cuya!escalabilidad!es!
reducida,!no!por!el!uso!del!framework!sino!por!la!falta!de!conocimiento!por!parte!del!
desarrollador! .! Frecuentemente! nuestro! modelo! de! clases! deber! sobreescribir!
mtodos!para!mejorar!el!rendimiento!del!framework!ORM.!A!continuacin!se!muestra!
un! ejemplo! sencillo! donde! se! sobrecarga! el! mtodo! buscarTodos! para! obtener! un!
mejor!rendimiento.!

Cdigo!13.10:!(LibroDAOJPAImpl.java)!

public List<Libro> buscarTodos() {

TypedQuery<Libro> consulta = getManager().createQuery("SELECT l FROM Libro l


JOIN FETCH l.categoria",Libro.class);
return consulta.getResultList();

Resumen!
En!este!captulo!hemos!visto!!cmo!el!principio!ISP!y!el!principio!SRP!nos!orientan!hacia!
el!diseo!de!una!capa!de!persistencia!ms!flexible!mientras!que!el!principio!DRY!y!el!uso!
de! Genricos! nos! permite! eliminar! mucha! funcionalidad! repetida! entre! las! distintas!
clases! que! definen! la! capa! DAO.! Por! ltimo,! hemos! revisado! brevemente! temas! de!
rendimiento.!

228
www.arquitecturajava.com!

229
Arquitectura*Java!

14.El$principio'de'inversin'de'control'y'
patrn'factory!

En!el!captulo!anterior!hemos!aplicado!el!principio!ISP!y!con!l!hemos!construido!una!
capa! de! persistencia! basada! en! el! patrn! DAO.! Esto! nos! ha! permitido! separar! las!
responsabilidades!de!negocio!y!persistencia!.En!este!captulo!vamos!a!modificar!la!capa!
de! persistencia! para! que! no! solo! admita! varios! sistemas! de! persistencia!
(jdbc,hibernate,jpa)!a!travs!del!uso!de!interfaces,!sino!para!que!adems!sea!sencillo!o!
transparente! cambiar! unas! implementaciones! por! otras.! En! estos! momentos!
disponemos!de!dos!posibles!implementaciones!de!capa!!de!!persistencia:!una!basada!en!
Hibernate! y! otra! basada! en! Hibernate! sobre! JPA.! A! continuacin! se! muestra! cmo!
hemos!hecho!evolucionar!el!cdigo!en!el!captulo!anterior.!

230
www.arquitecturajava.com!

Ahora!bien,!para!realizar!estos!cambios!no!nos!ha!quedado!ms!remedio!que!modificar!
el! cdigo! fuente! de! nuestras! Acciones.! Si! ! en! algn! momento! quisiramos! realizar! el!
proceso! inverso,! tendramos! que! volver! a! cambiar! estas.! Esto! se! debe! a! que! la!
responsabilidad! ! sobre! el! tipo! de! objeto! de! persistencia! para! construir! recae! en! el!
programador!y!en!el!cdigo!que!l!construye!en!las!diferentes!acciones!(ver!imagen).!

Si!en!algn!momento!queremos!cambiar!de!tipo!de!persistencia,!ser!el!programador!
quien!deber!realizar!los!cambios.!Este!diseo!no!cumple!con!el!principio!OCP!ya!que!si!
queremos!cambiar!la!capa!de!persistencia,!nos!veremos!obligados!a!modificar!el!cdigo!
que! previamente! hemos! construido.! En! este! captulo! vamos! a! introducir! un! nuevo!
principio! de! ingeniera:! el! principio! de! Inversin! de! Control! que! nos! ayudar! a!
solventar! este! problema! y! permitir! que! ! nuestra! capa! de! persistencia! pueda!
evolucionar!cumpliendo!con!OCP.!Vamos!a!explicar!este!principio.!

Inversin!de!Control!(Inversion!of!Control!o!IOC):!El!principio!de!inversin!de!
control! consiste! en! que! el! control! de! la! construccin! de! los! objetos! no! recae!!
directamente!en!el!desarrollador!a!travs!del!uso!del!operador!new,!!sino!que!
es!otra!clase!o!conjunto!de!clases!las!que!se!encargan!de!construir!los!objetos!
que!necesitamos.!Aunque!la!definicin!es!de!entrada!algo!confusa,!durante!el!
resto!del!captulo!la!iremos!clarificando!a!travs!de!la!creacin!de!ejemplos.!!

Objetivos :

Aplicar! el! principio! de! inversin! de! control! IOC! a! la! capa! de! persistencia! de!
nuestra!aplicacin.!

231
Arquitectura*Java!

Tareas :

1. Crear!factorias!e!implementar!el!principio!de!IOC.!
2. El!principio!DRY!y!el!patrn!Abstract!Factory.!
3. El!patrn!Abstract!Factory!y!el!uso!de!interfaces.!

1. Crear!Factoras!e!implementar!el!principio!de!IOC,!

Para! implementar! el! principio! de! IOC! en! nuestra! aplicacin! debemos! aadirle! nuevas!
clases!que!se!encarguen!de!construir!los!distintos!objetos!de!la!capa!de!persistencia!.!
Como!punto!de!partida!vamos!a!revisar!el!cdigo!fuente!de!una!de!nuestras!acciones!
para!ver!cmo!construye!los!distintos!objetos!de!la!capa!DAO.!

LibroDAOJPAImpl!!
CategoriaDAOJPAImpl.!

A!continuacin!se!muestra!el!cdigo!fuente!de!la!clase!MostrarLibrosAccion.!

Cdigo!14.1:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequest request,


HttpServletResponse response) {

LibroDAO libroDAO = new LibroDAOJPAImpl();


CategoriaDAO categoriaDAO = new CategoriaDAOJPAImpl();
List<Libro> listaDeLibros = libroDAO.buscarTodos();
List<Categoria> listaDeCategorias = categoriaDAO.buscarTodos();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";

Como!podemos!ver,!es!responsabilidad!del!programador!que!desarrolla!la!aplicacin!el!
crear!cada!uno!de!los!distintos!objetos!de!la!capa!DAO.!Segn!la!definicin!del!principio!
de!inversin!de!control,!no!ser!a!partir!de!ahora!el!programador!el!que!construya!los!
distintos!de!objetos!de!!la!capa!de!persistencia,!sino!que!se!encargar!otra!clase.!Vamos!
a!ver!el!cdigo!fuente!de!la!clase!LibroDAOFactory!que!sera!la!encargada!de!crear!los!
objetos!de!tipo!LibroDAO.!

232
www.arquitecturajava.com!

Cdigo!14.2:!(LibroDAO.java)!

public class LibroDAOFactory {


public static LibroDAO getInstance() {
String tipo = "JPA";
if (tipo.equals("Hibernate")) {
return LibroDAOHibernateImpl();
} else {
returnnew LibroDAOJPAImpl();
}
}
}
!

Como! el! cdigo! muestra,! esta! clase! tiene! la! responsabilidad! de! construir! las! distintas!
implementaciones!que!existan!del!interface!LibroDAO!(ver!imagen).!

De! esta! manera! y! dependiendo! del! tipo! de! persistencia! ! definamos,! la! factora! nos!
devuelve! una! implementacin! u! otra.! Habitualmente! las! factoras! se! apoyan! en! un!
fichero!de!properties!para!leer!el!tipo!de!persistencia!que!estamos!utilizando.!En!este!
caso! nosotros! devolveremos! siempre! la! implementacin! de! JPA! por! simplicidad! .Una!
vez!que!hemos!construido!esta!clase!factora,!vamos!a!ver!cmo!queda!el!cdigo!fuente!
de! cada! una! de! nuestras! acciones! .Para! ello! vamos! a! mostrar! el! cdigo! de! la! accin!
MostrarLibros,! ya! que! usa! tanto! la! clase! de! persistencia! CategoriaDAO! como! la! clase!
LibroDAO.!

!
233
Arquitectura*Java!

Cdigo!14.3:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequest request,


HttpServletResponse response)
CategoriaDAO categoriaDAO= CategoriaDAOFactory.getInstance();
LibroDAO libroDAO= LibroDAOFactory.getInstance();
List<Libro> listaDeLibros = libroDAO.buscarTodos();
List<Categoria> listaDeCategorias = categoriaDAO.buscarTodos();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";
}
!

El! cdigo! no! es! complicado! de! entender! y! podemos! ver! como! ya! el! programador! no!
necesita!hacer!uso!del!operador!new!sino!que!se!apoyar!en!dos!factoras!que!hemos!
construido,!una!para!los!Libros!y!otra!para!las!Categoras.!De!esta!forma!simplemente!
cambiando! la! implementacin! que! devuelve! cada! una! las! factoras! podremos!
intercambiar!una!capa!de!persistencia!por!otra!(obligando!por!ejemplo!a!las!factoras!a!
leer! la! implementacin! de! un! fichero! de! propiedades).! Sin! embargo,! para! conseguir!
este!nivel!de!transparencia!a!la!hora!de!poder!intercambiar!las!capas!de!persistencia!y!
ganar!en!flexibilidad,!debemos!pagar!un!precio!bastante!alto:!por!cada!clase!de!negocio!
que!tengamos!!aparecer!una!nueva!factora!(ver!imagen).!

234
www.arquitecturajava.com!

Esto!es!un!problema!!importante!ya!que!nos!encontraremos!con!una!violacin!clara!del!
principio!DRY!pues!prcticamente!todas!las!factoras!que!construimos!son!idnticas,!ya!
que! todas! cubren! la! misma! funcionalidad! al! elegir! una! implementacin! u! otra! de! la!
capa! de! persistencia.! A! continuacin! se! muestra! el! cdigo! fuente! de! la! factora!
CategoraDAOFactory!,!podemos!advertir!que!es!prcticamente!idntico!al!cdigo!de!la!
factora!LibroDAOFactory.!

235
Arquitectura*Java!

Cdigo!14.4:!(CategoriaDAOFactory.java)!

public class CategoriaDAOFactory {


public static CategoriaDAO getInstance() {
String tipo = "JPA";
if (tipo.equals("Hibernate")) {
return new CategoriaDAOHibernateImpl();
} else {
return new CategoriaDAOJPAImpl();
}
}
}

As!pues!tenemos!un!problema!de!repeticin!de!funcionalidad!(ver!imagen).

236
www.arquitecturajava.com!

Por! lo! tanto! debemos! refactorizar! nuestro! cdigo! para! evitar! tantas! repeticiones! de!
funcionalidad!y!a!la!vez!mantener!la!capacidad!que!tiene!nuestra!aplicacin!de!cambiar!
de!implementacin!de!capa!de!persistencia!de!forma!transparente!(Hibernate,!JPA!etc)!
.!Para!ello!la!siguiente!tarea!se!encargara!de!solventar!este!problema.!

2. El!principio!DRY!y!el!patrn!Abstract!Factory!

La! estructura! de! clases! de! capa! de! persistencia! que! tenemos! tiene! una! peculiaridad! :!
pueden!ser!agrupadas!por!familias.!Una!familia!sera!la!implementacin!de!JPA!y!otra!
familia!sera!la!implementacin!de!Hibernate!(ver!imagen).!

Cuando!tenemos!esta!casustica!tan!especial!existe!un!patrn!de!diseo!que!nos!puede!
ayudar!a!cumplir!con!el!principio!IOC!y!mantener!nuestro!compromiso!con!el!principio!
DRY,! permitindonos! ! por! lo! tanto! cambiar! de! forma! transparente! entre! una!
implementacin!y!otra!sin!tener!que!pagar!un!alto!precio!!de!repeticin!de! cdigo!en!
nuestra! aplicacin.! Este! patrn! de! diseo! se! denomina! Abstract! Factory! ,! vamos! a!
introducirlo!a!continuacin.

237
Arquitectura*Java!

El!patrn!abstract!factory!es!un!patrn!de!diseo!que!se!apoya!en!la!construccin!de!un!
grupo!reducido!de!factoras.!Concretamente!una!factora!por!cada!familia!de!clases!que!
tengamos! y! otra! factora! que! agrupa! a! las! factoras! encargadas! de! ! crear! las! familias!
.As,!en!nuestro!ejemplo!tendremos!la!necesidad!de!construir!tres!factoras.!

1. Crear!una!factora!para!la!familia!de!Hibernate!!
2. Crear!una!factora!para!la!familia!de!JPA!
3. Crear!una!factora!para!las!dos!factoras!que!hemos!creado!

As!pues!vamos!a!empezar!con!la!primera!tarea!construir!una!factora!que!sea!capaz!de!
crear! todos! los! objetos! de! una! de! las! familias,! para! ello! elegiremos! la! familia! de! JPA.!
Nuestra!factora!tendr!la!peculiaridad!de!tener!un!mtodo!por!cada!una!de!las!clases!
JPA! que! construyamos.! A! continuacin! se! muestra! un! diagrama! aclaratorio! de! cmo!
est!construida!esta!factora.!

Una!vez!creada!la!factora!de!!JPA,!!vamos!a!ver!su!cdigo!fuente!para!que!nos!ayude!a!
asentar!ideas.!

238
www.arquitecturajava.com!

Cdigo!14.5:!(DAOJPAFactory.java)!

public class DAOJPAFactory {


public CategoriaDAO getCategoriaDAO() {
return new CategoriaDAOJPAImpl();
}
public LibroDAO getLibroDAO() {
return new LibroDAOJPAImpl();
}
}

La! factora! nos! devuelve! los! objetos! que! pertenecen! ! a! la! familia! de! JPA!!
LibroDAOJPAImpl!y!CategoriaDAOJPAImpl.!Vamos!a!ver!a!continuacin!el!cdigo!de!la!
factora!que!se!encarga!de!la!otra!familia!la!familia!de!Hibernate.!

Cdigo!14.6:!(DAOHibernateFactory.java)!

public class DAOHibernateFactory {


public CategoriaDAO getCategoriaDAO() {
return new CategoriaDAOHibernateImpl();
}
public LibroDAO getLibroDAO() {
return new LibroDAOHibernateImpl();
}
}
!

Una!vez!creadas!ambas!clases!,!es!fcil!identificar!que!comparten!el!mismo!conjunto!de!
mtodos!y!por!lo!tanto!se!puede!definir!un!interface!comn!para!ambas,!como!el!que!
se!muestra!en!el!siguiente!diagrama.!!

239
Arquitectura*Java!

A! continuacin! se! muestra! el! cdigo! fuente! del! interface! para! el! caso! sencillo! de!
nuestra!aplicacin.!

Cdigo!14.7:!(DAOFactory.java)!

package com.arquitecturajava.aplicacion.dao;

public interface DAOFactory {


public CategoriaDAO getCategoriaDAO();
public LibroDAO getLibroDAO();
}

Una! vez! definido! el! interface,! obligaremos! a! cada! una! de! nuestras! factoras! a!
implementarlo!!

Cdigo!14.8:!(DAOJPAFactory.java)!

public class DAOJPAFactory implements DAOFactory {


// resto del cdigo
}
!

240
www.arquitecturajava.com!

Cdigo!14.9:!(DAOJPAFactory.java)!

public class DAOHibernateFactory implements DAOFactory {


// resto del cdigo
}

!Definido!el!interface!comn!para!ambas!factoras,!!nos!encontramos!con!que!podemos!
definir! una! factora! que! nos! devuelva! una! implementacin! de! este! interface! para! JPA!!
(DAOJPAFactory)! o! una! implementacin! para! Hibernate! (DAOHibernateFactory),! algo!
muy!similar!a!lo!que!hacamos!antes.!A!esta!factora,!dado!que!crea!objetos!que!son!de!
tipo! ! factora,! se! la! denomina! AbstractFactory.! La! siguiente! figura! muestra! la! relacin!
entre!las!distintas!clases.!

241
Arquitectura*Java!

A!continuacin!se!muestra!su!cdigo!fuente.!

Cdigo!14.10:!(DAOAbstractFactory.java)!

package com.arquitecturajava.aplicacion.dao;

public abstract class DAOAbstractFactory {


public static DAOFactory getInstance() {
String tipo="JPA";
if (tipo.equals("Hibernate")) {
new DAOHibernateFactory();
} else {
returnnew DAOJPAFactory();}}
}

Esta!clase!crea!objetos!bien!de!un!tipo!de!factora!bien!de!otro!.!Ms!tarde!cada!una!de!
las! factoras! creadas! sern! las! encargadas! de! devolvernos! los! distintos! objetos! DAO!
para!una!implementacin!concreta.!A!continuacin!se!muestra!cmo!se!usa!a!nivel!de!
las! acciones! el! concepto! de! AbstractFactory! y! de! Factory,! poniendo! como! ejemplo! el!
mtodo!ejecutar!de!MostrarLibrosAccion.!

Cdigo!14.11:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequest request,


HttpServletResponse response) {
DAOFactory factoria= DAOAbstractFactory.getInstance().
CategoriaDAO categoriaDAO= factoria.getCategoriaDAO();
LibroDAO libroDAO=factoria.getLibroDAO();
List<Libro> listaDeLibros = libroDAO.buscarTodos();
List<Categoria> listaDeCategorias = categoriaDAO.buscarTodos();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";
}

A! partir! de! este! momento! el! programador! crear! una! instancia! de! la! clase!
AbstractFactory! la! cul! se! apoyara! habitualmente! en! un! fichero! de! propiedades! para!
elegir! qu! familia! de! objetos! de! persistencia! construir.! Una! vez! hecho! esto,! nos!
encontramos!con!que!el!nuevo!diseo!de!la!aplicacin!cumple!con!el!principio!IOC!y!con!

242
www.arquitecturajava.com!

el! principio! DRY! a! nivel! de! capa! de! persistencia,! permitindonos! variar! entre! una!
implementacin!y!otra!de!forma!transparente!(ver!imagen).!

Resumen!
Una!vez!rediseada!la!capa!de!persistencia!podremos!de!una!manera!sencilla!cambiar!
una! capa! por! otra! sin! tener! necesidad! de! tocar! el! cdigo! fuente,! cumpliendo! con! el!
principio!OCP.!Para!ello!habremos!aadido!las!siguientes!clases!a!la!capa!DAO:!

243
Arquitectura*Java!

15.El#Principio"DRY"y"el"patrn"servicio!

En!el!captulo!anterior!hemos!aadido!versatilidad!a!la!capa!de!persistencia!utilizando!
los!siguientes!patrones!de!diseo.!

Factory!
Abstract!Factory!

permitindonos! intercambiar! las! distintas! capas! de! persistencia! de! forma!


prcticamente!transparente!!como!muestra!la!figura.!

Sin! embargo,! para! poder! disponer! de! esta! funcionalidad,! hemos! tenido! que! sacrificar!
algo! :hemos! incrementado! la! complejidad! del! manejo! de! la! capa! de! persistencia! por!
parte!de!los!desarrolladores!y!se!necesita!un!conjunto!de!clases!mayor!que!antes!para!
realizar!las!mismas!operaciones!(ver!imagen).!

244
www.arquitecturajava.com!

Es! momento! de! abordar! este! problema! .El! objetivo! principal! de! este! captulo! ser!
simplificar! el! trabajo! de! los! desarrolladores! con! la! capa! de! persistencia! al! construir! la!
capa! de! presentacin! e! interactuar! con! la! misma.! Enumeremos! los! objetivos! y! tareas!
planteados:!

Objetivos:!

Simplificar!el!acceso!a!la!capa!de!persistencia!

Tareas:!

1. Uso!del!principio!DRY!!en!el!acceso!a!la!capa!de!persistencia!
2. Creacin!de!una!clase!de!servicio!que!simplifique!el!acceso.!

1. El!principio!DRY!y!el!acceso!a!la!capa!de!persistencia!

Vamos!a!revisar!el!cdigo!fuente!de!la!clase!MostrarLibrosAccion!del!captulo!anterior!
una!vez!hemos!hecho!uso!de!factoras!para!aadir!flexibilidad!a!esta!capa.!

245
Arquitectura*Java!

Cdigo!15.1:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequest request,


HttpServletResponse response) {

DAOFactory factoria= DAOAbstractFactory.getInstance().


CategoriaDAO categoriaDAO= factoria.getCategoriaDAO();
LibroDAO libroDAO=factoria.getLibroDAO();
List<Libro> listaDeLibros = libroDAO.buscarTodos();
List<Categoria> listaDeCategorias = categoriaDAO.buscarTodos();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";
}

Como!podemos!ver!se!ha!hecho!uso!de!las!factoras!y!del!abstract!factory!para!generar!
los!objetos!que!pertenecen!a!la!capa!de!persistencia.!Ahora!bien!si!revisamos!alguna!de!
nuestras! otras! acciones! (como! por! ejemplo! la! accin! de! FormularioEditarLibro! cuyo!
cdigo!se!muestra!a!continuacin),!

Cdigo!15.2:!(FormularioEditarLibro.java)!

public String ejecutar(HttpServletRequest request,


HttpServletResponse response) {

DAOFactory factoria= DAOAbstractFactory.getInstance().


CategoriaDAO categoriaDAO= factoria.getCategoriaDAO();
LibroDAO libroDAO=factoria.getLibroDAO();

String isbn = request.getParameter("isbn");


List<Categoria> listaDeCategorias = categoriaDAO.buscarTodos();
Libro libro = libroDAO
.buscarPorClave(request.getParameter("isbn"));
request.setAttribute("listaDeCategorias", listaDeCategorias);
request.setAttribute("libro", libro);
return "FormularioEditarLibro.jsp";
}

nos! podremos! dar! cuenta! de! que! comparten! el! mismo! cdigo! fuente! de! inicializacin!
de!las!factoras!a!la!hora!de!utilizar!la!capa!de!persistencia!.Este!es!un!problema!claro!de!
repeticin!de!cdigo!en!el!cul!no!se!est!utilizando!el!principio!DRY!(ver!imagen).!

246
www.arquitecturajava.com!

2. Creacin!de!una!clase!de!Servicio!

Si!queremos!eliminar!las!repeticiones!de!cdigo!que!tenemos!en!cada!una!de!nuestras!
acciones,!debemos!crear!una!nueva!clase!que!se!encargue!de!centralizar!la!creacin!de!
los! objetos! de! la! capa! DAO! para! un! subconjunto! de! clases! relacionadas! a! nivel! de!
negocio.! A! estas! clases! se! las! denomina! habitualmente! clases! de! servicio! y! como!
podemos!ver!en!la!siguiente!figura,!un!grupo!de!acciones!delega!en!ellas.!

247
Arquitectura*Java!

Para!que!esta!nueva!capa!que!aparece!en!la!aplicacin!pueda!disponer!posteriormente!
de! una! flexibilidad! similar! a! la! que! dispone! la! capa! de! persistencia,! la! construiremos!
apoyndonos! en! el! uso! de! interfaces.! En! nuestro! caso! construiremos! un! servicio!
denominado! servicioLibros! que! agrupa! la! funcionalidad! asociada! a! la! gestin! de! ! los!
libros! y! sus! categoras.! A! continuacin! se! muestra! un! diagrama! aclaratorio! de! la!
estructura.!

Tenemos!claro!ya!el!interfaces!y!el!servicio.!Vamos!a!pasar!a!mostrar!el!cdigo!fuente!
del!interface!de!servicio.!

Cdigo!15.3:!(ServicioLibros.java)!

package com.arquitecturajava.aplicacion.servicios;
import java.util.List;
import com.arquitecturajava.aplicacion.bo.Categoria;
import com.arquitecturajava.aplicacion.bo.Libro;
public interface ServicioLibros {
public void salvarLibro(Libro libro);
public void borrarLibro(Libro libro);
public List<Libro> buscarTodosLosLibros();
public List<Categoria> buscarCategoriasLibros();
public Libro buscarLibroPorClave(String isbn);
public Categoria buscarCategoriaPorClave(int id);
public List<Libro> buscarLibrosPorCategoria(int categoria);
}

Definido! el! interface! ,vamos! a! ver! su! implementacin! y! cmo! sta! delega! en! las!
factoras!que!hemos!creado!anteriormente!para!realizar!su!funcionalidad.!

!
248
www.arquitecturajava.com!

Cdigo!15.4:!(ServicioLibros.java)!

package com.arquitecturajava.aplicacion.servicios.impl;

// omitidos imports
public class ServicioLibrosImpl implements ServicioLibros {

private LibroDAO libroDAO=null;


private CategoriaDAO categoriaDAO=null;
public ServicioLibrosImpl() {
DAOFactory factoria= DAOAbstractFactory.getInstance();
libroDAO= factoria.getLibroDAO();
categoriaDAO=factoria.getCategoriaDAO();
}

public void salvarLibro(Libro libro) {


libroDAO.salvar(libro);
}
public void borrarLibro(Libro libro) {
libroDAO.borrar(libro);
}
public List<Libro> buscarTodosLosLibros() {
return libroDAO.buscarTodos();
}
public List<Categoria> buscarCategoriasLibros() {
return categoriaDAO.buscarTodos();
}

public Libro buscarLibroPorClave(String isbn) {


return libroDAO.buscarPorClave(isbn);
}
public Categoria buscarCategoriaPorClave(int id) {
return categoriaDAO.buscarPorClave(id);
}
public List<Libro> buscarLibrosPorCategoria(int id) {
Categoria categoria= categoriaDAO.buscarPorClave(id);
return libroDAO.buscarPorCategoria(categoria);
}
}

249
Arquitectura*Java!

Una!vez!construida!esta!clase,!podemos!ver!como!su!constructor!se!encarga!de!poner!a!
nuestra!disposicin!las!distintas!factoras!necesarias.!La siguiente imagen muestra!la!
relacin!entre!la!capa!de!servicios,!la!capa!de!persistencia!y!la!capa!de!presentacin!y!
cmo!el!construir!esta!capa!reduce!la!repeticin!de!cdigo.!

Construida! la! clase! de! servicio,! vamos! a! ver! ! por! ltimo! cmo! el! cdigo! fuente! de! la!
clases! de! accin! queda! simplificado.! Seguidamente! se! muestra! el! nuevo! cdigo! de! la!
clase!MostrarLibrosAccion.!

Cdigo!15.5:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequest request,


HttpServletResponse response) {
ServicioLibros servicioLibros= new ServicioLibrosImpl();
List<Libro> listaDeLibros = servicioLibros.buscarTodosLosLibros();
List<Categoria> listaDeCategorias =
servicioLibros.buscarCategoriasLibros();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";
}

250
www.arquitecturajava.com!

Una!vez!realizados!estos!cambios!podemos!mostrar!los!nuevos!ficheros!y!paquetes!que!
aparecen!en!nuestra!aplicacin.!

Resumen!
En!este!captulo!nos!hemos!centrado!en!simplificar!el!acceso!a!la!capa!de!persistencia!
apoyndonos! para! ello! en! la! construccin! de! una! nueva! capa:! la! capa! de! servicios!
clsica.!

251
Arquitectura*Java!

16.El#principio#IOCy#el#framework#
Spring!

En! el! captulo! anterior! hemos! construido! una! capa! de! servicios! que! nos! ha! permitido!
eliminar!repeticiones!innecesarias!de!cdigo!as!como!aislar!completamente!la!capa!de!
presentacin!de!la!capa!de!persistencia.!En!este!captulo!vamos!a!aadir!flexibilidad!a!la!
capa! de! persistencia! construida.! Ahora! nuestra! capa! de! persistencia! soporta! nuevas!
implementaciones!a!travs!del!uso!del!patrn!AbstractFactory!que!define!un!conjunto!
de!familias,!pudiendo!aadir!nuevas!familias!mas!adelante!.!Por!ejemplo!puede!ser!que!
en!algn!momento!necesitemos!una!familia!de!XML!o!una!familia!JDBC!como!!muestra!
en!la!siguiente!figura.!

252
www.arquitecturajava.com!

Como! acabamos! de! comentar,! es! la! clase! AbstractFactory! la! que! se! encarga! de! la!
gestin!de!las!familias!y!la!responsable!de!crear!los!distintos!objetos!(ver!imagen).!

Ahora! bien! el! patrn! Abstract! Factory! aunque! aporta! ventajas,! tambin! tiene!
limitaciones.! Si! nos! apoyamos! en! l,! no! nos! ser! posible! disponer! de! una! capa! de!
persistencia!hbrida!en!la!que!una!parte!de!las!clases!DAO!sean!por!ejemplo!JDBC!y!otra!
JPA!(ver!imagen).!
253
Arquitectura*Java!

Puede!parecer!extrao!el!que!una!aplicacin!necesite!un!modelo!hbrido!pero!pueden!
existir! muchas! situaciones! en! las! cuales! esto! sea! til,! a! continuacin! se! enumeran!
varias.!

Aplicacin!de!legado:!Puede!ser!que!nuestra!aplicacin!tenga!alguna!parte!de!
legado!y!necesitemos!por!ejemplo!acceder!a!esa!parte!va!JDBC.!
!
Modulo! no! relacional:! Situacin! en! la! que! la! capa! de! persistencia! necesita!
puntualmente!acceder!a!una!informacin!que!no!est!almacenado!en!una!base!
de! datos! relacional,! por! ejemplo! ficheros! XML! y! necesitamos! que! parte! de! la!
implementacin!de!la!capa!de!persistencia!acceda!a!ficheros!xml.!
!
Objeto! Mock! :! Necesitamos! construir! una! clase! que! simule! una! funcionalidad!
concreta! de! la! capa! ! de! persistencia! ya! que! en! estos! momentos! no! ha! sido!
todava!construida!o!en!nuestro!entorno!de!desarrollo!no!tenemos!acceso!a!ella!
pero!queremos!poder!simularla.!
!
254
www.arquitecturajava.com!

Problemas! de! rendimiento:! Partes! de! la! aplicacin! tienen! problemas! con! la!
capa! de! persistencia! habitual! que! utilizamos! y! necesitan! usar! otro! tipo! de!
implementacin!que!d!mejor!rendimiento.!

Estas! son! algunas! de! las! situaciones! por! las! cules! soportar! un! modelo! hbrido! es!
interesante! pero! existen! muchas! ms.! El! objetivo! principal! de! este! captulo! ser! el!
permitir! variar! la! implementacin! de! parte! de! nuestra! capa! de! persistencia! sin! tener!
que!estar!ligados!al!uso!concreto!de!una!familia!A!o!familia!B!de!tal!forma!que!nuestra!
aplicacin! sea! ms! flexible.! Para! ello! introduciremos! ! el! framework! Spring! y! sus!
capacidades!de!inversin!de!control.!

Objetivos:

Introduccin!al!framework!Spring.!
Permitir! a! la! aplicacin! cambiar! las! implementaciones! ! de! clases! concretas! de!
forma! totalmente! transparente! al! desarrollador,! aportando! flexibilidad! a! la!
aplicacin!usando!Spring!framework!

Tareas:

1. Creacin!de!ejemplo!elemental!de!factoras!
2. Instalacin!de!Spring!Framework!
3. Configuracin!de!Spring!en!nuestra!aplicacin!
!
!

1. Creacin!de!ejemplo!de!factorias!

El! framework! Spring! es! un! framework! de! Inversin! de! Control! que! nos! permite!
gestionar! nuestras! necesidades! de! inversin! de! control! agrupada! y! sencillamente! sin!
tener! que! recurrir! al! uso! de! patrones! de! diseo! clsicos! (como! Factory! y! Abstract!
Factory).!Para!comprender!cmo!funciona!este!framework,!vamos!a!realizar!un!ejemplo!
sencillo!antes!de!retomar!nuestra!aplicacin!y!aplicar!las!ventajas!aportadas.!Para!ello!
construiremos!un!sencillo!interface!Mensaje!que!dispone!de!dos!implementaciones.!A!
continuacin!se!desglosan!los!conceptos!a!construir:!

Interface!Mensaje:!Interface!con!un!nico!mtodo!denominado!hola().!
Clase!MensajeHTML!:Clase!que!implementa!el!interface!e!imprime!por!pantalla!
un!mensaje!en!formato!HTML.!
Clase!MensajePlano:!Clase!que!implementa!el!interface!e!imprime!por!pantalla!
un!mensaje.!!
Clase! FactoriaMensajes:! Clase! que! se! encarga! de! aplicar! el! principio! de!
inversin!de!control.!
255
Arquitectura*Java!

!A!continuacin!se!muestra!un!diagrama!con!la!estructura!bsica.!

Clarificado!el!diagrama,!vemos!el!cdigo!fuente!de!cada!una!de!las!clases!e!interfaces:

Cdigo!16.1:!(Mensaje.java)!

public interface Mensaje {


public void hola();
}

Cdigo!16.2:!(MensajeHTML.java)!

public class MensajeHTML implements Mensaje {


@Override
public void hola() {
System.out.println("<html>hola</html>");
}
}

Cdigo!16.3:!(MensajePlano.java)!

public class MensajePlano implements Mensaje {


@Override
public void hola() {
System.out.println("hola");
}
}
256
www.arquitecturajava.com!

Ya! tenemos! el! cdigo! de! cada! una! de! nuestras! clases.! Ahora! vamos! a! construir! un!
sencillo!programa!que!haga!uso!de!la!implementacin!de!HTML!.El!cdigo!se!muestra!a!
continuacin.!

Cdigo!16.4:!(Principal.!java)!

package com.arquitecturajava;
public class Principal {
public static void main(String[] args) {

Mensaje mensaje= newMensajeHTML();


mensaje.hola();
}
}
!

Construido! el! cdigo,! podemos! ejecutar! el! programa! y! ver! qu! resultados! genera.!
Vase!una!imagen!una!vez!ejecutado!el!programa:!

Una! vez! que! hemos! construido! las! clases,! vamos! a! usar! el! principio! de! inversin! de!
control! y! construir! una! sencilla! factora! apoyada! en! un! fichero! ! de! propiedades! para!
crear!un!tipo!de!mensaje!u!otro!dependiendo!del!contenido!del!fichero!(ver!imagen).!

257
Arquitectura*Java!

Una! vez! que! tenemos! claro! el! diagrama,! vamos! a! ver! el! contenido! del! fichero! de!
propiedades!que!vamos!a!utilizar!as!como!el!cdigo!fuente!de!nuestra!factora.!

Cdigo!16.5:!(mensaje.properties)!

tipo=html

258
www.arquitecturajava.com!

Cdigo!16.5:!(MensajeFactory.java)!

packagecom.arquitecturajava;

importjava.io.FileInputStream;
import java.util.Properties;

public class MensajeFactory {

public static Mensaje getMensaje(){


Properties propiedades= new Properties();
Mensaje mensaje=null;
try {
propiedades.load(new FileInputStream("mensaje.properties"));
String tipo=propiedades.getProperty("tipo");
if (tipo.equals("html")) {
mensaje=new MensajeHTML();
}else {
mensaje= new MensajePlano();
}

} catch (Exception e) {
e.printStackTrace();
}
return mensaje;
}
}

Acabamos! de! aplicar! ! el! principio! de! inversin! de! control! ! a! travs! del! uso! ! de! una!
factora.! Ahora! podremos! construir! el! programa! principal! de! la! siguiente! forma! y! el!
resultado!ser!idntico!al!anterior:!

Cdigo!16.6:!(Principal.java)!

public static void main(String[] args) {

Mensaje mensaje= MensajeFactory.getMensaje();


mensaje.hola();
}

De! igual! manera! ! podremos! modificar! el! fichero! de! propiedades! que! acabamos! de!
construir! para! que! la! implementacin! y! el! funcionamiento! de! nuestro! programa!
cambie.!En!este!caso!cambiamos!en!el!fichero!el!tipo!(ver!cdigo).!

!!
259
Arquitectura*Java!

Cdigo!16.7:!(fichero)!

tipo=plano

El resultado ser el siguiente:

Una!vez!hemos!visto!cmo!utilizar!de!forma!sencilla!el!principio!de!inversin,!podremos!
darnos! cuenta! de! cmo! al! apoyarnos! en! un! fichero! de! propiedades,! conseguimos!
cambiar! de! una! implementacin! de! Mensaje! a! otra! sin! tocar! el! cdigo! fuente! de!
nuestro!programa!.De!esta!forma!cumplimos!adems!con!el!principio!OCP!(ver!imagen).!

260
www.arquitecturajava.com!

Es! momento! de! dar! por! finalizada! esta! revisin! del! principio! IOC! y! de! cmo! puede!
ligarse!al!principio!OCP!para!introducir!en!la!siguiente!tarea!el!framework!Spring!y!ver!
qu!ventajas!adicionales!aporta!a!nuestra!solucin!actual.!

2. Instalacin!de!Spring!

Una! vez! tenemos! el! ejemplo! ms! elemental! de! inversin! de! control! ! construido,! lo!
haremos! evolucionar! para! que! haga! uso! de! Spring! framework! para! lo! cul! el! primer!
paso!ser!obtener!el!framework!de!la!siguiente!url.!

http://www.springsource.com/download/community

Una!vez!obtenido!el!framework,!pasaremos!a!instalar!en!nuestros!ejemplos!los!ficheros!
jar! necesarios! para! realizar! las! operaciones! bsicas.! A! continuacin! se! muestra! una!
imagen!con!los!jars.!

Una! vez! aadida! la! carpeta! lib! y! los! jars! necesarios,! podemos! comenzar! a! usar! el!
framework!Spring.!Este!framework!trabaja!como!inversor!de!control!y!hace!las!tareas!
de! una! factora.! En! este! caso! se! trata! de! una! factora! capaz! de! crear! objetos!
apoyndose!en!un!fichero!de!configuracin!XML!(contextoAplicacion.xml)!(ver!imagen).

261
Arquitectura*Java!

Una!vez!que!tenemos!claro!que!Spring!funciona!como!si!de!una!factora!se!tratase!y!usa!
un! fichero! de! configuracin,! vamos! a! ver! una! imagen! que! muestra! el! proyecto! de!
Spring,!sus!libreras!y!la!ubicacin!del!fichero!de!configuracin.

Vamos! a! ver! cual! es! el! contenido! que! este! fichero! tendr! para! poder! realizar! una!
funcionalidad!similar!a!la!que!nosotros!realizbamos!con!nuestra!factora.!

262
www.arquitecturajava.com!

Cdigo!16.8:!(contextoAplicacion.xml)!

<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="mensajeHTML"class="com.arquitecturajava.MensajeHTML">
</bean>
</beans>

Se! puede! identificar! claramente! que! el! fichero! se! compone! de! una! etiqueta! <beans>!
principal! la! cual! contiene! un! grupo! de! etiquetas! <bean>! anidadas.! Estas! etiquetas!
<bean>!sern!las!encargadas!de!definir!los!distintos!objetos!a!instanciar!por!parte!del!
framework.!Para!ello!cada!objeto!usar!dos!atributos!!

id!:!Identifica!el!nombre!del!objeto!
class:!identifica!a!partir!de!qu!clase!se!debe!construir!el!objeto!

A! continuacin! se! muestra! el! bloque! de! cdigo! que! define! un! objeto! de! tipo!
MensajeHTML.!

Cdigo!16.9:!(contextoAplicacion.xml)!

<bean id="mensajeHTML" class="com.arquitecturajava.MensajeHTML">


</bean>

Una! vez! tenemos! claro! esto,! vamos! a! ver! cmo! modificar! nuestro! programa! original!
para!hacer!uso!de!Spring!framework!a!la!hora!de!instanciar!nuestros!objetos!y!no!tener!
que!construirnos!nosotros!nuestras!propias!factoras.!

Cdigo!16.10:!(Principal.java)!

public static void main(String[] args) {


ApplicationContextfactoria = new
FileSystemXmlApplicationContext("contextoAplicacion.xml");
Mensaje mimensaje= (Mensaje)factoria.getBean("mensajeHTML");
mimensaje.hola();
}
!

Visiblemente!el!cdigo!vara!un!poco!ya!que!hacemos!uso!no!ya!de!nuestra!factora!sino!
de!una!factora!propia!del!framework!Spring.!

263
Arquitectura*Java!

FileSystemXmlApplicationContext

la!cul!recibe!como!parmetro!el!fichero!de!configuracin!de!Spring!!

contextoAplicacion.xml

Si! ejecutamos! nuestro! programa,! el! resultado! es! idntico! al! programa! inicial! (ver!
imagen)!

La!ventaja!de!hacer!uso!de!Spring!es!que!permite!aadir!todas!las!clases!que!deseemos!
a!nivel!del!fichero!xml!(ver!cdigo).

Cdigo!16.11:!(aplicacionContexto.xml)!

<bean id="mensajeHTML" class="com.arquitecturajava.MensajeHTML" />


<bean id="mensajeBasico" class="com.arquitecturajava.MensajePlano" />

As! se! aade! una! mayor! flexibilidad! a! la! hora! de! crear! objetos! y! se! elimina! las!
limitaciones! habituales! que! tiene! una! factora! que! nicamente! construya! objetos! de!
una!jerarqua!de!clases!concreta.!!

264
www.arquitecturajava.com!

Por! ltimo,! vamos! a! ver! el! cdigo! fuente! de! la! clase! principal! al! trabajar! con! dos!
implementaciones!distintas!a!travs!del!uso!de!Spring.!

Cdigo!16.12:!(Principal.java)!

public static void main(String[] args) {

ApplicationContextfactoria = new
FileSystemXmlApplicationContext("contextoAplicacion.xml");
Mensaje hola= (Mensaje)factoria.getBean("mensajeHTML");
hola.hola();
Mensaje hola= (Mensaje)factoria.getBean("mensajePlano");
hola.hola();
}
!

Ahora! ! tenemos! claro! que! podemos! aadir! varias! clases! al! fichero! de! configuracin!
contextoAplicacion.xml! ! .Podemos! usar! el! framework! Spring! como! factora! principal! y!
se! encargar! de! crear! todos! los! objetos! que! le! solicitemos.! Adems! podremos! aadir!
nuevas! clases! a! instanciar! o! cambiar! una! implementacin! por! otra! sin! necesidad! de!
cambiar!nuestro!cdigo!fuente,!cumpliendo!con!el!principio!OCP!(ver!imagen).!

265
Arquitectura*Java!

3. Instalacin!de!Spring!en!nuestra!aplicacin.!

Visto!como!funcionan!de!una!manera!elemental!las!capacidades!de!inversin!de!control!
del!framework!Spring,!vamos!a!ver!cmo!podemos!aplicarlas!a!la!aplicacin!construida.!
Lo!primero!que!vamos!a!hacer!es!instalar!las!libreras!necesarias!del!framework!Spring!
en!nuestra!aplicacin!web!(ver!imagen).!

Una! vez! realizada! esta! operacin! y! aadidas! las! libreras,! hay! que! configurar! el!
framework! Spring! para! que! funcione! correctamente! en! una! aplicacin! web.! Para! ello!
modificaremos!el!fichero!web.xml!y!aadiremos!las!siguientes!etiquetas.!

!!

266
www.arquitecturajava.com!

Cdigo!16.13:!(web.xml)!

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:contextoAplicacion.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

El! parmetro! de! contexto! define! cul! va! a! ser! el! nombre! del! fichero! de! configuracin!
que! Spring! debe! cargar.! Por! otro! lado! el! listener! de! la! aplicacin! permite! que! el!
framework!Spring!se!cargue!y!lea!el!fichero!de!configuracin!antes!de!que!la!aplicacion!
web!entre!en!funcionamiento.!

Una!vez!configurado!el!framework,!podemos!definir!el!fichero!XML!con!las!clases!que!
queremos! sean! instanciadas! por! la! factoria! de! spring.! Para! comenzar! poco! a! poco!
nicamente!solicitaremos!al!framework!que!instancie!las!clases!DAO.!!A!continuacin!se!
muestra!el!codigo!del!fichero!contextoAplicacion.xml.!

Cdigo!16.14:!(contextoAplicacion.java)!

<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
</bean>

<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
</bean>
</beans>

Configurado! el! fichero! contextoAplicacion.xml! ,! es! necesario! usar! la! capa! de! servicio!
para! crear! los! distintos! elementos! de! la! capa! de! persistencia.! Ahora! bien,! en! lugar! de!
usar!factorias!y!abstract!factories,!en!este!caso!usaremos!el!framework!Spring!,como!se!
muestra!a!continuacin!en!el!siguiente!bloque!de!cdigo.!

267
Arquitectura*Java!

Cdigo!16.15:!(ServicioLibrosImpl.java)!

public class ServicioLibrosImpl implementsServicioLibros {

private LibroDAOlibroDAO=null;
private CategoriaDAOcategoriaDAO=null;

publicServicioLibrosImpl() {
ClassPathXmlApplicationContextfactoria =
new ClassPathXmlApplicationContext("contextoAplicacion.xml");
libroDAO= (LibroDAO)factoria.getBean("libroDAO");
categoriaDAO=(CategoriaDAO)factoria.getBean("categoriaDAO");
}

Esta! claro! que! se! utiliza! otra! factora! :ClassPathXmlApplicationContext,! factora! de!
Spring! que! busca! un! fichero! dentro! del! classpath! .As! hemos! usado! un! framework! de!
inversin!de!control!para!poder!cambiar!la!implementacin!de!la!capa!de!persistencia!
de!una!forma!flexible,!permitiendo!tanto!usar!JPA,!Hibernate,!JDBC!como!otras!.!Aadir!
nuevas! implementaciones! nicamente! implica! aadir! o! modificar! el! fichero! xml! de!
configuracin.!No!hay!que!tocar!para!nada!la!aplicacin!(ver!imagen).!

268
www.arquitecturajava.com!

Una! vez! que! hemos! realizado! los! primeros! cambios! a! nivel! de! Spring! framework,!
podremos! eliminar! todas! las! clases! de! factora! que! habamos! creado! para! la! capa! de!
persistencia!y!simplificar!el!modelo!de!nuestra!aplicacin!en!el!que!ya!no!necesitaremos!
el!grupo!de!factorias!(ver!imagen).!

Resumen!
En! este! captulo! hemos! visto! una! introduccin! al! framework! Spring! y! cmo! este!
framework!permite!eliminar!el!sistema!de!factoras!previamente!construido,!aadiendo!
mayor!flexibilidad!a!la!aplicacin!en!proceso!de!construccin,!utilizando!el!principio!de!
inversin!de!control.!

! !

269
Arquitectura*Java!

17.Inyeccion+de+Dependencia++y!Spring'
framework!
!
!

En! el! captulo! anterior! hemos! comenzado! a! usar! el! principio! de! inversin! de! control!
para! que! la! clase! ServicioLibrosImpl! se! encargue! de! crear! los! distintos! objetos! de! la!
capa!de!persistencia!a!travs!del!framework!Spring!(ver!imagen).

270
www.arquitecturajava.com!

En!este!captulo!vamos!a!avanzar!en!el!uso!del!principio!de!inversin!de!control!y!vamos!
a!utilizar!el!framework!Spring!para!que!se!encargue!de!inicializar!no!slo!las!clases!que!
pertenecen! a! la! capa! de! persistencia! sino! tambin! las! clases! de! servicio,! en! nuestro!
caso! ServicioLibrosImpl.! De! esta! forma! nuestras! acciones! delegarn! ahora! en! el!
framework!Spring!para!cargar!!!las!clases!de!servicio!(ver!imagen).!

Para!ello!!nuestro!primer!paso!ser!modificar!el!fichero!contextoAplicacion.xml!y!aadir!
nuestra!clase!de!servicios!(ver!cdigo).!

Cdigo!17.1:!(contextoAplicacion.xml)!

<bean id="servicioLibros
class="com.arquitecturajava.aplicacion.servicios.impl.ServicioLibrosImpl">
</bean>
!

Una!vez!realizada!esta!operacin,!necesitamos!!modificar!la!clase!!abstracta!Accin!de!
tal!forma!!que!el!resto!de!las!acciones!se!puedan!apoyar!en!Spring!al!solicitar!el!servicio!
de! libros.! Para! ello! crearemos! un! nuevo! mtodo! en! esta! clase! denominado!
getBean(String! nombreBean)! ,as! todas! las! dems! acciones! al! heredarlo! pueden!
delegar!en!l!para!construir!la!clase!de!servicios!necesarios!(ver!imagen).!

271
Arquitectura*Java!

Una!vez!entendido!este!concepto,!vemos!cmo!implementar!esta!funcionalidad!a!nivel!
de!la!clase!Accin.!Ahora!se!muestra!el!cdigo!de!nuestro!nuevo!mtodo.!

Cdigo!17.2:!(Accion.java)!

public Object getBean(String nombre) {


ClassPathXmlApplicationContextfactoria = new
ClassPathXmlApplicationContext("contextoAplicacion.xml");
return factoria.getBean(nombre);
}

Terminada!esta!operacin,!las!acciones!crearn!los!servicios!de!una!forma!muy!sencilla!
como!se!muestra!en!el!siguiente!cdigo!de!la!clase!MostrarLibrosAccion:!

272
www.arquitecturajava.com!

Cdigo!17.3:!(MostrarLibrosAccion.java)!

public class MostrarLibrosAccion extendsAccion {

@Override
public String ejecutar(HttpServletRequestrequest,
HttpServletResponse response) {

ServicioLibros servicio =
(ServicioLibros) getBean("servicioLibros");

List<Libro>listaDeLibros = servicio.buscarTodosLosLibros();
List<Categoria>listaDeCategorias =
servicio.buscarTodasLasCategorias();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";
}

Tras!modificar!las!acciones!para!que!deleguen!en!el!framework!Spring!al!crear!la!capa!
de! servicios,! no! olvidemos! que! tambin! hemos! usado! en! el! captulo! anterior! el!
framework!Spring!para!crear!objetos!de!la!capa!de!persistencia!necesarios!para!la!capa!
de!servicio,!como!muestra!el!siguiente!bloque!de!cdigo.!

Cdigo!17.4:!(ServicioLibrosImpl.java)!

public ServicioLibrosImpl() {

ClassPathXmlApplicationContextfactoria =
new ClassPathXmlApplicationContext("applicationContext.xml");
libroDAO= (LibroDAO)factoria.getBean("libroDAO");
categoriaDAO=(CategoriaDAO)factoria.getBean("categoriaDAO");
}

As! pues,! en! estos! momentos! hemos! usado! el! framework! Spring! en! dos! partes! de!
nuestra!aplicacin,!primero!a!nivel!de!las!acciones!y!segundo!a!nivel!de!los!servicios!(ver!
imagen).!

273
Arquitectura*Java!

Segn!vayamos!progresando!en!el!diseo!de!la!aplicacin!nos!daremos!cuenta!de!que!la!
responsabilidad!al!inicializar!el!framework!!se!encuentra!implementada!en!varias!clases!
y!por!lo!tanto!tenemos!un!problema!de!repeticin!de!cdigo!(ver!imagen).!

Visto!el!!problema,!es!momento!de!definir!los!objetivos!y!tareas!de!este!captulo:!nos!
centraremos!en!eliminar!las!repeticiones!de!cdigo!a!la!hora!de!inicializar!Spring!y!nos!
encargaremos!de!centralizar!la!responsabilidad!de!cmo!se!construyen!cada!uno!de!los!
distintos! objetos.! Para! ello! nos! apoyaremos! en! un! patrn! denominado! Inyeccin! de!
dependencia!(DI)!que!ser!abordado!ms!adelante.!!

Objetivos:

Eliminar!repeticiones!de!cdigo!!en!cuanto!a!la!inicializacin!de!Spring.!
Centralizar!la!responsabilidad!de!crear!los!distintos!objetos.!

274
www.arquitecturajava.com!

Tareas:

1. Introduccin!al!patrn!!de!Inyeccin!de!Dependencia!!
2. Spring!como!framework!de!Inyeccin!de!dependencia.!
3. Spring!y!factora!web.!
4. Spring!inyeccin!de!dependencia!y!Capa!DAO.!
!

1. Introduccin!al!!principio!de!Inyeccin!de!Dependencia!

En! esta! tarea! vamos! a! introducir! brevemente! el! patrn! de! Inyeccin! de! dependencia!
que!consiste!en!lo!siguiente:!

Inyeccin! de! Dependencia:! Las! dependencias! que! una! clase! tiene! no! deben! ser!
asignadas!por!ella!misma!sino!por!un!agente!externo.!

Quiz! la! definicin! no! sea! sencilla! en! un! primer! momento,! para! clarificarla! ! vamos!
aplicar!el!patrn!de!inyeccin!de!dependencia!a!las!clases!de!servicio!y!persistencia!que!
tenemos!construidas.!Antes!de!abordar!esta!tarea,!vamos!a!mostrar!cul!es!la!relacin!
existente! entre! estas! clases! y! cules! han! usado! Spring! para! inicializar! las! distintas!
dependencias!relativas!a!la!clase!ServiciosLibrosImpl.!

275
Arquitectura*Java!

Como!podemos!ver!en!el!diagrama,!la!clase!ServicioLibrosImpl!ha!hecho!uso!de!Spring!
para! inicializar! sus! dependencias.! Vamos! a! utilizar! el! principio! de! inyeccin! de!
dependencia!en!la!clase!ServicioLibroImpl!de!tal!forma!que,!a!partir!de!este!momento!
no! sea! ella! la! encargada! de! inicializar! sus! dependencias! sino! un! agente! externo.! Para!
ello!pasaremos!a!aadirle!los!siguientes!mtodos!a!su!implementacin!e!interface.!

setLibroDAO(LibroDAOlibroDAO)!:Asigna!un!objeto!de!tipo!LibroDAO!a!la!clase!
de!servicio!!
getLibroDAO()!:!Devuelve!un!objeto!de!tipo!LibroDAO!
setCategoriaDAO! (CategoriaDAOcategoriaDAO):! Asigna! un! objeto! de! tipo!
categoriaDAO!a!la!clase!de!servicio.!
getCategoriaDAO()!:Devuelve!un!objeto!de!tipo!CategoriaDAO!
!

Una! vez! claro! qu! mtodos! vamos! a! aadir,! vamos! a! ver! un! diagrama! que! muestra!
como!quedan!el!interface!y!la!clase.!

276
www.arquitecturajava.com!

Visto!el!diagrama,!vamos!a!ver!!el!cdigo!fuente!de!ambos!

public interface ServicioLibros {


public LibroDAO getLibroDAO() {
public void setLibroDAO(LibroDAO libroDAO) {
public CategoriaDAO getCategoriaDAO()
public void setCategoriaDAO(CategoriaDAO categoriaDAO)
//resto de mtodos
}
!

277
Arquitectura*Java!

Cdigo!17.5:!(ServicioLibrosImpl.java)!

public class ServicioLibrosImpl implements ServicioLibros {

private LibroDAOlibroDAO=null;
private CategoriaDAOcategoriaDAO=null;
public LibroDAO getLibroDAO() {
return libroDAO;
}

public void setLibroDAO(LibroDAO libroDAO) {


this.libroDAO = libroDAO;
}

public CategoriaDAO getCategoriaDAO() {


return categoriaDAO;
}

public void setCategoriaDAO(CategoriaDAO categoriaDAO) {


this.categoriaDAO = categoriaDAO;
}
//resto de codigo
!

Una!vez!realizada!esta!operacin,!la!clase!ServicioLibroJPAImpl!ya!no!necesita!que!se!le!
asignen! las! dependencias! en! su! constructor! ServicioLibroJPAImpl()! .Sino! que! estas!
depencencias! podrn! ser! asignadas! a! travs! de! los! nuevos! mtodos! set/get! .Estos!
mtodos!sern!invocados!en!nuestro!caso!por!una!clase!de!tipo!Accion!(ver!cdigo).!

Cdigo!17.6:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequestrequest,


HttpServletResponse response) {
ServicioLibro servicio= getBean(ServicioLibro);
CategoriaDAOcategoriaDAO= getBean(categoriaDAO);
LibroDAOlibroDAO= getBean(libroDAO);
servicio.setLibroDAO(libroDAO);
servicio.setCategoriaDAO(categoriaDAO)
}

De!esta!manera!habremos!utilizado!el!patrn!de!Inyeccin!de!Dependencia!para!asignar!
las!dependencias!a!nuestra!clase!de!servicio.!Ya!no!es!necesario!usar!Spring!a!nivel!de!
capa!de!servicios!en!el!constructor!del!servicio!sino!que!son!las!propias!acciones!las!que!
asignan!las!dependencias!necesarias!!(ver!imagen).!

278
www.arquitecturajava.com!

De! esta! manera! habremos! dejado! de! inicializar! varias! veces! el! framework! Spring! y!
cumpliremos!con!el!principio!DRY!como!se!ve!en!el!diagrama.!

279
Arquitectura*Java!

2. Spring!e!inyeccin!de!dependencia.!

Hemos! visto! cmo! el! principio! de! inyeccin! de! dependencia! permite! centralizar! la!
creacin! de! los! distintos! objetos! y! agrupar! la! responsabilidad! de! crearlos! ! en! las!
acciones.! Ahora! bien,! aunque! hemos! usado! el! principio! DRY! y! eliminado! el! cdigo! de!
inicializacin!de!las!clases!de!Servicio!(ver!cdigo).!

Cdigo!17.7:!(ServicioLibrosImpl.java)!

public ServicioLibrosImpl() {
//ya no existe codigo de Spring
}
!

Aun!as!todava!nos!queda!un!problema!!por!resolver!:todas!las!acciones!comparten!el!
uso!de!la!factora!de!Spring!y!la!inyeccin!de!dependencias!entre!la!clase!de!servicios!y!
las!clases!DAO!como!muestran!los!siguientes!bloques!de!cdigo!que!son!prcticamente!
idnticos..!

Cdigo!17.8:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequestrequest,


HttpServletResponse response) {
ServicioLibro servicio=(ServicioLibro) getBean(ServicioLibro);
CategoriaDAOcategoriaDAO= (CategoriaDAO) getBean(categoriaDAO);
LibroDAOlibroDAO= (LibroDAO)getBean(libroDAO);
servicio.setLibroDAO(libroDAO);
servicio.setCategoriaDAO(categoriaDAO)
//resto de codigo
}
!

Cdigo!17.9:!(FiltroLibrosPorCategoriaAccion.java)!

publicString ejecutar(HttpServletRequestrequest,
HttpServletResponse response) {
ServicioLibro servicio=(ServicioLibro) getBean(ServicioLibro);
CategoriaDAOcategoriaDAO= (CategoriaDAO) getBean(categoriaDAO);
LibroDAOlibroDAO= (LibroDAO)getBean(libroDAO);
servicio.setLibroDAO(libroDAO);
servicio.setCategoriaDAO(categoriaDAO)
}

No! es! difcil! darse! cuenta! de! que! tenemos! cdigo! repetido! en! las! dos! acciones! :!
volvemos!a!tener!un!problema!respecto!al!principio!DRY!(ver!imagen).!
280
www.arquitecturajava.com!

Para!solventar!este!problema!vamos!a!usar!Spring!!como!framework!de!Inyeccin!de!
dependencia.! Los! frameworks! de! inyeccin! de! dependencia! permiten! asignar! las!
dependencias! fuera! de! nuestro! propio! cdigo! fuente! apoyndonos! normalmente! en!
ficheros!de!configuracin!xml.!Este!es!el!caso!de!Spring,!!que!a!travs!de!su!fichero!xml!
es! capaz! de! inyectar! las! distintas! dependencias! a! los! distintos! objetos! que!
construyamos!.Por!lo!tanto!ahora!todo!el!cdigo!de!inyeccin!de!dependencia!en!cada!
una!de!nuestras!clases!de!accin!quedar!relegado!a!un!fichero!xml!(ver!imagen).!

281
Arquitectura*Java!

Vamos! a! mostrar! a! continuacin! el! cdigo! fuente! del! fichero! contextoaplicacin.xml!


para! ver! qu! sintaxis! usa! el! framework! spring! a! la! hora! de! inyectar! las! distintas!
dependencias!y!as!clarificar!los!conceptos!explicados.!

Cdigo!17.10:!(contextoAplicacion.xml)!

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="servicioLibros"
class="com.arquitecturajava.aplicacion.servicios.impl.ServicioLibrosImpl">
<propertyname="libroDAO" ref="libroDAO"></property>
<propertyname="categoriaDAO" ref="categoriaDAO"></property>
</bean>
<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
</bean>
<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
</bean>
</beans>

Como! podemos! ver,! utilizamos! la! etiqueta! <property>! para! usar! el! principio! de!
inyeccin! de! dependencia! e! inyectar! desde! el! fichero! XML! las! dependencias! que!
nuestro!servicio!necesita.!De!esta!forma!nuestro!cdigo!fuente!a!nivel!de!cada!una!de!
las!acciones!quedar!simplificado!pues!nicamente!necesitaremos!obtener!el!servicio!a!
travs!del!mtodo!getBean!y!Spring!a!travs!de!su!fichero!xml!se!encargar!de!inyectar!
las! distintas! dependencias,! como! se! muestra! en! el! siguiente! bloque! de! cdigo! que!
corresponde!a!la!clase!!MostrarLibroAccion.!

Cdigo!17.11:!(MostrarLibrosAccion.java)!

public String ejecutar(HttpServletRequestrequest,


HttpServletResponse response) {
ServicioLibros servicio = (ServicioLibros)
getBean("servicioLibros");
List<Libro>listaDeLibros = servicio.buscarTodosLosLibros();
List<Categoria>listaDeCategorias = servicio.buscarTodasLasCategorias();
request.setAttribute("listaDeLibros", listaDeLibros);
request.setAttribute("listaDeCategorias", listaDeCategorias);
return "MostrarLibros.jsp";
}

282
www.arquitecturajava.com!

3. Spring!y!factora!para!aplicaciones!web!

Hasta!este!momento!hemos!estado!utilizando!la!factora!clsica!de!Spring!(ver!cdigo).!

Cdigo!17.12:!(Accion.java)!

public Object getBean(String nombre) {


ClassPathXmlApplicationContextfactoria = new
ClassPathXmlApplicationContext("applicationContext.xml");
returnfactoria.getBean(nombre);
}

Es! momento! de! configurar! Spring! para! que! use! una! factora! especfica! a! nivel! de!
aplicacin! web.! Por! eso! es! necesario! modificar! el! mtodo! getBean! de! nuestra! clase!
Accion!y!substituir!la!factora!habitual!por!el!siguiente!bloque!de!cdigo.!

Cdigo!17.13:!(MostrarLibrosAccion.java)!

public Object getBean(String nombre,HttpServletRequest request) {

WebApplicationContextfactoria =WebApplicationContextUtils.
getRequiredWebApplicationContext(request.getSession().
getServletContext());
return factoria.getBean(nombre);

De!esta!forma!nos!aseguraremos!de!que!Spring!slo!carga!el!fichero!de!configuracin!
una! nica! vez! al! arrancar! la! aplicacin! web.! Realizado! este! cambio,! vamos! a! seguir!
aplicando! el! principio! de! inyeccin! de! dependencia! ! ! a! otras! clases! de! nuestra!
aplicacin.!

4. Spring!inyeccin!de!dependencia!y!Capas!DAO!

Hemos!trabajado!con!el!framework!Spring!como!inyector!de!dependencia!a!la!hora!de!
crear!los!servicios!y!las!capas!DAO.!Es!momento!de!aplicar!el!principio!de!inyeccin!de!
dependencia! a! las! propias! clases! DAO! que! tenemos! construidas.! Si! revisamos! los!
distintos!mtodos!de!la!clase!GenericDAOJPAImpl!como!por!ejemplo!el!siguiente.!

!
283
Arquitectura*Java!

Cdigo!17.14:!(GenericDAOJPAImpl.java)!

public void borrar(T objeto) {

EntityManager manager = getEntityManagerFactory().createEntityManager();


EntityTransactiontx = null;
try {
tx = manager.getTransaction();
tx.begin();
manager.remove(manager.merge(objeto));
tx.commit();
} catch (PersistenceException e) {
tx.rollback();
throw e;
} finally {
manager.close();
}
}

Nos!daremos!cuenta!de!que!no!solo!este!mtodo!sino!todos!los!dems!dependen!de!un!
objeto! EntityManagerFactory.! Asi! pues! vamos! a! refactorizar! el! cdigo! de! la! clase!
GenericDAOJPAImpl!asi!como!el!de!su!interface!para!inyectar!a!travs!de!Spring!dicho!
objeto!(ver!imagen)!.!

Una! vez! que! tenemos! claro! qu! operacin! vamos! a! realizar,! es! momento! de! ver! el!
cdigo!fuente!de!nuestra!nueva!clase.!

284
www.arquitecturajava.com!

Cdigo!17.15:!(GenericDAOJPAImpl.java)!

public abstract class GenericDAOJPAImpl<T, Id extends Serializable > implements


GenericDAO<T, Id> {
....
public EntityManagerFactory getEntityManagerFactory() {
return entityManagerFactory;
}
public void setEntityManagerFactory(EntityManagerFactory
entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}

Una!vez!definidos!los!nuevos!mtodos!que!nos!permitirn!inyectar!la!dependencia!de!
EntityManagerFactory!a!nuestras!clases!DAO,!es!momento!de!ver!qu!nuevos!bean!han!
de!ser!aadidos!a!nivel!de!fichero!xml!.A!continuacin!se!enumeran:!

DriverManagerDataSource:Bean! encargado! de! crear! un! pool! de! conexiones!


contra! la! base! de! datos! que! seleccionemos! pasando! usuario,! password! ,! url,!
driver.!
EntityManagerFactory:! Hace! uso! del! DataSource! creado! y! asigna! el! tipo! de!
persistencia!y!algunos!parmetros!adicionales,!como!es!el!dialecto!de!JPA!que!
se!utilizar!.!

A!continuacin!se!muestra!la!nueva!versin!del!fichero.!

Cdigo!17.16:!(contextoAplicacion.java)!

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="fuenteDeDatos"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName" value="com.mysql.jdbc.Driver" />
<propertyname="url" value="jdbc:mysql://localhost/arquitecturaJavaORM"
/>
<propertyname="username" value="root" />
<propertyname="password" value="java" />
</bean>

285
Arquitectura*Java!

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<propertyname="persistenceUnitName" value="arquitecturaJava" />


<propertyname="dataSource" ref="fuenteDeDatos" />
<propertyname="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
>
<propertyname="databasePlatform"
value="org.hibernate.dialect.MySQL5Dialect" />
<propertyname="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="servicioLibros"
class="com.arquitecturajava.aplicacion.servicios.impl.ServicioLibrosImpl">
<propertyname="libroDAO" ref="libroDAO"></property>
<propertyname="categoriaDAO" ref="categoriaDAO"></property>
</bean>
<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
<propertyname="entityManagerFactory"
ref="entityManagerFactory"></property>
</bean>
<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
<propertyname="entityManagerFactory"
ref="entityManagerFactory">
</property>
</bean>
</beans>
!

Es! evidente! que! ahora! tambin! las! capas! DAO! se! apoyan! en! Spring! para! inyectar! la!
dependencia! que! necesitan! de! EntityManagerFactory.! Esta! dependencia!
(EntityManagerFactory)! necesita! a! su! vez! la! inyeccin! de! varias! propiedades! y! de! una!
fuente!de!datos!(pool!de!conexiones!a!base!de!datos).!Es!lo!que!hemos!configurado!en!
el!fichero.!Veamos!como!estos!cambios!afectan!a!nuestros!mtodos:!

!
286
www.arquitecturajava.com!

Cdigo!17.16:!(GenericDAOJPAImpl.java)!

public void salvar(T objeto) {


EntityManager manager =
getEntityManagerFactory().createEntityManager();

EntityTransaction tx = null;
try {
tx = manager.getTransaction();
tx.begin();
manager.merge(objeto);
tx.commit();

} catch (PersistenceException e) {
tx.rollback();
throw e;
} finally {
manager.close();
}
}

Resumen!
En!este!captulo!nos!hemos!centrado!en!explicar!el!patrn!de!Inyeccin!de!dependencia!
y! cmo! se! configura! a! travs! del! framework! Spring! y! nos! hemos! apoyado! en! l! para!
redefinir!la!configuracin!de!las!clases!de!servicio!y!capas!DAO,!simplificando!el!cdigo!
de!nuestras!clases!y!externalizando!la!configuracin!en!gran!medida.!

287
Arquitectura*Java!

18.El#principio#DRY#y#Spring#Templates!

En!el!captulo!anterior!hemos!visto!cmo!usar!!el!principio!de!inyeccin!de!dependencia!
que!nos!permite!centralizar!la!responsabilidad!de!crear!objetos!en!el!framework!Spring!
y! su! fichero! de! configuracin.! Este! captulo! volver! a! centrarse! en! la! evolucin! de! la!
capa!de!persistencia.!Para!ello!vamos!a!revisar!dos!mtodos!de!la!capa!de!persistencia!.!
En! concreto! dos! que! pertenecen! a! la! clase! GenericDAOJPAImpl:! salvar! y! borrar.! A!
continuacin!mostramos!el!cdigo!de!los!mismos:!

Cdigo!18.1:!(GenericDAOJPAImpl.java)!

public void salvar(T objeto) {


EntityManager manager =
getEntityManagerFactory().createEntityManager();

EntityTransaction tx = null;
try {
tx = manager.getTransaction();
tx.begin();
manager.merge(objeto);
tx.commit();

} catch (PersistenceException e) {
tx.rollback();
throw e;
} finally {
manager.close();
}
}
!

288
www.arquitecturajava.com!

Cdigo!18.2:!(GenericDAOJPAImpl.java)!

public void borrar(T objeto) {


EntityManager manager = getEntityManagerFactory().createEntityManager();
EntityTransaction tx = null;
try {
tx = manager.getTransaction();
tx.begin();
manager.remove(manager.merge(objeto));
tx.commit();
} catch (PersistenceException e) {
tx.rollback();
throw e;
} finally {
manager.close();
}
}

Como!podemos!ver,!el!cdigo!de!la!capa!de!persistencia!de!ambos!mtodos,!aunque!no!
es!idntico!s!que!se!trata!de!cdigo!muy!similar!(hay!bloques!idnticos).!Por!lo!tanto,!
nos! encontramos! otra! vez! en! una! situacin! de! violacin! del! principio! DRY,! ya! que!
tenemos!grandes!bloques!de!cdigo!repetidos!en!mtodos!distintos!(ver!imagen).!

Una! vez! que! tenemos! clara! la! repeticin! de! cdigo,! podemos! identificar! que! ! ambos!
mtodos!comparten!los!mismos!pasos!que!a!continuacin!se!enumeran.!

289
Arquitectura*Java!

Obtener!EntityManager!
Abrir!nueva!Transaccion!
Ejecutar/Abortar!Transaccion!
Cerrar!Recursos!

El!objetivo!principal!de!este!captulo!ser!eliminar!dichas!repeticiones!de!cdigo!de!tal!
forma! que! las! clases! de! persistencia! queden! mucho! ms! sencillas.! Para! ello!
introduciremos!un!nuevo!patrn:!el!patrn!Template!o!plantilla.!!

Objetivos:!!

Eliminar!repeticiones!de!cdigo!en!la!capa!DAO!

Tareas!

1. Introducir!el!patrn!de!diseo!Template!
2. Spring!y!el!patrn!Template!
1. Spring!Plantillas!y!JPADAOSupport!

1. El!patrn!Template!

El! patrn! Template! o! plantilla! es! un! patrn! de! diseo! que! se! encarga! de! definir! una!
serie! de! mtodos! a! nivel! de! clase! que! funcionen! en! forma! de! plantilla! .! As! que!
clarificaremos! el! funcionamiento! de! ! este! patrn! a! travs! de! un! ejemplo,! para! ello!
vamos!a!crear!la!clase!Documento!!y!dos!clases!hijas:!Documento!Sencillo!y!Documento!
Oficial.! La! clase! documento! nos! aportar! el! mtodo! imprimir! que! se! encarga! de!
imprimir! por! pantalla! el! texto! del! documento! .En! la! siguiente! imagen! se! muestra! la!
relacin!de!clases!y!mtodos!soportados.!

290
www.arquitecturajava.com!

Vamos!a!ver!a!continuacin!el!cdigo!fuente!de!cada!una!de!ellas!y!cmo!funciona!el!
programa!cuando!imprime!un!documento.!

Cdigo!18.3:!(Documento.java)!

package com.arquitecturajava;

public abstract class Documento {

public abstract void imprimir(String mensaje);


}

Cdigo!18.4:!(DocumentoOficial.java)!

package com.arquitecturajava;

public class DocumentoOficial extends Documento{

public void imprimir(String mensaje) {


System.out.println("<oficial>cabecera documento oficial<oficial>");
System.out.println("<oficial>"+mensaje+"</oficial>");
System.out.println("<oficial>pie documento oficial</oficial>");
}

}
!

Cdigo!18.5:!(Documento.java)!

package com.arquitecturajava;
public class DocumentoPlano extends Documento {
public void imprimir(String mensaje) {
System.out.println("cabecera documento sencillo");
System.out.println(mensaje);
System.out.println("pie documento sencillo");
}
}

Tras! construir! el! cdigo! de! cada! una! de! nuestras! claves,! vamos! a! ver! cmo! queda! el!
cdigo!del!programa!main!o!principal!que!se!encarga!de!imprimir!ambos!documentos!
por!pantalla.!

291
Arquitectura*Java!

Cdigo!18.6:!(Principal.java)!

package com.arquitecturajava;
public class Principal {
public static void main(String[] args) {
Documento d= new DocumentoOficial();
d.imprimir("texto documento oficial");
d= new DocumentoPlano();
d.imprimir("texto documento plano");
}
}

El!resultado!de!imprimir!estos!documentos!ser!el!siguiente:!

Como! podemos! ver! todo! se! imprime! correctamente! y! parece! que! el! programa!
construido! no! tiene! fisuras.! Ahora! bien,! imaginmonos! que! tenemos! otro! tipo! de!
documento! prcticamente! idntico! al! oficial! pero! que! al! ser! a! nivel! del! estado,! la!
cabecera!cambia!de!forma!puntual!y!tiene!el!siguiente!texto.!

Cdigo!18.7:!(Principal.java)!

<oficial> cabecera documento ESTATAL</oficial>


!

292
www.arquitecturajava.com!

Cmo! podemos! abordar! este! cambio! de! funcionalidad! con! el! cdigo! actual?! En! este!
caso!es!sencillo:!simplemente!debemos!crear!una!nueva!clase!que!extienda!de!la!clase!
documento!y!se!denomine!DocumentoEstatal.!Vase!una!imagen!aclaratoria:!

A!continuacin!se!muestra!el!cdigo!fuente!de!la!nueva!clase!que!define!el!documento!
estatal!

Cdigo!18.8:!(DocumentoEstatal.java)!

package com.arquitecturajava;
public class DocumentoEstatal extends Documento{
public void imprimir(String mensaje) {
System.out.println("<oficial>cabecera documento ESTATAL<oficial>");
System.out.println("<oficial>"+mensaje+"</oficial>");
System.out.println("<oficial>pie documento oficial</oficial>");
}
}

A! travs! de! la! herencia! hemos! solventado! en! principio! el! problema! del! nuevo! tipo! de!
documento! .Ahora! bien,! si! nos! fijamos! ms,! percibiremos! un! problema! de! cdigo! a!
nivel! del! principio! DRY,! ya! que! la! clase! DocumentoOficial! y! DocumentoEstatal!
comparten!cdigo!al!95%(ver!imagen).!

293
Arquitectura*Java!

Una!vez!tenemos!claro!cul!es!nuestro!problema,!vamos!a!refactorizar!nuestro!cdigo!
usando!el!patrn!Template!o!plantilla.!ste!se!encarga!de!dividir!la!funcionalidad!de!un!
mtodo! en! un! conjunto! de! mtodos! que! implementan! la! misma! funcionalidad! y! que!
forman! una! estructura! de! plantilla,! ya! que! cada! uno! de! estos! mtodos! puede! ser!
sobrescrito!por!las!clases!hijas!dependiendo!de!nuestras!necesidades.!Vamos!a!ver!una!
imagen!aclaratoria!de!la!estructura!de!este!patrn:!

294
www.arquitecturajava.com!

Una!vez!realizada!esta!operacin,!!podremos!crear!nuevas!clases!que!se!encarguen!de!
sobreescribir!aquellas!partes!que!nos!interesen.!Vamos!a!ver!a!continuacin!el!cdigo!
de!este!nuevo!diagrama!de!clases:!

!
295
Arquitectura*Java!

Cdigo!18.9:!(DocumentoEstatal.java)!

package com.arquitecturajava.plantillas;
public abstract class Documento {
public void imprimir(String mensaje) {
imprimirCabecera();
imprimirMensaje(mensaje);
imprimirPie();
}
protected abstract void imprimirCabecera();
protected abstract void imprimirMensaje(String mensaje);
protected abstract void imprimirPie();
}
!

Cdigo!18.10:!(DocumentoOficial.java)!

package com.arquitecturajava.plantillas;

public class DocumentoOficial extends Documento{


@Override
public void imprimirCabecera() {
System.out.println("<oficial>cabecera documento oficial <oficial>");
}
@Override
public void imprimirMensaje(String mensaje) {
System.out.println("<oficial>"+mensaje+"</oficial>");
}
@Override
public void imprimirPie() {
System.out.println("<oficial>pie documento sencillo</oficial>");
}
}
!

Visiblemente! el! cdigo! es! bastante! distinto,! pero! si! ejecutamos! otra! vez! nuestro!
programa,! el! resultado! ser! idntico.! Ahora! bien,! cuando! deseemos! construir! la! clase!
DocumentoEstatal!,podremos!hacer!uso!del!patrn!plantilla!y!nicamente!sobreescribir!
la!parte!que!realmente!cambia.!

296
www.arquitecturajava.com!

Cdigo!18.11:!(DocumentoEstatal.java)!

package com.arquitecturajava.plantillas;
public class DocumentoEstatal extends DocumentoOficial{
public void imprimirCabecera() {
System.out.println("<oficial>cabecera documento ESTATAL<oficial>");
}
}
!

!Para! construir! el! documento! estatal! nicamente! hemos! tenido! que! sobrescribir! un!
mtodo!y!hemos!podido!eliminar!las!repeticiones!de!cdigo!(ver!imagen).!

A! continuacin! vamos! a! usar! el! patrn! Template! junto! al! framework! Spring! para!
eliminar!repeticiones!en!la!capa!de!persistencia.!

2. Spring!y!plantillas.!

Si!revisamos!cualquiera!de!los!mtodos!que!en!estos!momentos!tenemos!en!la!capa!de!
persistencia,! nos! daremos! cuenta! de! que! se! comportan! de! una! forma! muy! similar! al!
patrn! Template! que! acabamos! de! comentar,! ! ya! que! cada! mtodo! de! persistencia!
puede!dividirse!en!varias!operaciones!(ver!imagen).!

297
Arquitectura*Java!

Prcticamente! toda! la! funcionalidad! que! construimos! en! los! distintos! mtodos! de!
persistencia!es!idntica,!salvo!la!operacin!concreta!que!el!EntityManager!ejecuta.!As!
pues! toda! esta! funcionalidad! puede! ser! rediseada! para! que! se! apoye! en! el! patrn!
Template.!Para!ello!el!framework!Spring!nos!provee!de!una!clase!que!implementa!toda!
la!funcionalidad!de!Manejo!de!Excepciones,!Gestin!de!Entity!Manager!y!Transacciones.!
A!continuacin!se!muestra!un!diagrama!con!la!clase.!

298
www.arquitecturajava.com!

Una!vez!que!sabemos!que!el!framework!Spring!nos!puede!ayudar!a!gestionar!la!capa!de!
persistencia! a! travs! de! una! clase! plantilla,! vamos! a! apoyarnos! en! esta! clase! para!
refactorizar! el! cdigo! de! las! clases! DAO.! Para! ello! refactorizaremos! nuestra! clase!
GenericDAOJPAImpl!para!que!delegue!en!la!clase!JPATemplate!del!framework!Spring!al!
realizar!todas!las!operaciones!de!persistencia.!

Vamos! a! ver! a! continuacin! ! cmo! queda! refactorizado! el! cdigo! de! nuestra! clase! y!
cmo!se!apoya!en!la!plantilla.!

299
Arquitectura*Java!

Cdigo!18.12:!(GenericDAOJPAImpl.java)!

package com.arquitecturajava.aplicacion.dao.jpa;
//omitimos imports
public abstract class GenericDAOJPAImpl<T, Id extends Serializable>implements
GenericDAO<T, Id> {

private Class<T> claseDePersistencia;


private JpaTemplate plantillaJPA;

public JpaTemplate getPlantillaJPA() {


return plantillaJPA;
}
public void setPlantillaJPA(JpaTemplate plantillaJPA) {
this.plantillaJPA = plantillaJPA;
}
@SuppressWarnings("unchecked")
public GenericDAOJPAImpl() {

this.claseDePersistencia = (Class<T>) ((ParameterizedType)getClass()


.getGenericSuperclass()).getActualTypeArguments()[0];
}
@Override
public T buscarPorClave(Id id) {
return plantillaJPA.find(claseDePersistencia, id);
}
@SuppressWarnings("unchecked")
public List<T> buscarTodos() {
return plantillaJPA.find("select o from "
+ claseDePersistencia.getSimpleName() + " o");
}
publicvoid borrar(T objeto) {
plantillaJPA.remove(plantillaJPA.merge(objeto));
}
publicvoid salvar(T objeto) {
plantillaJPA.merge(objeto);
}
publicvoid insertar(T objeto) {
plantillaJPA.persist(objeto);
}
}
!

Como! podemos! ver! el! framework! Spring! nos! aporta! una! clase! JPATemplate! que! ya!
implementa!toda!la!funcionalidad!necesaria!de!JPA!!y!que!es!inyectada!(ver!cdigo).!

300
www.arquitecturajava.com!

Cdigo!18.13:!(GenericDAOJPAImpl.java)!

private JpaTemplate plantillaJPA;


public JpaTemplate getPlantillaJPA() {
return plantillaJPA;
}
public void setPlantillaJPA(JpaTemplate plantillaJPA) {
this.plantillaJPA = plantillaJPA;}
!

Al!realizar!esta!operacin!todos!los!mtodos!de!la!clase!GenericDAOJPAImpl!quedarn!
claramente! simplificados.! Es! evidente! que! la! clase! JPATemplate! acta! como! una!
plantilla! y! nicamente! necesitamos! ejecutar! un! mtodo! concreto! ya! que! el! resto! de!
funcionalidad!viene!implementada!por!defecto.!

Cdigo!18.14:!(GenericDAOJPAImpl.java)!

public void borrar(T objeto) {


plantillaJPA.remove(plantillaJPA.merge(objeto));
}
!

La! siguiente! imagen! clarifica! cmo! funciona! la! clase! JPATemplate! en! cuanto! a! los!
mtodos! que! maneja! y! qu! partes! de! la! funcionalidad! vienen! implementadas! ya! por!
defecto,!de!tal!forma!que!no!debemos!preocuparnos!por!ello.!

!
301
Arquitectura*Java!

Una! vez! realizada! esta! operacin,! ! deberemos! usar! Spring! como! Inyector! de!
dependencia!y!configurar!la!plantilla!de!JPA!a!nivel!del!fichero!XML!!al!ser!la!plantilla!la!
encargada!de!la!gestin!de!la!capa!de!persistencia!.Ser!esta!clase!a!la!que!inyectemos!
el!entityManagerFactory!(ver!imagen).!

Cdigo!18.15:!(contextoAplicacion.xml)!

<bean id="plantillaJPA" class="org.springframework.orm.jpa.JpaTemplate">


<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="servicioLibros"
class="com.arquitecturajava.aplicacion.servicios.impl.ServicioLibrosImpl">
<property name="libroDAO" ref="libroDAO"></property>
<property name="categoriaDAO" ref="categoriaDAO"></property>
</bean>
<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
<property name="plantillaJPA" ref="plantillaJPA" />
</bean>
<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
<property name="plantillaJPA" ref="plantillaJPA" />
</bean>
!

Ejecutada!esta!operacin,!la!aplicacin!seguir!funcionando!de!la!misma!forma!con!la!
ventaja! de! haber! simplificado! sobremanera! el! cdigo! que! exista! en! nuestras! clases!
DAO,!cumpliendo!con!el!principio!DRY.!

3. Spring!Herencia!Plantillas!y!JDADAOSupport!

Otra!opcin!ms!practica!es!usar!una!clase!que!ya!aporte!la!plantilla!que!necesitamos!y!
que!nuestra!clase!genrica!extienda!de!ella.!El!Framework!Spring!nos!aporta!esta!clase!
a!nivel!de!JPA!y!se!denomina!JPADAOSupport!(ver!imagen).!

302
www.arquitecturajava.com!

Una! vez! que! esta! clase! hace! uso! de! JPATemplate,! podemos! hacer! que! nuestra! clase!
genrica! extienda! de! ella! y! as! todas! nuestras! clases! DAO! implementarn! la!
funcionalidad!(ver!imagen).!

A!continuacin!se!muestra!el!cdigo!con!la!nueva!versin!de!la!clase:!

Cdigo!18.16:!(GenericDAOJPAImpl.java)!

package com.arquitecturajava.aplicacion.dao.jpa;
//omitimos imports
public abstract class GenericDAOJPAImpl<T, Id extends Serializable>extends
JpaDaoSupport implements
GenericDAO<T, Id> {

private Class<T> claseDePersistencia;


@SuppressWarnings("unchecked")
public GenericDAOJPAImpl() {

this.claseDePersistencia = (Class<T>) ((ParameterizedType) getClass()


.getGenericSuperclass()).getActualTypeArguments()[0];
}
@Override
public T buscarPorClave(Id id) {
return getJpaTemplate().find(claseDePersistencia, id);
}
// resto de mtodos de persistencia no cambian
!

303
Arquitectura*Java!

Como!podemos!ver!la!clase!ha!quedado!muy!simplificada!y!la!capa!de!persistencia!muy!
sencilla,!pero!debemos!modificar!de!nuevo!!nuestro!fichero!de!configuracin!de!Spring!
ya!que!nuestras!clases!ahora!se!apoyaran!en!el!mtodo!setEntityManagerFactory!que!
implementa!la!clase!JPADAOSupport!(ver!cdigo).!

Cdigo!18.17:!(contextoAplicacion.xml)!

<bean id="servicioLibros"
class="com.arquitecturajava.aplicacion.servicios.impl.ServicioLibrosImpl">
<property name="libroDAO" ref="libroDAO"></property>
<property name="categoriaDAO" ref="categoriaDAO"></property>
</bean>
<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

Resumen!
Hemos!refactorizado!nuestra!capa!DAO!a!travs!del!uso!del!patrn!plantilla!(template)!
y! hemos! eliminado! mucho! cdigo! redundante.! En! estos! momentos! la! capa! de!
persistencia! ha! quedado! muy! simplificada,! el! principio! DRY! ha! vuelto! a! ser! una! de! las!
piezas!claves!para!poder!seguir!avanzando!con!el!diseo.!

304
www.arquitecturajava.com!

305
Arquitectura*Java!

19.Programacin*Orientada*a*
Aspecto((AOP)!

En!el!captulo!anterior!hemos!utilizado!el!principio!DRY!para!simplificar!el!cdigo!de!la!
capa! de! persistencia! y! reducirlo! a! la! mnima! expresin,! como! muestra! el! siguiente!
mtodo.!

Cdigo!19.1:!(GenericDAOJPAImpl.java)!

public void borrar(T objeto) {


getJpaTemplate().remove(getJpaTemplate().merge(objeto));
}

Parece!que!es!imposible!simplificar!ms!el!cdigo!que!tenemos!y!estamos!en!lo!cierto!
en!cuanto!al!principio!DRY!se!refiere.!Aun!as,!existen!algunas!mejoras!que!se!pueden!
realizar!en!la!capa!de!persistencia!aunque!no!son!evidentes.!Si!revisamos!el!cdigo!que!
acabamos!de!mostrar,!nos!podremos!dar!cuenta!de!que!no!solo!se!encarga!de!borrar!
un!objeto!de!la!base!de!datos,!sino!que!adems!ejecuta!esa!operacin!dentro!de!una!
transaccin.! Igual! que! este! mtodo! ejecuta! una! transaccin,! el! resto! de! mtodos! de!
modificacin!tambin!!realizan!esta!operacin,!como!se!muestra!en!la!imagen.!

306
www.arquitecturajava.com!

En!principio!esto!no!parece!acarrear!ningn!problema!ya!que!al!habernos!apoyado!en!
las!plantillas!en!el!captulo!anterior,!no!tenemos!cdigo!repetido!en!estas!clases.!Lo!que!
sucede! es! que! la! responsabilidad! sobre! la! gestin! de! transacciones! est! distribuida! y!
cada!uno!de!los!mtodos!es!responsable!de!gestionar!sus!propias!transacciones.!Ahora!
bien,!supongamos!que!deseamos!realizar!la!siguiente!transaccin:!!

insertar!un!nuevo!libro!
borrar!un!libro!! !

Ambas!operaciones!se!tienen!que!realizar!de!una!forma!atmica!!e!indivisible!es!decir:!
o! se! realizan! ambas! operaciones! o! ninguna.! Es! en! este! momento! cuando! nos!
encontraremos! con! el! siguiente! problema:! cada! una! de! estas! operaciones! es! una!
transaccin!completamente!independiente!de!la!otra!(ver!imagen).!

No! es! posible! ,tal! como! tenemos! construida! la! solucin,! definir! una! transaccin! que!
agrupe!operaciones!de!varios!mtodos!de!forma!conjunta!(ver!imagen).!

307
Arquitectura*Java!

As! pues! nuestro! diseo! actual! tiene! un! problema! importante! ya! que! la! necesidad! de!
que! varios! mtodos! se! ejecuten! de! forma! conjunta! (transaccional)! es! algo! muy!
necesario!para!las!aplicaciones.!Para!solventar!este!problema,!necesitamos!centralizar!
la!gestin!de!las!transacciones!y!no!tenerla!dispersa!por!todo!el!cdigo.!Este!captulo!se!
centrar! en! solventar! esta! cuestin.! Para! ello! introduciremos! el! concepto! de!
programacin!orientada!a!aspecto!o!AOP!(AspectOrientedPrograming).!!

Objetivos:

Centralizar!la!gestin!de!transacciones.!!

Tareas:

1. Introduccin!a!AOP.!
2. Spring!y!Proxies.!
3. Configuracin!de!proxies!con!spring!

1. Introduccin!a!AOP!

En! estos! momentos! cada! uno! de! los! mtodos! de! nuestras! clases! se! encarga! de!
gestionar!de!forma!independiente!las!transacciones!.Si!queremos!unificar!la!gestin!de!
transacciones,! deberemos! extraer! la! responsabilidad! de! ejecutar! las! transacciones! de!
nuestras!clases!(ver!imagen).!

308
www.arquitecturajava.com!

No! parece! sencillo! realizar! esta! operacin! ya! que! si! extraemos! la! responsabilidad! de!
nuestras!clases,!no!podremos!!!ejecutar!los!mtodos!de!forma!transaccional!ya!que!no!
dispondrn!de!esa!capacidad.!Para!solventar!esto,!vamos!a!volver!a!retomar!el!ejemplo!
de! la! clase! Mensaje! y! vamos! a! usar! esta! clase! para! introducir! algunos! conceptos!
fundamentales! de! la! programacin! orientada! a! aspecto.! ! En! este! caso,! un! patrn! de!
diseo!fundamental!para!este!tipo!de!programacin!el!patrn!proxy.!

Patrn!Proxy!:!Este!patrn!hace!las!tareas!de!intermediario!entre!un!objeto!y!su!cliente!
permitiendo! controlar! el! acceso! a! l! aadiendo! o! modificando! la! funcionalidad!
existente! de! forma! transparente.! Para! aclarar! el! concepto,! vamos! a! construir! un!
ejemplo!sencillo!que!nos!facilite!entender!cmo!se!construye!un!Proxy,!a!tal!fin!vamos!a!
partir!del!interface!Mensaje!y!de!su!implementacin!MensajeHTML,!como!se!muestra!
en!la!siguiente!figura!y!bloque!de!cdigo.!

309
Arquitectura*Java!

Cdigo!19.2:!(MensajeHTML.java)!

public class MensajeHTML implements Mensaje {


public void hola() {
System.out.println("<html>hola</html>");
}
}
!

Para! construir! objetos! de! la! clase! MensajeHTML! vamos! a! hacer! uso! de! una! sencilla!
factora!(ver!imagen).!

310
www.arquitecturajava.com!

El!cdigo!de!la!factoria!es!el!siguiente.!

Cdigo!19.3:!(Principal.java)!

public class MensajeFactory {


public static Mensaje getMensaje() {
return new MensajeHTML();
}
}

Realizada! esta! operacin,! ! vamos! a! crear! un! objeto! de! nuestra! clase! a! travs! de! la!
factora.!

Cdigo!19.4:!(Principal.java)!

MensajeFactorymifactoria= new MensajeFactory()


Mensaje mensaje= mifactoria.getMensaje();
mensaje.hola ()

A!continuacin!podemos!ver!el!resultado!por!la!consola.!

As! pues! la! clase! factoria! se! encarga! simplemente! de! crear! el! objeto! y! luego! nosotros!
simplemente! invocamos! al! mtodo! hola()! y! el! cdigo! funciona! perfectamente.Ahora!
bien,! si! quisiramos! aadir! una! nueva! responsabilidad! a! la! clase! de! tal! forma! que! al!
invocar!el!mtodo!hola!se!imprima!por!pantalla!lo!siguiente.

311
Arquitectura*Java!

No!nos!quedara!ms!remedio!que!aadir!una!nueva!funcionalidad!al!mtodo!mensaje!
(ver!imagen).!

Cdigo!19.5:!(Mensaje.java)!

public void mensaje(String ) {


System.out.println(funcionalidad adicional proxy);
System.out.println(<html>+mensaje+</html>);
System.out.println(funcionalidad adicional proxy);
}!

De!esta!manera!la!funcionalidad!que!aadimos!queda!ligada!a!nuestro!cdigo!de!forma!
totalmente! esttica! y! definitiva.! A! partir! de! ahora! cuando! invoquemos! al! mtodo!
mensaje!siempre!se!imprimir!la!funcionalidad!de!log.!Si!queremos!que!la!funcionalidad!
aadida! sea! dinmica! y! podamos! ejecutarla! en! un! momento! determinado! o! no,! hay!
que!extraerla!de!la!clase!en!la!cul!la!acabamos!de!ubicar!(ver!imagen).!

312
www.arquitecturajava.com!

Para! extraer! la! responsabilidad! de! log! crearemos! una! clase! que! se! denomine!
ProxyMensajeLog.!Esta!clase!har!de!intermediaria!entre!la!factora!y!la!clase!mensaje,!
aadiendo!la!funcionalidad!extra!sin!modificar!la!clase!original.!A!continuacin!el!cdigo!
fuente!de!la!nueva!clase!asi!como!un!diagrama!que!ayuda!a!clarificar.!

Cdigo!19.6:!(MensajeProxy.java)!

public class MensajeProxy implements Mensaje {


private Mensaje mensaje;
public Mensaje getMensaje() {
return mensaje;
}
public void hola() {
System.out.println("funcionalidad adicional proxy");
mensaje.hola();
System.out.println("funcionalidad adicional proxy");
}
public MensajeProxy() {
this.mensaje = newMensajeHTML();
}
}
!

313
Arquitectura*Java!

La! imagen! muestra! con! claridad! cmo! la! clase! MensajeHTML! no! ha! sido! modificada.!
Podemos! volver! a! ejecutar! nuestro! programa! y! veremos! cmo! hemos! aadido! nueva!
funcionalidad!al!concepto!de!mensaje!(ver!imagen).!

Sin!embargo!la!clase!MensajeFactory!si!se!habr!modificidado!para!devolver!un!objeto!
de!tipo!MensajeProxy!como!se!muestra!a!continuacin.!

Cdigo!19.5:!(MensajeFactory.java)!

public class MensajeFactory


public static Mensaje getMensaje() {
return new MensajeProxy();
}
}
!

!Para!el!cliente!que!usa!la!factora!ni!siquiera!es!visible!que!existe!un!proxy!intermedio!
realizando! las! operaciones! adicionales! ,esto! es! totalmente! transparente! para! el!
programador! ya! que! el! cdigo! del! programa! principal! no! vara.! Nosotros! podramos!
configurar! la! factora! para! que! use! la! clase! proxy! o! la! clase! original! segn! nuestras!
necesidades!a!travs!por!ejemplo!de!un!fichero!de!properties.!

2. Usando!Proxies!con!Spring!

Ahora!bien!si!volvemos!a!nuestra!aplicacin!e!intentamos!realizar!un!smil,!nos!daremos!
cuenta!de!que!toda!la!capa!de!servicios!y!DAO!es!creada!a!travs!del!Framework!Spring!
el!cul!tiene!la!funcin!de!factora!(ver!imagen).!

314
www.arquitecturajava.com!

Por! lo! tanto! al! ser! Spring! una! factora,! podra! ser! el! encargado! de! construir! un! proxy!
para! cada! uno! de! los! objetos! creados! de! tal! forma! que! sean! estos! proxies! los!
encargados! de! aglutinar! la! responsabilidad! relativa! a! las! transacciones! (funcionalidad!
adicional),!como!se!muestra!en!la!siguiente!figura!en!la!que!todos!los!objetos!disponen!
de!un!proxy!a!travs!del!cual!se!accede!a!los!mismos!.!

Ahora!bien,!aunque!podamos!usar!el!framework!Spring!para!que!cada!uno!de!nuestros!
objetos! disponga! de! un! proxy! con! el! cul! gestionar! las! transacciones,! tenemos! el!
315
Arquitectura*Java!

problema!de!crear!una!clase!proxy!por!cada!una!de!las!clases!que!d!servicio!y!DAO!que!
tenemos!en!estos!momentos!(ver!imagen).!

Esto! parece! una! tarea! titnica! ya! que! en! una! aplicacin! podemos! tener! cientos! de!
clases! de! servicio! o! DAO.! Sin! embargo! Spring! posee! la! capacidad! de! generar!
dinmicamente!proxies!basndose!en!las!clases!ya!existentes!sin!tener!que!escribir!una!
lnea!de!cdigo.!Estos!proxies!son!especiales!!y!se!les!denomina!proxies!dinmicos!ya!
que!son!creados!en!tiempo!de!ejecucin.!Vase!una!imagen!del!proxy:!

316
www.arquitecturajava.com!

Estos!tipos!de!proxies!quedan!asociados!a!los!objetos!reales!.El!proceso!de!construccin!
automtica!de!un!proxy!es!complejo!(ver!imagen).!

Vamos!a!explicarlo!a!continuacin!con!mayor!profundidad!:!

1. Spring!lee!el!fichero!de!configuracin!con!los!distintos!tipos!de!beans!existentes!!
2. Spring!instancia!los!objetos!requeridos!por!el!fichero!!
3. Spring!lee!los!metadatos!de!un!objeto!determinado!que!acabamos!de!instanciar!
(clase,!metodos,!interfaces,!etc)!a!traves!del!api!de!reflection.!
4. Spring!crea!un!proxy!por!cada!objeto!instanciado!que!lo!necesite!!
5. Spring!asocia!el!proxy!al!objeto!

Por! lo! tanto! con! Spring! podemos! crear! el! conjunto! de! objetos! que! necesitemos! y!
asignarles!a!todos!un!proxy!!de!forma!automtica!.!Una!vez!hecho!esto,!cada!vez!que!
una! aplicacin! cliente! desee! acceder! a! un! objeto! determinado,! el! proxy! actuar! de!
intermediario!y!aadir!la!funcionalidad!adicional!que!deseemos!(ver!imagen).!

317
Arquitectura*Java!

Esta!funcionalidad!adicional!que!aadimos!a!travs!del!proxy!es!comnmente!conocida!
como!Aspecto!!y!es!compartidad!habitualmente!por!!varios!proxies!(ver!imagen).!

Una! vez! que! tenemos! claro! que! el! framework! Spring! puede! generar! estos! proxies,!
debemos! decidir! qu! tipo! de! proxy! queremos! crear! pues! Spring! soporta! varios! (ver!
imagen).!

318
www.arquitecturajava.com!

En!nuestro!caso!vamos!a!definir!proxies!que!nos!ayuden!a!gestionar!las!transacciones!
entre! las! distintas! invocaciones! a! los! mtodos! de! la! capa! de! persistencia.! Por! ello!
elegiremos! los! proxies! de! transaccin,! que! sern! los! encargados! de! ejecutar! la!
funcionalidad!relativa!a!las!transacciones!(ver!imagen).!

3. Configuracin!de!proxies!y!transacciones.!

Para! poder! trabajar! con! proxies! que! gestionen! transacciones! en! nuestra! aplicacin!
deberemos! aadir! un! gestor! transaccional! a! la! configuracin! del! framework! Spring!

319
Arquitectura*Java!

como! la! figura! anterior! muestra! .En! este! caso! utilizaremos! un! gestor! transaccional!
orientado!a!JPA,!que!se!define!a!travs!de!un!bean!de!Spring.!

Cdigo!19.7:!(contextoAplicacion.xml)!

<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory" ref="entityManagerFactory" />
</bean>

En!segundo!lugar,!al!fichero!de!configuracin!debemos!aadir!una!nueva!etiqueta!que!
ser! la! encargada! de! crear! los! distintos! proxies! transaccionales! para! todas! nuestras!
clases!.!

Cdigo!19.8:!(contextoAplicacion.java)!

<tx:annotation-driven />

Esta!etiqueta,!a!nivel!de!fichero!xml,!permitir!al!framework!Spring!dar!de!alta!proxies!
para!todas!aquellas!clases!que!dispongan!de!mtodos!marcados!como!transaccionales.!
Para!marcar!los!mtodos!como!transaccionales!debemos!aadir!un!nuevo!conjunto!de!
anotaciones!a!nuestra!aplicacin!(ver!cdigo).!

Cdigo!19.9:!(GenericDAOJPAImpl.java)!

@Transaccional

Estas!anotaciones!son!aportadas!!por!el!framework!Spring!y!se!encargan!de!definir!!la!
transaccionalidad!para!cada!uno!de!los!mtodos!de!nuestras!clases.!A!continuacin!se!
muestra!una!lista!con!los!distintos!tipos!de!transacciones!soportadas!por!Spring:!

1. Required!:Se!requiere!de!una!transaccin,!si!existe!una!transaccin!en!curso,!el!
mtodo!se!ejecutara!dentro!de!ella!!si!no,!el!mtodo!se!encargar!de!iniciar!una!
nueva.!!
2. Required_New! :Requiere! ejecutarse! de! forma! transaccional! ,! si! existe! una!
transaccin! creada!,! suspender! la! que! esta! en! curso.! En! el! caso! de! no! existir!
una!transaccin,!crear!una.!
3. Supports!:!Si!existe!una!transaccin,!se!ejecutar!dentro!de!ella.!Si!no!existe,!no!
iniciar!ninguna!
4. Not_Supported! :! Se! ejecutar! fuera! de! una! transaccin.! Si! esta! transaccin!
existe,!ser!suspendida.!
320
www.arquitecturajava.com!

5. Mandatory:!Debe!ejecutarse!obligatoriamente!de!forma!transaccional.!Si!no!lo!
hace,!lanzar!una!excepcin.!
6. Never! :Debe! ejecutarse! siempre! de! forma! no! transaccional.! Si! existe! una!
transaccin,!lanzar!una!excepcin.!
7. Nested!:Crear!una!nueva!transaccin!dentro!de!la!transaccin!actual.!

Una!vez!declarados!los!distintos!atributos!se!usarn!as!a!nivel!de!clase:!!

Cdigo!19.10:!(LibroJPADAOImpl.java)!

@Transactional(propagation=Propagation.Required)
public void insertarLibro() {
// codigo
}
!

De! esta! manera! el! mtodo! se! ejecutar! de! forma! transaccional.! El! valor!
Propagation.Required!se!aplica!por!defecto!en!el!caso!de!que!no!se!haya!especificado!
nada.!Por!lo!tanto,!el!mtodo!tambin!podra!haberse!anotado!de!la!siguiente!forma:!

Cdigo!19.10:!(LibroJPDADAOImpl.java)!

@Transactional
public void insertarLibro() {
// codigo
}

As!estaremos!sealando!que!el!mtodo!se!ejecuta!dentro!de!una!transaccion.Vamos!a!
ver!como!afectan!estas!anotaciones!a!nuestras!clases!de!la!capa!DAO!y!de!la!capa!de!
Servicios.!

321
Arquitectura*Java!

Cdigo!19.11:!(GenericDAOJPAImpl.java)!

public abstract class GenericDAOJPAImpl<T, Id extends Serializable> extends


JpaDaoSupport implements
GenericDAO<T, Id> {
private Class<T> claseDePersistencia;

@SuppressWarnings("unchecked")
public GenericDAOJPAImpl() {
this.claseDePersistencia = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
@Override
public T buscarPorClave(Id id) {
return getJpaTemplate().find(claseDePersistencia, id);
}
@SuppressWarnings("unchecked")
@Transactional(readOnly=true)
public List<T> buscarTodos() {

return getJpaTemplate().find("select o from "


+ claseDePersistencia.getSimpleName() + " o");
}
@Transactional
public void borrar(T objeto) {
getJpaTemplate().remove(getJpaTemplate().merge(objeto));
}
@Transactional
public void salvar(T objeto) {

getJpaTemplate().merge(objeto);
}
@Transactional
public void insertar(T objeto) {
getJpaTemplate().persist(objeto);
}
}
!

322
www.arquitecturajava.com!

Cdigo!19.12:!(ServicioLibrosImpl.java)!

package com.arquitecturajava.aplicacion.servicios.impl;

//omitimos imports
public class ServicioLibrosImpl implements ServicioLibros {

private LibroDAO libroDAO=null;


private CategoriaDAO categoriaDAO=null;
//omitimos set/get
@Transactional
public void salvarLibro(Libro libro) {
libroDAO.salvar(libro);
}
@Transactional
public void borrarLibro(Libro libro) {
libroDAO.borrar(libro);
}
@Transactional
public List<Libro> buscarTodosLosLibros() {
return libroDAO.buscarTodos();
}
@Transactional
public void insertarLibro(Libro libro) {
libroDAO.insertar(libro);
}
@Transactional
public List<Libro> buscarLibrosPorCategoria(Categoria categoria) {
return libroDAO.buscarPorCategoria(categoria);
}
@Transactional
public Libro buscarLibroPorISBN(String isbn) {
return libroDAO.buscarPorClave(isbn);
}
@Transactional
public Categoria buscarCategoria(int id) {
// TODO Auto-generated method stub
return categoriaDAO.buscarPorClave(id);
}
@Transactional
public List<Categoria> buscarTodasLasCategorias() {
// TODO Auto-generated method stub
return categoriaDAO.buscarTodos();
}

}
!

323
Arquitectura*Java!

Una! vez! dispuestas! las! anotaciones! que! marcan! los! ! mtodos! que! soportan!
transacciones,! es! momento! para! mostrar! como! Spring! se! encarga! de! ejecutar! una!
transaccin!atmica! entre! varios! mtodos! a! travs! del! uso! de! un! conjunto! de! proxies!
que! comparten! el! mismo! objeto! conexin.! A! continuacin! se! muestra! un! diagrama!
aclaratorio:!

Vamos! a! ver! cul! es! la! estructura! final! del! fichero! de! configuracin! de! Spring! con! las!
nuevas!etiquetas.!

324
www.arquitecturajava.com!

Cdigo!19.13:!(contextoAplicacion.xml.java)!

<beans>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="dataSource
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName" value="com.mysql.jdbc.Driver" />
<propertyname="url"
value="jdbc:mysql://localhost/arquitecturaJavaORM" />
<propertyname="username" value="root" />
<propertyname="password" value="java" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<propertyname="persistenceUnitName" value="arquitecturaJava" />
<propertyname="dataSource" ref="dataSource" />
<propertyname="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<propertyname="databasePlatform"
value="org.hibernate.dialect.MySQL5Dialect" />
<propertyname="showSql" value="true" />
</bean>
</property>
</bean
<bean id="servicioLibros"
class="com.arquitecturajava.aplicacion.servicios.impl.ServicioLibrosImpl">
<propertyname="libroDAO" ref="libroDAO"></property>
<propertyname="categoriaDAO" ref="categoriaDAO"></property>
</bean>
<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
<propertyname="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
<propertyname="entityManagerFactory" ref="entityManagerFactory" />

</bean>
</beans>

Realizada! esta! operacin,! sern! los! proxies! los! que! controlen! cmo! se! ejecuta! una!
transaccin!y!a!cuntos!mtodos!afecta!de!forma!simultnea!(ver!imagen).!

325
Arquitectura*Java!

Resumen!
En! este! captulo! hemos! aadido! una! gestin! transaccional! transparente! ,distribuida!
entre!los!distintos!mtodos!!de!la!capa!de!servicio!y!cada!DAO,!usando!programacin!
orientada!a!objeto!y!un!gestor!transacional.!As!!simplificamos!sobremanera!la!gestin!
transacional!que!habra!sido!necesario!desarrollar!en!una!programacin!clsica.!

! !

326
www.arquitecturajava.com!

327
Arquitectura*Java!

20.Uso#de#anotaciones!y"COC!

Hemos! simplificado! la! capa! de! persistencia! y! la! capa! de! servicios! a! travs! del! uso! de!
Spring! tanto! como! framework! de! Inversin! de! Control! e! Inyeccin! de! dependencia!
como! usando! sus! capacidades! de! programacin! orientada! a! aspecto! a! la! hora! de!
disear!la!gestin!de!transacciones.!Sin!embargo,!aunque!primeramente!parece!que!no!
hemos!pagado!ningn!precio!por!ello,!la!realidad!es!distinta.!Segn!pasan!los!captulos!
el! fichero! de! configuracin! (contextoAplicacion.xml)! que! tenemos! es! cada! vez! ms!
grande!y!con!ms!elementos.!Por!lo!tanto!cada!vez!ser!ms!difcil!de!configurar!y!de!
entender! .! Volvemos! a! la! situacin! de! los! captulos! de! Hibernate! donde! podamos!
acabar!con!un!nmero!muy!elevado!de!ficheros!xml!de!mapeo.!Es!momento!de!hacer!
uso! del! principio! de! convencin! sobre! configuracin! (COC)! y,! a! travs! del! uso! de!
anotaciones,! simplificar! el! fichero! xml! con! el! que! trabajamos.! Ese! ser! el! objetivo! del!
presenta!captulo.!

!
328
www.arquitecturajava.com!

Objetivos:

Simplificar!el!fichero!de!configuracin!de!Spring!apoyndonos!en!anotaciones!y!
en!el!principio!COC.!

Tareas:

1. !@PersistenceContext!y!Entity!manager!
2. @Repository!!y!manejo!de!excepciones!
3. @Service!y!capas!de!Servicio!
4. @AutoWired!e!inyeccin!de!dependencia!

1. @PersistenceContext!y!EntityManager!

En!estos!momentos!tenemos!diseada!nuestra!capa!DAO!a!travs!de!JPA!y!utilizando!la!
clase!JPADAOSupport!como!apoyo!a!la!hora!de!crear!cualquiera!de!nuestras!clases!DAO!!
(ver!cdigo)!

Al! depender! todas! nuestras! clases! de! la! clase! JPADAOSupport,! todas! soportarn! la!
asignacin!de!un!entityManagerFactory!a!travs!del!fichero!contextoAplicacion.xml!de!
Spring!(ver!figura).!

!
329
Arquitectura*Java!

Cdigo!20.1:!(contextoAplicacion.xml)!

<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
!

Como!anteriormente!hemos!comentado,!es!momento!de!intentar!poco!a!poco!reducir!
este! fichero! de! configuracin! y! eliminar! etiquetas! .A! tal! fin,! haremos! uso! de! una!
anotacin! soportada! por! el! estndar! de! JPA:! la! anotacin! @PersistenceContext! .Esta!
anotacin! nos! inyectar! de! forma! directa! un! entityManager! a! cada! una! de! nuestras!
clases!DAO!de!forma!transparente,!sin!tener!que!usar!etiquetas!<property>!a!nivel!del!
fichero!contextoAplicacion.xml!.!Para!ello!debemos!aadir!esta!nueva!lnea:!

Cdigo!20.2:!(contextoAplicacion.xml)!

<context:annotation-config />

Esta! lnea! se! encarga! de! inyectar! de! forma! automtica! el! entity! manager! a! todas! las!
clases! que! usen! la! anotacin! @PersistenceContext.! Por! lo! tanto,! a! partir! de! este!
momento,!ninguna!de!las!clases!de!la!capa!de!persistencia!tendr!asignada!propiedades!
de!entity!manager!(ver!figura).!

Cdigo!20.3:!(contextoAplicacion.xml)!

<bean id="libroDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.LibroDAOJPAImpl">
</bean>
<bean id="categoriaDAO"
class="com.arquitecturajava.aplicacion.dao.jpa.CategoriaDAOJPAImpl">
</bean>

Seguidamente!se!muestra!la!modificacin!que!hemos!tenido!que!realizar!a!nivel!de!la!
clase!GenericDAOJPAImpl.!

330
www.arquitecturajava.com!

Cdigo!20.4:!(GenericDAOJPAImpl.java)!

public abstract class GenericDAOJPAImpl<T, Id extends Serializable> implements


GenericDAO<T, Id> {
private Class<T> claseDePersistencia;
@PersistenceContext
private EntityManager manager;

public EntityManager getManager() {


return manager;
}
public void setManager(EntityManager manager) {
this.manager = manager;
}
@SuppressWarnings("unchecked")
public GenericDAOJPAImpl() {

this.claseDePersistencia = (Class<T>) ((ParameterizedType) getClass()


.getGenericSuperclass()).getActualTypeArguments()[0];
}
public T buscarPorClave(Id id) {
return getManager().find(claseDePersistencia, id);
}

@Transactional(readOnly=true)
public List<T> buscarTodos() {
List<T> listaDeObjetos = null;
TypedQuery<T> consulta = manager.createQuery("select o from "
+ claseDePersistencia.getSimpleName() + " o",
claseDePersistencia);
listaDeObjetos = consulta.getResultList();
return listaDeObjetos;
}
@Transactional
public void borrar(T objeto) {
getManager().remove(getManager().merge(objeto));
}
@Transactional
public void salvar(T objeto) {
getManager().merge(objeto);
}
@Transactional
public void insertar(T objeto) {

getManager().persist(objeto);
}
}
!

331
Arquitectura*Java!

Como! podemos! ver! hemos! usado! directamente! la! clase! manager! para! invocar! los!
mtodos! de! persistencia! y! no! hemos! usado! para! nada! el! mtodo! getTemplate()! de! la!
clase! JPADAOSupport.! Esta! clase! se! encargaba! de! obtener! el! manager! de! Spring! y! de!
gestionar!las!excepciones.!Ya!no!heredamos!de!ella!puesto!que!no!la!necesitamos!para!
inyectar!el!objeto!EntityManager.!Sin!embargo!si!tenemos!que!gestionar!excepciones,!
una!vez!que!hemos!dejado!de!heredar!de!JPADAOSupport,!deberemos!aadir!algo!ms!
para!que!todo!funcione!como!antes.!La!siguiente!tarea!se!encargara!de!esto.!

2. @Repository!y!manejo!de!excepciones!

Spring! puede! trabajar! con! varios! frameworks! de! persistencia! desde! JDBC! a! Hibernate!
pasando! por! JPA! o! IBatis! y! para! cada! una! de! estas! soluciones! genera! un! conjunto! de!
excepciones!distinto.!Por!lo!tanto,!para!que!nuestra!aplicacin!se!comporte!de!la!misma!
forma! sin! importar! cul! es! el! framework! de! persistencia! usado! o! cules! son! las!
excepciones! que! se! lanzan,! deberemos! marcar! nuestras! clases! de! capa! DAO! con! la!
anotacin!@Repository,!la!cul!se!encargar!de!traducir!las!excepciones!que!se!hayan!
construido,!as!como!de!cerrar!recursos!(ver!figura).!

Vamos! a! ver! cmo! nuestras! clases! hacen! uso! de! la! anotacin! .A! continuacin! se!
muestra!el!cdigo!fuente!de!una!de!ellas.!Todas!las!clases!DAO!incorporan!a!partir!de!
ahora!esta!anotacin.!

332
www.arquitecturajava.com!

Cdigo!20.5:!(contextoAplicacion.xml)!

@Repository
public abstract class GenericDAOJPAImpl<T, Id extends Serializable>implements
GenericDAO<T, Id>{
private Class<T> claseDePersistencia;
@PersistenceContext
private EntityManager manager;
public EntityManager getManager() {
return manager;
}

Al! marcar! nuestras! clases! con! la! anotacin! ! @Repository,! conseguimos! que! Spring!
gestione! el! manejo! de! excepciones! de! una! forma! ms! integrada,! encargndose! de!
cerrar!los!recursos!de!conexiones!abiertas!etc!.!Ahora!bien,!al!marcar!la!clase!con!esta!
anotacin,! ya! no! ser! necesario! registrar! esta! clase! a! nivel! de! contextoAplicacion.xml!
pues! al! anotarla! queda! registrada! de! forma! automtica.! A! continuacin! se! muestra!
cmo!queda!nuestro!fichero.!

Cdigo!20.6:!(contextoAplicacion.xml)!

<bean id="servicioLibros"
class="com.arquitecturajava.aplicacion.servicios.impl.ServicioLibrosImpl>
</bean>
<!eliminamos las clases dao!
!

Eliminadas! las! clases! DAO! del! fichero! xml,! pasaremos! a! revisar! las! clases! de! servicio!
para!realizar!la!misma!operacin!

3. Anotacin!@Service!

Vamos!a!aadir!una!nueva!anotacin!a!nuestra!clase!de!servicios!denominada!@Service!
que!nos!permite!eliminar!tambin!estas!clases!del!fichero!de!configuracin!xml!donde!
las!tenemos!ubicadas!.!A!continuacin!se!muestra!el!cdigo!fuente!de!nuestra!clase!una!
vez!aadida!la!anotacin:!

Cdigo!20.7:!(contextoAplicacion.xml)!

@Service(value=servicioLibros)
public class ServicioLibrosImpl implements ServicioLibros {
// resto de cdigo
}
!

333
Arquitectura*Java!

Una!vez!realizada!esta!operacin,!podremos!eliminar!las!clases!de!servicio!del!fichero!
xml!y!simplificarlo!(ver!cdigo).!

Cdigo!20.8:!(contextoAplicacion.xml)!

<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!eliminamos las clases de servicio!

Hemos! eliminado! todas! las! clases! de! servicio! y! clases! DAO! de! nuestro! fichero! xml! ya!
que!a!travs!de!las!anotaciones!se!registran!como!componentes!de!forma!automtica.!
Para!ello,!nicamente!deberemos!aadir!la!siguiente!lnea!de!cdigo!a!nuestro!fichero:!

<context:component-scan base-package="com.arquitecturajava.aplicacion.*" />


!

Esta! lnea! se! encargar! de! buscar! en! los! distintos! paquetes! clases! anotadas! y!
registrarlas!sin!necesidad!de!que!aparezcan!en!el!fichero.!Hecho!esto,!ya!tenemos!todas!
las! clases! registradas.! Lamentablemente! el! fichero! xml! no! slo! se! encargaba! de!
registrarlas! sino! tambin! de! relacionarlas! a! travs! de! la! etiqueta! <property>! y! esta!
funcionalidad! todava! no! la! hemos! cubierto.! La! siguiente! anotacin! nos! ayudar! a!
cumplir!con!esta!tarea.!

4. Anotaciones!@AutoWired!

La! anotacion! @AutoWired! est! basada! en! el! principio! de! convencin! sobre!
configuracin!para!simplificar!la!inyeccion!de!dependencias!entre!las!distintas!clases.!Se!
encarga! de! buscar! las! relaciones! existentes! entre! los! distintos! objetos! registrados! e!
inyecta!de!forma!automtica!las!dependencias(!ver!imagen).!

334
www.arquitecturajava.com!

Una! vez! tenemos! claro! cmo! funciona! esta! anotacin,! vamos! a! ver! cmo! queda! el!
codigo!de!la!clase!de!servicio.!

Cdigo!20.6:!(ServicioLibrosImpl.xml)!

@Service(value="servicioLibros")
public class ServicioLibrosImpl implements ServicioLibros {
private LibroDAO libroDAO=null;
private CategoriaDAO categoriaDAO=null;
@Autowired
public void setLibroDAO(LibroDAO libroDAO) {
this.libroDAO = libroDAO;
}
@Autowired
public void setCategoriaDAO(CategoriaDAO categoriaDAO) {
this.categoriaDAO = categoriaDAO;
}
//resto!de!cdigo!

!
De!esta!manera!hemos!pasado!de!una!configuracin!basada!exclusivamente!en!ficheros!
xml! a! una! configuracin! en! la! que! las! anotaciones! tienen! mas! peso! y! el! fichero! se!
reduce!significativamente!(ver!imagen).!

335
Arquitectura*Java!

Las! anotaciones! y! el! principio! de! convencion! sobre! configuracin! nos! han! permitido!
eliminar!informacin!redundante!a!nivel!de!la!configuracin.!Seguidamente!se!muestra!
cmo!queda!el!fichero!contextoAplicacion.xml!,!podemos!ver!cmo!claramente!ha!sido!
simplificado!sin!tener!que!registrar!ninguna!clase.!

<tx:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.arquitecturajava.aplicacion.*" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost/arquitecturaJavaORM" />
<property name="username" value="root" />
<property name="password" value="java" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
>
<property name="persistenceUnitName" value="arquitecturaJava" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform"
value="org.hibernate.dialect.MySQL5Dialect" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

336
www.arquitecturajava.com!

Resumen!!
En!este!capitulo!hemos!conseguido!simplificar!sobremanera!el!fichero!de!configuracin!
de! Spring! apoyandomos! en! el! conceptos! de! convencin! sobre! configuracin! asi! como!
en!la!programacin!orientada!a!aspecto.!

! !

337
Arquitectura*Java!

21.Java$Server$faces!
!

En! los! ltimos! captulos! nos! hemos! centrado! en! el! uso! de! Spring! para! mejorar! y!
simplificar! la! construccin! de! la! capa! de! persistencia! y! de! servicios! de! nuestra!
aplicacin.! ! Es! momento! de! volver! a! mirar! hacia! la! capa! de! presentacin! que! hemos!
construido!apoyndonos!en!el!standard!de!JSTL!!y!hacerla!evolucionar!hacia!estndares!
ms!actuales,!en!concreto!hacia!Java!Server!Faces!o!JSF!.!!JSF!es!el!framework!standard!
a! nivel! de! capa! de! presentacin! en! arquitecturas! JEE.! Este! captulo! servir! de!
introduccin!a!JSF!.Se!crearn!algunos!ejemplos!tiles!a!la!hora!de!migrar!la!aplicacin!a!
esta!tecnologa!en!prximos!captulos!

Objetivos:!

Introducir!!JSF!y!desarrollar!unos!ejemplos!bsicos!que!nos!sean!tiles!cuando!
migremos!nuestra!aplicacin!!
!

Tareas:!

1. Introduccion!a!JSF.!
2. Instalar!JSF!2.0.!
3. HolaMundo!con!JSF!
4. Construccin!de!un!combo!con!JSF!
5. Creacin!de!tabla!con!JSF!

338
www.arquitecturajava.com!

1. Introduccin!a!JSF!

Hasta!este!momento!hemos!usado!JSTL!y!un!modelo!MVC2!para!gestionar!la!capa!de!
presentacin.! Ahora! bien,! la! capa! de! presentacin! construida! hasta! este! momento! se!
basa!en!el!uso!de!un!conjunto!de!etiquetas!sencillas!como!son!las!etiquetas!<c:forEach>!
y!<c:out>!que!se!muestran!en!la!siguiente!figura!y!que!estn!ligadas!al!modelo!MVC2!y!
su!controlador.!

Es!momento!de!avanzar!y!modificar!el!conjunto!de!etiquetas!que!tenemos!para!poder!
usar! etiquetas! ms! complejas! que! aporten! mayor! funcionalidad.! Son! etiquetas!
aportadas!por!el!framework!de!JSF!y!en!lugar!de!definir!bubles!sencillos!o!sentencias!if!
estn!orientadas!a!definir!controles!complejos!,!de!tal!forma!que!el!desarrollador!pueda!
utilizar! estos! controles! para! desarrollar! aplicaciones! de! mayor! complejidad! ms!
rpidamente!.!A!continuacin!se!muestra!una!imagen!aclaratoria.!

339
Arquitectura*Java!

Como!podemos!ver,!en!este!caso!las!etiquetas!definen!un!formulario!y!una!tabla! que!
muestra!una!lista!de!datos!as!como!un!nuevo!controlador.!Es!evidente!que!el!nivel!de!
abstraccin!se!ha!incrementado.!Una!vez!explicado!el!concepto!a!nivel!general,!vamos!a!
instalar!el!framework!de!JSF!y!crear!unos!ejemplos!sencillos.

2. Instalacin!de!JSF!

Para! instalar! el! framework! de! Java! Server! ! Faces! en! nuestra! aplicacin! debemos!
acceder! a! la! siguiente! url! y! obtener! las! libreras! necesarias.! En! este! caso! las! que!
correspondan!a!la!versin!2.x.!

http://javaserverfaces.java.net/!

Una!vez!obtenido!el!framework,!es!necesario!extraer!los!siguientes!ficheros!jar!del!zip!
que!acabamos!de!bajar!

jsftapi.jar.!
jsftimpl.jar.!

340
www.arquitecturajava.com!

Finalmente!extraemos!los!ficheros!al!directorio!lib!de!nuestra!aplicacin.!

Realizada!esta!operacin,!vamos!a!pasar!a!configurar!el!propio!framework!.A!diferencia!
de! la! situacin! actual! en! la! que! nosotros! tenemos! construido! con! controlador! para!
nuestra!aplicacin!,el!framework!de!JSF!aporta!!un!controlador!pre!construido!que!se!
denomina!FacesServlet.!As!,!para!poder!trabajar!con!JSF!hay!que!dar!de!alta!un!nuevo!
controlador! a! nivel! de! web.xml! ! ! y! eliminar! el! existente.! A! continuacin! se! muestra!
cmo!dar!de!alta!el!nuevo!controlador!en!el!web.xml.!

Cdigo!21.1:!(web.xml)!

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>

Antes!de!entrar!a!modificar!nuestra!aplicacin,!vamos!a!construir!una!serie!de!ejemplos!
sencillos!que!nos!permitan!conocer!la!tecnologa!y!manejar!este!nuevo!controlador.!

341
Arquitectura*Java!

3. Hola!Mundo!con!JSF!

Hasta!este!momento!nuestra!capa!de!presentacin!se!basaba!fundamentalmente!en!un!
controlador!y!un!conjunto!de!acciones!asociados!a!ste!(ver!imagen).!

Al! usar! el! framework! de! JSF! no! vamos! a! tener! la! necesidad! de! apoyarnos! en! un!
conjunto!de!acciones!como!tal,!sino!que!el!framework!se!apoya!en!un!nuevo!concepto!
denominado!ManagedBean.!Por!lo!tanto!a!partir!de!ahora!nuestro!nuevo!controlador!
FaceServlet!se!apoyar!en!un!conjunto!de!ManagedBeans!para!realizar!las!operaciones!
(ver!imagen).!

Un! managedBean! es! una! clase! que! realiza! tareas! de! intermediario! entre! la! capa! de!
presentacin! y! la! capa! de! servicios! .! Por! lo! tanto! todas! las! paginas! JSF! se! apoyan! en!
ellas!para!enviar!o!recibir!informacin!(ver!imagen).!

342
www.arquitecturajava.com!

Los!ManagedBeans!desempean!!el!mismo!rol!que!tenan!hasta!ahora!los!comandos!o!
acciones!!pero!a!diferencia!de!!stos,!son!capaces!de!tratar!con!varios!eventos!y!no!con!
uno!solo,!como!ocurre!con!las!acciones!construidas!hasta!ahora.!Vamos!a!comenzar!a!
tomar!contacto!con!JSF!como!tecnologa!de!capa!de!presentacin.!Para!ello!nos!vamos!
a!construir!nuestra!pagina!de!HolaMundo!usando!JSF.!En!este!caso!vamos!a!partir!de!un!
formulario!elemental!que!nos!solicita!un!nombre!(ver!imagen).!

Una! vez! que! tenemos! claro! cul! es! el! aspecto! del! formulario,! vamos! a! ver! el! codigo!
fuente!a!nivel!de!JSF.

Cdigo!21.2:!(formularioNombre.xhtml)!

<htmlxmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:viewcontentType="text/html"/>
<h:head>
<title>HolaMundo</title>
</h:head>
<h:body>
<h:form id="holaMundo">
<h:inputText id="nombreUsuario"value="#{usuarioBean.nombre}"/>
<h:commandButton id="submit"action="resultado"value="Aceptar"/>
</h:form>
</h:body>
</html>

343
Arquitectura*Java!

Podemos!observar!que!las!etiquetas!de!JSF!tienen!cierta!similitud!con!las!etiquetas!JSTL!
y!la!diferencia!ms!importante!entre!ellas!es!que!las!JSF!estn!claramente!orientadas!a!
la!definicin!de!controles,!como!es!el!caso!de!la!etiqueta!<h:inputText>!que!!define!una!
caja!de!texto.!

Cdigo!21.3:!(formularioNombre.xhtml)!

<h:inputText id="nombreUsuario"value="#{usuarioBean.nombre}"/>

Una!vez!definida!la!caja!de!texto,!define!el!siguiente!atributo!

Cdigo!21.4:!(formularioNombre.xhtml)!

value="#{usuarioBean.nombre}"

Este!atributo!define!que!el!valor!que!se!escriba!en!la!caja!de!texto!est!asociado!a!un!
ManagedBean!,!concretamente!al!campo!nombre!de!este!managedBean.!Vamos!pues!a!
ver!cmo!se!construye!un!ManagedBean!que!est!asociado!a!este!formulario.!

Cdigo!21.5:!(formularioNombre.xhtml)!

package com.arquitectura.beans;
import javax.faces.bean.ManagedBean;

@ManagedBean
public class UsuarioBean {

private String nombre;


Public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
}

Visiblemente! se! trata! de! una! sencilla! clase! java! a! la! que! se! le! asigna! una! nueva!
anotacion! @ManagedBean.! Una! vez! asignada! esta! anotacin! al! formulario,! JSF! y! el!
managedBean!se!relacionan!a!travs!de!la!etiqueta.!

344
www.arquitecturajava.com!

Cdigo!21.6:!(formularioNombre.xhtml)!

<h:inputText id="nombreUsuario"value="#{usuarioBean.nombre}"/>

Como!la!siguiente!imagen!muestra.!

Una!vez!que!tenemos!claro!esta!relacin,!vamos!a!explicar!el!otro!control!que!existe!a!
nivel!de!la!pgina!y!que!consiste!en!un!botn.!

Cdigo!21.7:!(formularioNombre.xhtml)!

<h:commandButton id="submit"action="resultado"value="Aceptar"/>

Este! botn! simplemente! se! encarga! de! invocar! a! otra! pagina! denominada!
resultado.xhtml! haciendo! uso! del! atributo! action.! Una! vez! pulsado! el! botn!
accederemos!a!la!hora!pagina!que!mostrar!la!siguiente!estructura:!

Visto! el! resultado,! vamos! a! comprobar! cul! es! la! estructura! de! la! pgina!
resultado.xhtml.!

345
Arquitectura*Java!

Cdigo!21.8:!(formularioNombre.xhtml)!

<htmlxmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:viewcontentType="text/html; charset=iso-8859-1"/>
<head><title>Respuesta</title></head>
<body>
<h:form id="formularioRespuesta">
<h2>Hola, #{usuarioBean.nombre}</h2>
<h:commandButton id="volver" value="volver" action="formularioNombre" />
</h:form>
</body>
</html>

De! esta! manera! quedan! ligadas! las! dos! pginas! al! managedBean.! La! primera! enva!
datos! al! managedBean,! que! los! almacena.! La! segunda! pgina! lee! datos! del!
ManagedBean.!La!siguiente!figura!aclara!los!conceptos:!

4. Construir!un!combo!con!JSF!

Acabamos! de! ver! el! ejemplo! ms! sencillo! de! JSF! .Sin! embargo! en! nuestra! aplicacin!
existen!dos!situaciones!algo!mas!complejas.!La!primera!es!!la!carga!del!desplegable!de!
categoras!y!la!segunda!la!presentacin!de!datos!en!una!tabla!.!Vamos!a!cubrir!cada!una!
de!estas!situaciones!usando!JSF!con!ejemplos!bsicos!para!luego!integrarlos!en!nuestra!

346
www.arquitecturajava.com!

aplicacin.!A!tal!fin!comenzaremos!usando!JSF!para!cargar!una!lista!de!elementos!en!un!
formulario!sencillo!!(ver!imagen).!

Una! vez! que! tenemos! claro! que! debemos! construir! vamos! a! verlo! con! detalle! en! el!
siguiente!bloque!de!cdigo.!

Cdigo!21.9:!(formularioSeleccion.xhtml)!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:viewcontentType="text/html"/>
<h:head>
<title>HolaLista</title>
</h:head>
<h:body>
<h:form id="holaMundo">
<h:selectOneMenuvalue="#{usuarioBeanLista.nombre}">
<f:selectItemsvalue="#{usuarioBeanLista.listaNombres}" />
</h:selectOneMenu>
<h:commandButton id="submit"action="resultadoLista"value="Aceptar"/>
</h:form>
</h:body>
</html>

Es!evidente!que!nuestro!cdigo!fuente!hace!uso!de!un!nuevo!control!como!se!muestra!
a!continuacin.!

347
Arquitectura*Java!

Cdigo!21.10:!(formularioSeleccion.xhtml)!

<h:selectOneMenuvalue="#{usuarioBeanLista.nombre}">

Este!control!es!el!encargado!de!definir!un!combo!desplegable!.Ahora!bien,!recordemos!
que!estos!controles!realizan!las!dos!siguientes!funciones:!

Mostrar!una!lista!de!elementos!
Permitir!seleccionar!uno!

Para!mostrar!la!lista!de!elementos!nuestro!control!hace!uso!!de!la!siguiente!etiqueta!

Cdigo!21.11:!(formularioSeleccion.xhtml)!

<f:selectItems value="#{usuarioBeanLista.listaNombres}" />

!!! apoyndose! en! un! managedBean! denominado! usuarioBeanLista,! ! que! carga!


una!lista!de!elementos!.Por!otro!lado,!para!elegir!un!elemento!y!almacenarlo,!hace!uso!
del!mismo!bean!y!de!la!propiedad!nombre.!

Cdigo!21.12:!(formularioSeleccion.xhtml)!

<h:selectOneMenu value="#{usuarioBeanLista.nombre}">

Una!vez!claros!cules!son!los!elementos!que!ha!de!tener!nuestro!ManagedBean,!vamos!
a!mostrar!su!cdigo!fuente.!

348
www.arquitecturajava.com!

Cdigo!20.12:!(formularioSeleccion.xhtml)!

package com.arquitectura.beans;
//omitimos import
@ManagedBean
public class UsuarioBeanLista {
privateList<SelectItem>listaNombres;

private String nombre;

public String getNombre() {


return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public List<SelectItem>getListaNombres() {

listaNombres= new ArrayList<SelectItem>();


listaNombres.add(new SelectItem("1","nombre1"));
listaNombres.add(new SelectItem("2","nombre2"));
listaNombres.add(new SelectItem("2","nombre3"));
returnlistaNombres;
}

Construidos!!todos!los!elementos,!podemos!cargar!la!pgina!y!seleccionar!un!elemento!
de!la!lista.Despus,!pulsamos!el!boton!que!dispone!de!un!atributo!action.!

Cdigo!20.13:!(formularioSeleccion.xhtml)!

<h:commandButton id="submit" action="resultadoLista"value="Aceptar"/>

Este! atributo! se! encarga! de! redirigirnos! a! la! pgina! de! destino! denominada!
resultadoLista.xhtml!que!se!muestra!a!continuacin:!!

349
Arquitectura*Java!

Podemos!ver!cmo!se!muestra!el!valor!del!elemento!que!seleccionamos!previamente.!
Seguidamente!se!muestra!el!cdigo!de!la!pagina!de!destino.!

Cdigo!20.14:!(formularioSeleccion.xhtml)!

<htmlxmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:viewcontentType="text/html; charset=iso-8859-1"/>
<head><title>RespuestaLista</title></head>
<body>
<h:form id="formularioRespuesta">
<h2>Hola, #{usuarioBeanLista.nombre}</h2>
<h:commandButton id="volver" value="volver" action="formularioSeleccion" />
</h:form>
</body>
</html>

Hemos!terminado!de!ver!como!construir!un!desplegable!con!JSF!y!cargarlo!con!datos,!
concretamente! con! elementos! del! tipo! SelectItem.! Es! momento! de! avanzar! un! poco!
ms!y!ver!cmo!construir!una!tabla!:!el!ltimo!elemento!que!necesitamos.!

5. Crear!Tabla!con!JSF!

Vamos! a! ! construir! una! tabla! y! cargarla! de! datos! usando! la! tecnologa! JSF.! Para! ello!
vamos!a!apoyarnos!!en!el!concepto!de!usuario!(nombre,!edad)!.!La!tabla!que!aparecer!
ser!algo!similar!a!lo!siguiente:!

Una!vez!que!tenemos!claro!como!ha!de!ser!la!tabla,!vamos!a!ver!el!cdigo!fuente!de!la!
pgina!TablaUsuarios.xhtm.!
350
www.arquitecturajava.com!

Cdigo!20.15:!(TablaUsuarios.xhtml)!

<htmlxmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:viewcontentType="text/html"/>
<body>
<h:form>
<h:dataTable id="tabla"value="#{tablaUsuarioBean.usuarios}" var="usuario">
<h:column>
<h:outputTextvalue="#{usuario.nombre}"/>,
<h:outputTextvalue="#{usuario.edad}"/>
</h:column>
</h:dataTable>
</h:form>
</body>
</html>

Elaborada! la! pagina! JSF,! vamos! a! construir! los! dos! elementos! que! necesitamos! para!
cargar! la! tabla! de! datos:! una! clase! usuario! y! un! ManagedBean! que! nos! devuelva! una!
lista!de!ellos!.Vamos!a!ver!el!cdigo!fuente!de!cada!uno:!

Cdigo!20.16:!(TablaUsuarios.xhtml)!

package com.arquitectura.beans;
public class Usuario {
private String nombre;
private int edad;
public Usuario(String nombre, int edad) {
super();
this.nombre = nombre;
this.edad = edad;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public int getEdad() {
return edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
}
!

351
Arquitectura*Java!

Cdigo!20.17:!(TablaUsuarioBean)!

//omitimos imports
@ManagedBean
public class TablaUsuarioBean {

private List<Usuario> usuarios;

public void setUsuarios(List<Usuario> usuarios) {


this.usuarios=usuarios;
}

public List<Usuario> getUsuarios() {


return usuarios;
}

@PostConstruct
public void iniciar() {
Usuario u= new Usuario("pedro",25);
Usuario u1= new Usuario("crhistina",30);
usuarios = new ArrayList<Usuario>();
usuario.add(u);
usuario.add(u1);

}
}

Como! podemos! ver! el! cdigo! del! mtodo! iniciar()! se! encarga! de! rellenar! la! lista! de!
usuarios!que!necesitaremos!en!la!tabla!haciendo!uso!de!la!anotacin!@PostConstruct!
que!define!que!mtodo!ejecutar!una!vez!creado!el!ManagedBean.!Visto!cmo!construir!
tres! de! los! elementos! bsicos! necesarios! para! nuestra! aplicacin,! podremos! en! el!
siguiente!captulo!abordar!la!migracin!de!nuestra!aplicacin!!a!JSF.!

Resumen!
En!este!captulo!no!hemos!avanzado!en!el!a!diseo!de!la!arquitectura!de!la!aplicacin!
pero! hemos! presentado! una! tecnologa! que! pertenece! a! los! estndares! JEE! y! que!
usaremos!en!el!prximo!captulo!para!simplificar!la!aplicacin!.!

352
www.arquitecturajava.com!

353
Arquitectura*Java!

21.Migracin+a+Java+Server+Faces!

En!el!captulo!anterior!hemos!realizado!una!breve!introduccin!a!JSF!ya!que!se!trata!de!
un!framework!de!capa!de!presentacin!que!tiene!cierta!complejidad!.En!este!captulo!
vamos!a!hacer!migrar!nuestra!aplicacin!a!JSF.!Para!ello!necesitaremos!eliminar!algunas!
clases!!construidas!anteriormente!y!agregar!otras!nuevas.!!

Objetivos:!

Usar!JSF!como!framework!de!presentacin!en!nuestra!aplicacin.!

Tareas:!

1. Aadir!controlador!de!JSF!y!eliminar!el!existente!con!sus!acciones.!
2. Crear!un!ManagedBean!
3. Crear!la!pagina!MostrarLibros.xhtml!
4. Borrar!Libro!
5. Insertar!Libro!
6. Editar!Libro!
7. Filtrar!lista!de!Libros!
8. Mejora!Expression!Language!
9. Integracin!Spring!
!
!

354
www.arquitecturajava.com!

1. Aadir!controlador!de!JSF!y!eliminar!el!existente!

Hasta! este! momento! hemos! usado! un! controlador! construido! por! nosotros! mismos!
para!gestionar!todo!el!flujo!de!la!capa!de!presentacin.!A!partir!de!estos!momentos!no!
nos!ser!necesario!ya!que!como!hemos!visto!en!el!captulo!anterior,!JSF!nos!provee!de!
un!controlador!propio.!As!pues!nuestro!primer!paso!a!la!hora!de!migrar!la!aplicacin!a!
JSF!es!eliminar!el!cdigo!del!controlador!existente!mostrado!a!continuacin.!

Cdigo!22.1!(web.xml)!

<servlet>
<description></description>
<display-name>ControladorLibros</display-name>
<servlet-name>ControladorLibros</servlet-name>
<servlet-class>com.arquitecturajava.aplicacion.controlador.ControladorLibros</servlet-
class>
</servlet>
<servlet-mapping>
<servlet-name>ControladorLibros</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

Eliminado! este! controlador,! instalaremos! como! en! el! captulo! anterior! las! libreras! de!
JSF!en!la!carpeta!lib!y!aadiremos!el!controlador!de!JSF!a!nuestro!web.xml!(ver!imagen)!

Cdigo!22.2:!(web.xml)!

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>

Una! vez! eliminado! el! controlador! antiguo! y! creado! uno! nuevo,! se! presenta! otro!
problema:! a! nivel! de! nuestro! cdigo! fuente! el! controlador! antiguo! gestionaba! un!
conjunto!de!acciones!(ver!imagen).!

355
Arquitectura*Java!

Es! en! estas! acciones! donde! se! encuentra! ubicada! la! lgica! que! liga! la! capa! de!
presentacin! con! la! capa! de! negocio! y! persistencia.! Si! revisamos! estas! acciones! en!
profundidad,! observaremos! que,! para! las! pocas! que! hemos! diseado,! muchas!
comparten!cdigo,!como!es!el!caso!de!ModificarLibroAccion!y!InsertarLibroAccion,!que!
gestionan! las! mismas! variables! y! no! cumplen! con! el! principio! DRY,! ! ya! que! gestionan!
variables!idnticas!de!la!misma!forma!(ver!imagen)!

!De! ! la! misma! forma! que! hemos! substituido! un! controlador! por! otro,! es! momento! de!
substituir!un!conjunto!de!acciones!por!un!ManagedBean!!(ver!imagen)!

356
www.arquitecturajava.com!

As! pues! una! vez! eliminado! el! controlador! y! las! acciones! de! nuestra! aplicacin,! la!
estructura!de!paquetes!a!nivel!de!capa!de!presentacin!ser!la!siguiente.!!

Es!evidente!que!han!sido!eliminados!los!paquetes!relacionados!con!el!controlador!y!las!
acciones! y! nicamente! se! ha! aadido! un! nuevo! paquete! denominado! beans,! que!
contiene!un!nicoManagedbean!debido!a!reducido!tamao!de!nuestra!aplicacin.!!

Antes!de!crear!nuestro!ManagedBean!debemos!recordar!que!esta!clase!es!la!que!hace!
las!funciones!de!nexo!con!la!capa!de!servicios!y!por!lo!tanto!con!toda!la!infraestructura!
que!hemos!diseado!con!Spring!framework.!As,!el!primer!paso!que!debemos!dar!es!ver!
cmo!podemos!configurar!el!framework!de!JSF!para!que!pueda!hacer!uso!de!Spring.!En!
principio! no! hace! falta! realizar! ninguna! operacin! especial! y! lo! configurado!
anteriormente! valdr.! Ahora! bien,! cuando! construyamos! el! ManagedBean! debemos!

357
Arquitectura*Java!

tener!en!cuenta!que!hacemos!uso!de!Spring!!a!la!hora!de!ligar!la!capa!de!servicios!con!l!
de!una!forma!orientada!a!JSF.!

2. Creacin!ManagedBean!

Como!vimos!en!el!captulo!anterior,!construir!un!managedBean!no!es!algo!complicado.!
Simplemente! deberemos! usar! la! anotacin! @ManagedBean! .No! obstante,! el!
ManagedBean! que! nosotros! vamos! a! construir! almacenar! toda! la! funcionalidad!
ubicada!en!las!distintas!acciones!en!una!sola!clase!(ver!imagen).!

A! continuacin! se! muestra! el! codigo! fuente! ! de! esta! clase,! que! tiene! un! mbito! de!
sesin! que! en! nuestro! caso! es! lo! mas! cmodo! debido! al! tamao! de! la! aplicacin!
(pequea),! as! estar! accesible! siempre.! Aunque! tenemos! que! tener! claro! que! abusar!
de!este!tipo!de!mbito!puede!producir!problemas!importantes!de!escalabilidad!.!En!el!
manejo!de!JSF!es!clave!trabajar!de!forma!correcta!con!los!distintos!mbitos.!

358
www.arquitecturajava.com!

Cdigo!22.3:!(FormularioLibroManagedBean.java)!

//omitimos imports
@ManagedBean
@SessionScoped
public class FormularioLibroManagedBean {

private String isbn;


private String titulo;
private String categoria;
private List<SelectItem> listaDeCategorias;
private List<Libro> listaDeLibros;

public List<Libro> getListaDeLibros() {

return listaDeLibros;
}

@PostConstruct
public void iniciar() {

listaDeLibros = getServicioLibros().buscarTodosLosLibros();

List<Categoria> categorias = getServicioLibros()


.buscarTodasLasCategorias();
listaDeCategorias = new ArrayList<SelectItem>();
for (Categoria categoria : categorias) {
listaDeCategorias.add(new SelectItem(categoria.getId(),
..categoria.getDescripcion()));
}

public void setListaDeLibros(List<Libro> listaDeLibros) {


this.listaDeLibros = listaDeLibros;
}

public List<SelectItem> getListaDeCategorias() {

return listaDeCategorias;
}

public void setListaDeCategorias(List<SelectItem> listaDeCategorias) {


this.listaDeCategorias = listaDeCategorias;
}

public String getIsbn() {


return isbn;

359
Arquitectura*Java!

public void setIsbn(String isbn) {


this.isbn = isbn;
}

public String getTitulo() {


return titulo;
}

public void setTitulo(String titulo) {


this.titulo = titulo;
}

public String getCategoria() {


return categoria;
}

public void setCategoria(String categoria) {


this.categoria = categoria;
}

public void insertar(ActionEvent evento) {

getServicioLibros().insertarLibro(
new Libro(isbn, titulo, new Categoria(Integer
.parseInt(categoria))));
setListaDeLibros(getServicioLibros().buscarTodosLosLibros());
categoria="0";
}

public void borrar(ActionEvent evento) {

UIComponent componente = (UIComponent) evento.getComponent();


String isbn = componente.getAttributes().get("isbn").toString();
getServicioLibros().borrarLibro(new Libro(isbn));
setListaDeLibros(getServicioLibros().buscarTodosLosLibros());

public void filtrar(ValueChangeEvent evento) {

int idCategoria = Integer.parseInt(evento.getComponent()


.getAttributes().get("value").toString());

if(idCategoria!=0) {

setListaDeLibros(getServicioLibros().

360
www.arquitecturajava.com!

buscarLibrosPorCategoria(new Categoria(idCategoria)));
}else {

setListaDeLibros(getServicioLibros().
buscarTodosLosLibros());
}
}

public void editar(ActionEvent evento) {

UIComponent componente = (UIComponent) evento.getComponent();


Libro libro = getServicioLibros().buscarLibroPorISBN(
componente.getAttributes().get("isbn").toString());
isbn = libro.getIsbn();
titulo = libro.getTitulo();
}
public void formularioInsertar(ActionEvent evento) {
isbn = "";
titulo = "";
}
public void salvar(ActionEvent evento) {
getServicioLibros().salvarLibro(
new Libro(isbn, titulo, new Categoria(Integer
.parseInt(categoria))));
setListaDeLibros(getServicioLibros().buscarTodosLosLibros());
categoria="0";
}
public ServicioLibros getServicioLibros() {
ApplicationContext contexto = FacesContextUtils

.getWebApplicationContext(FacesContext.getCurrentInstance());
return (ServicioLibros) contexto.getBean("servicioLibros");
}
}
!

Como! podemos! ver,! el! ManagedBean! que! hemos! construido! tiene! bastante! cdigo!
mucho! del! cul! todava! no! hemos! explicado! .! Vamos! a! ir! comentando! los! distintos!
bloques! segn! los! vayamos! necesitando.! En! primer! lugar! vamos! a! hablar! del! mtodo!
getServicioLibros()!cuyo!cdigo!mostramos!a!continuacin.!

!
361
Arquitectura*Java!

Cdigo!22.4:!(FormularioLibroManagedBean.java)!

public ServicioLibros getServicioLibros() {


ApplicationContext contexto = FacesContextUtils
.getWebApplicationContext(FacesContext.getCurrentInstance());
return (ServicioLibros) contexto.getBean("servicioLibros");
}
!

Este! mtodo! es! el! que! se! encarga! de! cargar! todos! los! beans! a! nivel! de! framework!
Spring! y! ponerlos! a! disposicin! de! JSF.! Una! vez! configurado! el! framework! Spring,!
podemos! invocar! a! la! clase! ServicioLibros! y! ejecutar! los! distintos! mtodos,! como! por!
ejemplo! getLibros()! y! getCategorias().! Esta! operacin! la! realizaremos! a! travs! del!
mtodo!iniciar,!que!se!encargar!de!que!la!propiedad!listaDeLibros!y!listaDeCategorias!
se! rellenen! de! forma! correcta! .! A! continuacin! se! muestra! el! cdigo! fuente! de! este!
mtodo:!

Cdigo!22.5:!(FormularioLibroManagedBean.java)!

@PostConstruct
public void iniciar() {
listaDeLibros = getServicioLibros().buscarTodosLosLibros();
List<Categoria> categorias = getServicioLibros()
.buscarTodasLasCategorias();
listaDeCategorias = new ArrayList<SelectItem>();
for (Categoria categoria : categorias) {
listaDeCategorias.add(new SelectItem(categoria.getId(),
categoria.getDescripcion()));
}
}
!

!Vamos!a!crear!seguidamente!la!pgina!MostrarLibros.xhml!y!ver!cmo!se!apoya!en!las!
variables!que!hemos!asignado!en!el!constructor.!

3. Crear!MostrarLibro.xhtml!

En! el! captulo! anterior! hemos! visto! cmo! podemos! construir! una! pagina! JSF! que! sea!
capaz!de!mostrar!una!lista!de!personas.En!cuanto!a!nuestra!aplicacin,!se!trata!de!un!
ejemplo!similar!en!el!cul!debemos!mostrar!una!lista!de!libros!.Para!ello!el!cdigo!que!
construiremos!!ser!el!siguiente,!que!se!apoya!completamente!en!JSF.!

362
www.arquitecturajava.com!

Cdigo!22.6:!(MostrarLibro.xhtml.)!

<htmlxmlns=http://www.w3.org/1999/xhtml xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view>
<body>
<h:form>
<h:selectOneMenu id="combo"
valueChangeListener="#{formularioLibroManagedBean.filtrar}"
value="#{formularioLibroManagedBean.categoria}" onchange="submit()">
<f:selectItemitemValue="0" itemLabel="seleccionar" />
<f:selectItems
value="#{formularioLibroManagedBean.listaDeCategorias}" />
</h:selectOneMenu>
<h:dataTable id="tabla"
value="#{formularioLibroManagedBean.listaDeLibros}"
var="libro">
<h:column>
#{libro.isbn}
</h:column>
<h:column>
#{libro.titulo}
</h:column>
<h:column>
#{libro.categoria.descripcion}
</h:column>
<h:column>
<h:commandLinkvalue="borrar"
actionListener="#{formularioLibroManagedBean.borrar}" >
<f:attributename="isbn" value="#{libro.isbn}" />
</h:commandLink>
</h:column>
<h:column>
<h:commandLinkvalue="editar"
actionListener="#{formularioLibroManagedBean.editar}"
action="FormularioEditarLibro">
<f:attributename="isbn" value="#{libro.isbn}" />
</h:commandLink>
</h:column>
</h:dataTable>
<h:commandButton
actionListener="#{formularioLibroManagedBean.formularioInsertar}"
action="FormularioInsertarLibro" value="insertar"/>
</h:form>
</body>
</f:view>
</html>

363
Arquitectura*Java!

Una!vez!tenemos!el!cdigo!de!la!pagina!MostrarLibros.xhml!vamos!a!comentar!algunas!
de!las!lneas!como!la!siguiente.!

Cdigo!22.6:!(MostrarLibro.xhtml.)!

<f:selectItems value="#{formularioLibroManagedBean.listaDeCategorias}" />


!

Esta! linea! de! encarga! de! cargar! el! combo! de! categorias! con! la! lista! de! categoras! que!
nos!devuelve!nuestro!managedBean.!Algo!similar!hace!la!siguiente!lnea!

Cdigo!22.7:!(MostrarLibro.xhtml)!

<h:dataTable id="tabla"
value="#{formularioLibroManagedBean.listaDeLibros}"
var="libro">

Que! se! encarga! de! cargar! la! lista! de! libros! a! travs! del! managedBean.! Una! vez! que!
tenemos! ambas! colecciones! cargadas! JSF! nos! mostrara! la! siguiente! pgina! al! solicitar!
MostrarLibros.xhtml.!

Por! ahora! nicamente! hemos! comentado! la! funcionalidad! que! se! encarga! de! cargar!
correctamente!los!datos!en!la!pagina!.Sin!embargo!no!hemos!cubierto!todava!el!botn!
de! insertar! ni! los! links! de! editar! y! borrar.! Vamos! a! ir! avanzando! con! estos! elementos!
poco!a!poco.!

364
www.arquitecturajava.com!

4. Borrar!Libro!

Si! revisamos! el! cdigo! de! la! pagina! MostrarLibros.xhtml! nos! encontraremos! con! lo!
siguiente.!

Cdigo!22.7:!(MostrarLibro.xhtml)!

<h:commandLink value="borrar"
actionListener="#{formularioLibroManagedBean.borrar}">
<f:attribute name="isbn"value="#{libro.isbn}" />
</h:commandLink>

Este! control! de! JSF! es! un! control! de! tipo! CommandLink! o! enlace! se! encargar! de!!
invocar! a! nuestro! managedBean! y! ejecutara! el! mtodo! borrar.! Una! vez! ejecutado,!
volver! a! cargar! la! misma! pgina.! Vamos! a! mostrar! a! continuacin! el! cdigo! de! la!
funcin!borrar!de!nuestro!managedBean.!

Cdigo!22.8:!(FormularioLibroManagedBean.xhtml)!

public void borrar(ActionEvent evento) {


UIComponent componente = (UIComponent) evento.getComponent();
String isbn = componente.getAttributes().get("isbn").toString();
getServicioLibros().borrarLibro(new Libro(isbn));
setListaDeLibros(getServicioLibros().buscarTodosLosLibros());
}

Este!mtodo!se!encarga!primero!de!obtener!el!componente!que!lo!!invoc,!en!este!caso!
es! un! CommandLink! ,componente! que! extiende! de! UIComponent.! Una! vez! que!
tenemos!el!componente!accedemos!a!su!coleccin!de!atributos!y!obtenemos!el!isbn!del!
Libro.! Hecho! esto! disponemos! del! isbn! e! invocamos! al! mtodo! borrar! de! la! clase!
ServicioLibros!y!borramos!el!registro!de!la!base!de!datos!.Por!ultimo!volvemos!a!cargar!
la!nueva!lista!de!libros.!

Acabamos!de!ver!como!nuestra!aplicacin!usa!JSF!para!mostrar!y!eliminar!registros!es!
momento! de! seguir! cubriendo! funcionalidad! y! ver! como! implementar! la! lgica! de!
insercin!de!libros!a!travs!de!JSF.!

365
Arquitectura*Java!

5. Insercin!Libro!

Para! realizar! la! tarea! de! insercin! debemos! apoyarnos! en! el! cdigo! que! hemos!
construido!en!la!pagina!MostrarLibros.xhtml.!En!esta!pgina!disponemos!de!un!botn!
de!insercin!del!cul!a!continuacin!mostramos!su!cdigo.!

Cdigo!22.9:!(MostrarLibros.xhtml)!

<h:commandButton actionListener="#{formularioLibroManagedBean.formularioInsertar}"
action="FormularioInsertarLibro" value="insertar"/>

Como!podemos!ver,!el!funcionamiento!del!botn!es!muy!sencillo:!simplemente!usa!el!
atributo! action! para! redirigirnos! a! otra! pgina! JSF,! en! concreto! la! pgina!
FormularioInsertarLibro.xhtml,! ejecutando! previamente! el! evento! formularioInsertar.!
Este!sencillo!evento!nicamente!se!encarga!de!vaciar!las!variables!isbn!y!titulo!como!se!
muestra!a!continuacin.!

Cdigo!22.10:!(MostrarLibros.xhtml)!

public void formularioInsertar(ActionEvent evento) {


isbn = "";titulo = "";
}

Una!vez!realizada!esta!operacin!al!pulsar!el!botn!pasaremos!a!la!pgina!que!muestra!
el!formulario!para!insertar!un!nuevo!libro.!A!continuacin!mostramos!tanto!!la!pgina!
como!su!cdigo!fuente.!

366
www.arquitecturajava.com!

Cdigo!22.11:!(FormularioInsertarLibro.xhtml)!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:viewcontentType="text/html" />
<h:head>
<title>FormularioInsertarLibro</title>
</h:head>
<h:bodybgcolor="white">
<h:form>
<p>
<labelfor="isbn">ISBN:</label>
<h:inputText id="isbn" value="#{formularioLibroManagedBean.isbn}" />
</p>
<p>
<labelfor="titulo">Titulo:</label>
<h:inputText id="titulo" value="#{formularioLibroManagedBean.titulo}" />
</p>
<p><labelfor="categoria">Categoria :</label>
<h:selectOneMenu id="categoria"
value="#{formularioLibroManagedBean.categoria}">

<f:selectItemsvalue="#{formularioLibroManagedBean.listaDeCategorias}" />
</h:selectOneMenu>
</p>
<h:commandButton id="submit"
actionListener="#{formularioLibroManagedBean.insertar}" action="MostrarLibros"
value="Insertar" />
</h:form>
</h:body>
</html>

Como! podemos! ver,! la! pgina! de! FormularioInsertarLibro! comparte! el! mismo! combo!
con!la!pgina!de!MostrarLibros.xhtml!y!por!lo!tanto!invoca!la!misma!funcin!de!nuestro!
managedBean.!Una!vez!cargada!esta!pgina,!vamos!!comentar!cmo!funciona!la!lgica!
del!botn!de!insertar!que!!se!muestra!a!continuacin.!

!
367
Arquitectura*Java!

Cdigo!22.12:!(FormularioInsertarLibro.xhtml)!

<h:commandButton
id="submit"actionListener="#{formularioLibroManagedBean.insertar}"
action="MostrarLibros"value="Insertar" />

Este!botn!invocar!la!funcin!insertar!!de!nuestro!managedBean,!insertando!!un!nuevo!
registro! en! la! tabla! y! volviendo! a! seleccionar! la! lista! de! libros.! Hecho! esto,! el! action!
MostrarLibros! nos! redirigir! otra! vez! a! la! lista.! Vamos! a! ver! el! cdigo! del! mtodo!
insertar!!

Cdigo!22.13:!(FormularioInsertarLibro.xhtml)!

public void insertar(ActionEvent evento) {


getServicioLibros().insertarLibro(
new Libro(isbn, titulo, new Categoria(Integer
.parseInt(categoria))));
setListaDeLibros(getServicioLibros().buscarTodosLosLibros());
categoria="0";}

Nuestro! mtodo! se! apoya! en! las! capacidades! que! tiene! JSF! de! mapeo! de! etiquetas! a!
propiedades!de!los!ManagedBeans!!y!se!encarga!de!insertar!el!registro!en!la!base!datos.!
Una! vez! hecho! esto,! vuelve! a! seleccionar! la! nueva! lista! de! libros! y! nos! redirige! a! la!
pagina!MostrarLibros.xhtml,!!mostrndonos!la!lista!con!el!nuevo!libro!insertado.!!

6. Funcionalidad!de!Edicin!

Vamos!a!ver!en!la!pgina!MostrarLibros.xhtml!cul!es!el!cdigo!fuente!que!nos!enlaza!
con!la!funcionalidad!de!edicin.!!

Cdigo!22.14:!(FormularioInsertarLibro.xhtml)!

<h:column>
<h:commandLinkvalue="editar"
actionListener="#{formularioLibroManagedBean.editar}"
action="FormularioEditarLibro">
<f:attributename="isbn" value="#{libro.isbn}" />
</h:commandLink>
</h:column>

368
www.arquitecturajava.com!

Ya! conocemos! algunos! atributos! a! nivel! de! commandLink,! concretamente! el! atributo!
action!que!nos!redirigir!a!la!pgina!FormularioEditarLibro.xhtml!.Ahora!bien,!antes!de!
redirigirnos!se!ejecuta!el!evento!actionListener!que!invoca!la!funcin!de!editar.!Vamos!a!
ver!el!cdigo!fuente!de!este!mtodo:!

Cdigo!22.15:!(FormularioLibroManagedBean.java)!

public void editar(ActionEvent evento) {


UIComponent componente = (UIComponent) evento.getComponent();
Libro libro = getServicioLibros().buscarLibroPorClave(
componente.getAttributes().get("isbn").toString());
isbn = libro.getIsbn();
titulo = libro.getTitulo();
}

Es!evidente!que!este!mtodo!carga!en!el!managedBean!los!datos!relativos!al!Libro!que!
vamos! a! editar,! para! ello! busca! por! clave! el! libro! apoyndose! en! el! atributo! isbn! del!!
commandLink.! Una! vez! realizado! esto,! se! muestra! el! formulario! de! edicin! con! los!
datos!cargados!(ver!imagen).!

Vamos!a!ver!el!cdigo!fuente!de!este!fichero!!

369
Arquitectura*Java!

Cdigo!22.16:!(FormularioEditarLibro.xhtml)!

<!omitimos doctype!
<f:view contentType="text/html" />
<h:head>
<title>Hello World!</title>
</h:head>
<h:body bgcolor="white">
<h:form >
<p>
<label for="isbn">ISBN:</label>
<h:inputText id="isbn" value="#{formularioLibroManagedBean.isbn}" />
</p>
<p>
<label for="titulo">Titulo:</label>
<h:inputText id="titulo" value="#{formularioLibroManagedBean.titulo}" />
</p>
<p><label for="categoria">Categoria :</label>
<h:selectOneMenu id="categoria"
.value="#{formularioLibroManagedBean.categoria}">
<f:selectItems
value="#{formularioLibroManagedBean.listaDeCategorias}" />
</h:selectOneMenu>
</p>

<h:commandButton id="submit"
..actionListener="#{formularioLibroManagedBean.salvar}"
..action="MostrarLibros" value="Salvar" />
</h:form>
</h:body>
</html>
!

Visto!esto,!nicamente!nos!queda!por!clarificar!cmo!se!encarga!esta!pgina!de!guardar!
la! informacin! .Para! ello,! el! commandButton! de! la! pgina! se! encarga! de! invocar! al!
mtodo!salvar.!

Cdigo!22.17:!(FormularioInsertarLibro.xhtml)!

<h:commandButton id="submit" actionListener="#{formularioLibroManagedBean.salvar}"


action="MostrarLibros" value="Salvar" />

!
370
www.arquitecturajava.com!

A!continuacin!se!muestra!el!cdigo!fuente!de!este!mtodo:!

Cdigo!22.18:!(FormularioLibroManagedBean.java)!

public void salvar(ActionEvent evento) {


getServicioLibros().salvarLibro(
new Libro(isbn, titulo, new Categoria(Integer
.parseInt(categoria))));
setListaDeLibros(getServicioLibros().buscarTodosLosLibros());
categoria="0";
}
!

Este!mtodo!localiza!la!categora!del!Libro!y!se!la!asigna!a!un!nuevo!libro!que!es!el!que!
salvamos!en!la!base!de!datos.!Por!ultimo!nos!queda!implementar!de!forma!correcta!la!
funcionalidad!de!Filtrar.!

7. Filtrar!por!categorias!

Vamos!a!modificar!el!combo!que!tenemos!construido!con!JSF!para!que!permita!realizar!
operaciones!de!filtrado.!Vase!el!nuevo!cdigo!fuente!de!este!combo:!

Cdigo!22.19:!(MostrarLibros.xhtml)!

<h:selectOneMenu id="combo"
valueChangeListener="#{formularioLibroManagedBean.filtrar}"
value="#{formularioLibroManagedBean.categoria}" onchange="submit()">
<f:selectItem itemValue="0" itemLabel="seleccionar" />
<f:selectItems
value="#{formularioLibroManagedBean.listaDeCategorias}" />
</h:selectOneMenu>
!

Hemos! visto! que! se! han! aplicado! varios! cambios! .En! primer! lugar! se! ha! aadido! un!
nuevo!item!denominado!Todas!(ver!cdigo)!

Cdigo!22.20:!(MostrarLibros.xhtml)!

<f:selectItemitemValue="0"itemLabel="Todas"/>
!

Este!elemento!permite!que!en!el!combo!se!puedan!seleccionar!todas!las!categoras!.!
Realizada! esta! operacin,! se! ha! aadido! ! el! atributo! valueChangeListener! que! define!
qu!funcin!se!ejecutar!cuando!el!valor!del!combo!cambie.!En!este!caso!la!funcin!se!
denomina!filtrar!y!est!a!nivel!de!nuestro!ManagedBean.!
371
Arquitectura*Java!

Por!ltimo,!usaremos!javascript!para!enviar!los!datos!del!formulario!al!!servidor!a!travs!
del!mtodo!onchange().!A!continuacin!se!muestra!una!imagen!del!filtro!en!ejecucin.!

Una! vez! hechos! estos! cambios,! tenemos! completamente! implementada! la!


funcionalidad!de!JSF!en!nuestra!aplicacin!.Es!momento!de!afrontar!algunas!tareas!ms!
orientadas!al!refactoring.!

8. Mejoras!Expression!Language!2.0!

El! primer! refactoring! que! vamos! a! aplicar! es! el! hacer! uso! de! expresin! language! en!
nuestra! pagina! JSF! 2.0! de! MostrarLibros.xhtml.! Para! ello! hay! que! registrar! un! listener!
especial! en! el! fichero! facestconfig.xml! que! hasta! este! momento! no! hemos!
utilizado.Vamos!a!ver!el!codigo!de!ste:!

Cdigo!22.23:!(MostrarLibros.xhtml)!

<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
!

Como! hemos! visto! en! ejemplos! anteriores! hay! bloques! de! cdigo! que! son! difciles! de!
entender,!concretamente!los!relacionados!con!los!links.!Vamos!a!verlo:!!

!
372
www.arquitecturajava.com!

Cdigo!22.24:!(MostrarLibros.xhtml)!

<h:column>
<h:commandLink value="borrar"
actionListener="#{formularioLibroManagedBean.borrar}" >
<f:attribute name="isbn" value="#{libro.isbn}" />
</h:commandLink>
</h:column>
<h:column>
<h:commandLink value="editar"
actionListener="#{formularioLibroManagedBean.editar}"
action="FormularioLibro">
<f:attribute name="isbn" value="#{libro.isbn}" />
</h:commandLink>
</h:column>
!

Podemos! simplificar! cada! uno! de! estos! elementos! apoyndonos! en! expressionl!
anguage!de!tal!forma!que,!a!partir!de!ahora,!estos!enlaces!quedaran!definidos!de!una!
forma! ms! sencilla! ya! que! ! el! expresin! language! permite! a! partir! de! la! versin! 2.0!
invocar!mtodos!que!reciban!parmetros.!Vase!el!nuevo!bloque!de!cdigo:!

Cdigo!22.25:!(MostrarLibros.xhtml)!

<h:column>
<h:commandLinkvalue="editar"
actionListener="#{formularioLibroManagedBean.editar(libro.isbn)}"
action="FormularioLibro">
</h:commandLink>
</h:column>
<h:column>
<h:commandLinkvalue="borrar"
actionListener="#{ formularioLibroManagedBean.borrar(libro.isbn)}"
action="MostrarLibro">
</h:commandLink>
</h:column>
!

Una! vez! modificado! el! cdigo,! realizamos! una! invocacin! directa! desde! ! la! pgina!
MostrarLibros.xhtml!!a!los!mtodos!del!ManagedBean.!Vamos!cmo!quedan!stos:!

373
Arquitectura*Java!

Cdigo!22.26:!(FormularioLibrosManagedBean.java)!

public void borrar(String isbn) {

getServicioLibros().borrarLibro(new Libro(isbn));
setListaDeLibros(getServicioLibros().buscarTodosLosLibros());
}
public void editar(String isbn) {

Libro libro = getServicioLibros().buscarLibroPorISBN(isbn);


isbn = libro.getIsbn();
titulo = libro.getTitulo();
}
!

Es!evidente!que!es!mucho!ms!sencillo!trabajar!de!esta!forma.!

9. Integracin!de!Spring!

Quiz! el! nico! elemento! que! no! acaba! de! encajar! en! la! integracin! con! el! framework!
Spring! y! JSF! es! el! siguiente! bloque! de! cdigo! que! tenemos! a! nivel! de! nuestro!
managedBean!y!que!se!encarga!de!enlazar!JSF!y!Spring.!

Cdigo!22.27:!(FormularioLibrosManagedBean.java)!

public ServicioLibros getServicioLibros() {


ApplicationContext contexto = FacesContextUtils
.getWebApplicationContext(FacesContext.getCurrentInstance());
return (ServicioLibros) contexto.getBean("servicioLibros");
}
!

Para! simplificar! este! bloque! de! cdigo,! es! necesario! usar! la! anotacion!
@ManagedProperty! e! inyectar! el! servicio! de! forma! directa! como! a! continuacin! se!
muestra.!

Cdigo!22.28!(FormularioLibrosManagedBean.java)!

@ManagedProperty("#{servicioLibros}")
private ServicioLibros servicioLibros;
!

ste!es!el!ltimo!paso!en!cuando!a!las!modificaciones!de!JSF!se!refiere!y!su!integracin!
con!Spring!Framework.!!

374
www.arquitecturajava.com!

10. JSF!2!y!Business!Objects!

Una!de!las!pocas!cosas!que!no!termina!de!encajar!en!el!ejemplo!de!JSF!es!este!bloque!
de!cdigo.!

Cdigo!22.29!(FormularioLibrosManagedBean.java)!

@PostConstruct
public void iniciar() {
listaDeLibros = getServicioLibros().buscarTodosLosLibros();
List<Categoria> categorias = getServicioLibros()
.buscarTodasLasCategorias();
listaDeCategorias = new ArrayList<SelectItem>();
for (Categoria categoria : categorias) {
listaDeCategorias.add(new SelectItem(categoria.getId(),
categoria.getDescripcion()));
}
}
!

Es!evidente!que!sera!mucho!mas!comodo!cargar!en!las!paginas!JSF!objetos!de!negocio!
que!una!lista!de!SelectItems.!Esto!es!posible!a!partir!de!la!version!de!JSF!2.0!que!
permite!definir!los!elementos!selectOneMenu!de!la!siguiente!forma.!
!

Cdigo!22.30!(MostrarLibros.xhtml)!

<h:selectOneMenu value="#{formularioLibroManagedBean.categoria}"">
<f:selectItem itemValue="0" itemLabel="seleccionar" />
<f:selectItems value="#{formularioLibroManagedBean.categorias}" var=categoria
itemLabel=#{categoria.descripcion} itemValue=#{categoria.id} />
</h:selectOneMenu>
!

Resumen!
En! este! captulo! nos! hemos! centrado! en! integrar! JSF! como! tecnologa! en! nuestra!
aplicacin,! eliminando! la! jerarqua! de! acciones! previa! y! creando! un! nico!
ManagedBean! .Evidentemente! una! aplicacin! habitual! tendr! varios! ManagedBean!
pero! siempre! sern! muchos! menos! que! el! grupo! de! acciones! antes! usado.! Por! otra!
parte,! hemos! abordado! la! integracin! con! el! framework! Spring.! An! asi! han! quedado!
muchas!cosas!fuera!como!el!sistema!de!navegacin!o!las!anotaciones!CDI!que!debido!a!
la!extensin!del!capitulo!no!sern!abordadas.!

375
Arquitectura*Java!

23.Servicios)Web!y"JAXeWS!
!

En! el! captulo! anterior! hemos! hecho! migrar! nuestra! aplicacin! a! JSF,! en! estos!
momentos!la!aplicacin!hace!uso!de!JSF,!JPA!y!Spring!utilizando!un!amplio!conjunto!de!
anotaciones.!Es!momento!de!cubrir!algunos!temas!complementarios!como!es!el!uso!de!
servicios! web.! Hoy! en! dia! la! mayor! parte! de! las! aplicaciones! web! que! construimos!
necesitan!acceder!a!informacin!remota!de!la!que!otra!aplicacin!nos!provee!,!o!bien!
necesita! publicar! informacin! para! que! otras! aplicaciones! accedan! a! ella! de! forma!
remota! .Una! de! las! formas! ms! habituales! de! publicar! este! tipo! de! informacin! es! a!
travs!del!uso!de!servicios!web.!En!este!captulo!nos!centraremos!en!integrar!el!uso!de!
esta!tecnologa!en!nuestra!aplicacion.!!

Objetivos:!

Publicar! a! travs! de! un! servicio! web! informacin! de! nuestros! libros! para! que!
aplicaciones!de!terceros!puedan!acceder!a!ella.!

Tareas:

1. Introduccin!!a!la!Programacin!Distribuida.!
2. Introduccin!al!concepto!de!!Servicio!Web.!
3. Creacin!de!un!Servicio!Web!!Bsico!usando!anotaciones.!
4. Publicacin!de!Servicio!Web!
5. Instalacin!de!Apache!CXF.!
6. Configuracin!de!Apache!CXF.!
7. Acceso!al!servicio!web.!

1. Introduccin!!a!programacin!distribuida!

376
www.arquitecturajava.com!

La!programacin!distribuida!viene!a!!aportar!una!solucin!a!un!problema!clsico!de!la!
programacin! orientada! a! objeto:! cmo! ! comunicar! objetos! que! se! encuentran! en!
ubicaciones!fsicas!distintas!.!A!continuacin!se!muestra!un!diagrama!del!problema:!

Como!podemos!ver,!tenemos!dos!objetos!A!y!B!que!necesitan!comunicarse!entre!ellos.!
Sin! embargo! de! entrada! esto! no! es! posible! ya! que! cada! uno! de! ellos! se! encuentra!
ubicado!en!una!mquina!distinta!y!por!lo!tanto!nicamente!pueden!acceder!a!objetos!
ubicados!en!su!misma!maquina!y!proceso.!Para!conseguir!que!estos!dos!objetos!puedan!
intercambiar! informacin! necesitamos! un! diseo! ms! complejo.! Este! diseo! se!
construye! a! travs! del! uso! de! proxies,! patrn! de! diseo! ! que! ya! hemos! visto!
anteriormente!.En!este!caso!se!necesitan!dos!proxies!:!el!proxy!local!y!el!proxy!remoto!
que! se! encargan! de! facilitar! la! comunicacin.! A! continuacin! se! explican!
detalladamente!ambos!conceptos.!

Proxy!Local:!Objeto!que!da!la!sensacin!de!ser!el!objeto!real!al!que!queremos!acceder!!
de! forma! remota! y! que! est! ubicado! en! la! mquina! local! .Se! encarga! de! gestionar! la!
comunicacin!entre!el!objeto!local!y!el!servidor!remoto.!

Proxy!Remoto:!Objeto!que!de!la!sensacin!de!ser!idntico!al!objeto!remoto!y!se!ubica!
en! la! mquina! remota,! gestionando! la! comunicacin! entre! el! proxy! local! y! el! objeto!
remoto.!

377
Arquitectura*Java!

Como!estos!conceptos!pueden!ser!complejos!en!un!primer!momento,!vamos!a!mostrar!
un!diagrama!que!incluye!los!objetos!reales!y!los!proxies.!

De!esta!forma!la!funcionalidad!es!implementada!dando!los!siguientes!pasos!

1. Un!objeto!A!invoca!un!mtodo!del!proxy!local!B!que!se!encuentra!en!su!misma!
mquina.!
2. Una! vez! este! objeto! recibe! la! invocacin,! implementa! la! funcionalidad!
necesaria!para!convertir!esa!invocacin!en!una!llamada!por!red!via!TCP/IP!hacia!
el!proxy!remoto.!
3. Una!vez!el!proxy!remoto!recibe!el!mensaje,!lo!convierte!en!una!peticin!normal!
e! invoca! al! objeto! remoto! que! es! el! que! tiene! la! lgica! de! negocio! a! la! cul!
queramos!acceder.!
4. Este!objeto!remoto!nos!devolver!un!resultado!que!el!proxy!remoto!convertir!
en!una!peticin!TCP!y!lo!enviara!al!proxy!local!
5. El!proxy!local!devolver!esta!informacin!al!objeto!local!
6. El!objeto!local!podr!hacer!uso!de!esta!informacin!!
!
A!continuacin!se!muestra!un!diagrama!aclaratorio:!
!
!

378
www.arquitecturajava.com!

Esta!forma!de!comunicacin!est!soportada!por!varias!plataformas!a!da!de!hoy,!entre!
las!cuales!destacaramos!JAVA!y!.NET!.stas!son!capaces!de!crear!automticamente!los!
proxies! necesarios! de! una! forma! transparente.! En! java! la! comunicacin! distribuida! se!
realiza!a!travs!de!RMI!y!en!.NET!a!travs!de!.NET!Remoting.!Ahora!bien,!!este!tipo!de!
comunicacin! slo! es! vlida! cuando! ambas! maquinas! albergan! la! misma! tecnologa!
(Java!o!NET)!.En!el!caso!de!que!una!maquina!use!Java!y!la!otra!.NET,!la!comunicacin!no!
es!posible!ya!que!los!protocolos!son!distintos!(ver!imagen).!

!
!

Este! tipo! de! problema! es! el! que! los! servicios! web! nos! ayudarn! a! solventar.! A!
continuacin!se!introducen!sus!conceptos.!
379
Arquitectura*Java!

2. Introduccin!a!Servicios!Web!

Como!acabamos!de!ver,!la!comunicacin!entre!.NET!y!Java!no!puede!ser!directa!.!Para!
conseguir! que! dos! plataformas! heterogneas! se! puedan! comunicar,! necesitamos! usar!
un!estndar!que!ambas!entiendan!.Esta!estndar!es!XML!ya!que!tanto!.NET!como!Java!
son!capaces!de!trabajar!con!esta!tecnologa!(ver!imagen).!

Una!vez!que!hemos!decidido!usar!XML!como!tecnologa,!tendremos!que!definir!cul!es!
el! protocolo! de! comunicacin! entre! los! dos! objetos! .Este! protocolo! ya! existe! y! se!
denomina! SOAP! (Simple! Object! Access! Protocol).SOAP! permitir! comunicar! ! dos!
tecnologas!diferentes!usando!XML!como!standard!a!la!hora!de!transferir!informacin!
entre!los!dos!sistemas.!A!continuacin!se!muestra!una!figura!aclaratoria.!

Una! vez! que! entendemos! que! SOAP! es! el! protocolo! de! comunicacin! basado! en! XML!
que!permite!la!transferencia!de!informacin!entre!dos!objetos!creados!en!tecnologas!
distintas,! es! momento! de! hablar! un! poco! ms! en! profundidad! de! la! estructura! de! un!
mensaje!SOAP.!Un!mensaje!SOAP!est!construido!con!etiquetas!XML!y!se!compone!de!
dos!estructuras!principales:!cabecera!y!cuerpo!!(ver!imagen).!

380
www.arquitecturajava.com!

Vamos! a! comentar! a! grosso! modo! cul! es! la! responsabilidad! de! cada! una! de! estas!
partes:!

Cabecera:!Se!encarga!de!definir!conceptos!transversales!al!mensaje,!como!por!
ejemplo!tipo!de!autenticacin.!
Cuerpo:! Se! encarga! de! definir! ! los! mtodos! que! se! van! a! invocar! de! forma!
remota!asi!como!los!tipos!de!datos!asociados!a!estos!mtodos.!

Evidentemente!a!travs!de!SOAP!podemos!realizar!cientos!de!peticiones!hacia!el!mismo!
objeto!y!mismo!mtodo.!Enviaremos!un!mensaje!SOAP!y!nos!ser!devuelto!otro.!Ahora!
bien,!a!la!hora!de!construir!el!mensaje,!debemos!usar!otra!tecnologa!que!se!encarga!de!
definir! cul! es! la! estructura! de! estos! mensajes.! En! programacin! orientada! a! objeto!
cuando! queremos! construir! un! objeto,! tenemos! que! definir! primero! una! clase! (ver!
imagen)!

381
Arquitectura*Java!

Igualmente! que! una! clase! define! cmo! se! construyen! los! distintos! objetos! de! ella,! los!
servicios! web! disponen! de! un! standard! que! define! cmo! han! de! crearse! los! distintos!
mensajes! SOAP! para! un! servicio! web! en! concreto.! Este! standard! se! denomina!
WSDL(Web! ServiceDescriptionLanguage).! A! continuacin! se! muestra! una! imagen!
aclaratoria.

As! pues! a! nivel! de! servicios! web,! el! fichero! WSDL! hace! las! funciones! de! clase! y! los!
mensajes! SOAP! hacen! la! funcin! de! objetos! que! pasan! entre! los! dos! sistemas!
distribuidos!definidos!a!nivel!de!XML.!Una!vez!claros!estos!conceptos,!es!momento!de!
comenzar!a!construir!un!servicio!web.!

3. Servicio!Web!

Una!de!las!ventajas!de!usar!tecnologa!Java!a!la!hora!de!construir!Servicios!Web!es!que!
permite!construir!un!servicio!web!a!partir!de!una!!sencilla!clase!Java!a!travs!del!uso!de!
anotaciones.!Estas!anotaciones!estn!definidas!en!el!estndar!JAXtWS!de!JEE.!Una!vez!
anotemos!la!clase!,JAXtWS!se!encargar!de!construir!los!proxies!y!el!fichero!WSDL!de!
forma! automtica.! Es! momento! de! definir! qu! informacin! queremos! publicar! va!
servicio! web! .En! nuestro! caso! el! servicio! web! a! construir! nos! devolver! una! lista! con!
todos!los!libros!incluyendo!la!siguiente!informacin:!

isbn!
ttulo!
descripcin!de!la!categora!

Si! nos! fijamos,! ninguna! de! nuestras! dos! clases! de! negocio! ! que! en! este! momento!
tenemos!en!nuestra!aplicacin!Libro!y!Categora!incorpora!la!informacin!necesaria.!As!
pues,! vamos! a! construir! una! nueva! clase! que! realice! las! funciones! de! contenedor! de!
informacin! y! encaje! con! los! campos! solicitados.! Estas! clases! se! denominan!
habitualmente! DTO! (Data! Transfer! Objects)! ya! que! son! clases! construidas!
especficamente!para!la!transmisin!de!informacin!entre!dos!sistemas.!

382
www.arquitecturajava.com!

!Los! DTO! o! Data! Transfer! Objects! son! patrones! de! diseo! orientados! a! programacin!
distribuida.!A!continuacin!se!muestra!una!imagen!aclaratoria!que!hace!uso!de!ellos.!

Una!vez!que!tenemos!clara!cul!es!la!funcionalidad!de!esta!clase,!vamos!a!ver!su!cdigo!
fuente.!

Cdigo!23.1:!(LibroDTO.java)!

package com.arquitecturajava.aplicacion.serviciosexternos;

public class LibroDTO {


private String isbn;
private String titulo;
private String categoria;
public LibroDTO() {
}
public LibroDTO(String isbn, String titulo, String categoria) {
super();
this.isbn = isbn;
this.titulo = titulo;
this.categoria = categoria;
}

public String getCategoria() {


return categoria;
}
383
Arquitectura*Java!

public String getIsbn() {


return isbn;
}

public String getTitulo() {


return titulo;
}
public void setCategoria(String categoria) {
this.categoria = categoria;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}

public void setTitulo(String titulo) {


this.titulo = titulo;
}
}
!

Construida! la! clase! que! vamos! a! utilizar! para! transferir! ! la! informacin! entre! ! las! dos!
aplicaciones! (LibroDTO),! es! momento! de! construir! una! clase! de! servicio! que! tenga! un!
mtodo!que!nos!devuelva!una!lista!de!LibroDTO!con!toda!la!informacin!referente!a!los!
libros.!Al!tratarse!de!una!clase!de!servicio!la!denominaremos!ServicioInformacionLibros!
y! al! mtodo! que! nos! devuelve! la! lista! de! LibroDTO! le! denominaremos!
listaInformacionLibros.! Para! construirla! nos! apoyaremos! en! el! uso! de! interfaces! (ver!
imagen)!

384
www.arquitecturajava.com!

Como!podemos!ver,!dispondremos!de!un!interface!ServicioInformacionLibros!y!de!una!
clase! que! lo! implementa.! ! A! continuacin! se! muestra! una! imagen! con! los! paquetes! y!
clases!que!debemos!aadir!al!proyecto!

Una! vez! tenemos! claro! qu! interfaces! y! clases! vamos! a! construir,! es! momento! de!
introducir!un!par!de!anotaciones!adicionales!que!pertenecen!al!estndar!JAXtWS!y!son!
las!encargadas!de!simplificar!la!publicacin!de!servicios!web!en!este!tipo!de!entorno.!

@WebService!:!Anotacin!que!marca!una!clase!como!servicio!web!!
@! WebMethod! :! Anotacin! que! marca! un! mtodo! como! mtodo! publico! a!
nivel!del!servicio!web.!

Vamos!a!usar!a!continuacin!estas!anotaciones!para!crear!un!Servicio!Web!que!cumpla!
con! los! requisitos! que! nosotros! necesitamos.! A! continuacin! se! muestra! el! cdigo!
fuente!de!ste.!

385
Arquitectura*Java!

Cdigo!23.2:!(ServicioInformacionLibrosCXF.java)!

//omitimos imports
@Service
@WebService(endpointInterface="com.arquitecturajava.aplicacion.serviciosextern
os.ServicioInformacionLibros")
public class ServicioInformacionLibrosCXF implements ServicioInformacionLibros{
@Autowired
private ServicioLibros servicioLibros;
@WebMethod
public List<LibroDTO> listaInformacionLibros() {
List<Libro> listaLibros=servicioLibros.buscarTodosLosLibros();
List<LibroDTO> listaDestino= new ArrayList<LibroDTO>();
for(Libro libro: listaLibros) {
LibroDTO libroExterno= new LibroDTO(libro.getIsbn(),libro.getTitulo(),
libro.getCategoria().getDescripcion());
listaDestino.add(libroExterno);
}
return listaDestino;
}
}
!

Es!evidente!que!nos!hemos!apoyado!en!las!anotacines!@Autowired!y!@Service!para!
acceder! a! la! informacin! de! ServicioLibros.! Una! vez! disponemos! de! esta! informacin!
usaremos! la! anotacin! @WebService! para! publicar! esta! informacin! hacia! el! exterior!
de!la!aplicacin!(ver!imagen).!

Al! haber! anotado! la! clase! con! @WebService! JAXtWS! se! encargar! de! generar! los!
proxies!y!el!fichero!WSDL!necesario!para!acceder!al!servicio.!A!continuacin!se!muestra!
una!imagen!aclaratoria.!
386
www.arquitecturajava.com!

Hemos!!terminado!de!construir!nuestro!servicio!web!.Sin!embargo!para!que!se!generen!
los!proxies!y!el!fichero!wsdl!deberemos! dar!una! serie! de! pasos! en! cuanto! a! Tomcat! y!
Spring!se!refiere.!

4. Publicacin!del!servicio!web.!

Tomcat!7!de!por!s!no!implementa!soporte!para!el!uso!de!servicios!web!con!JAXtWS,!ya!
que! no! cumple! con! todos! los! estndares! de! JEE! :! necesitaremos! utilizar! algn!
framework! o! librera! adicional! para! poder! usarlo.Para! ello! vamos! utilizar! Apache! CXF!
como! framework! de! servicios! web,! ya! que! se! integra! de! una! forma! muy! natural! con!
Spring.!La!siguiente!url!nos!permite!obtener!este!framework.!

http://cxf.apache.org!

Una! vez! obtenido! el! framework! pasamos! a! instalar! sus! libreras! dentro! de! nuestra!
aplicacin.!

5. Instalacin!de!Apache!CXF!

Apache! CXF! incorpora! un! grupo! amplio! de! libreras,! sin! embargo! las! que! necesitamos!
utilizar!para!nuestro!ejemplo!son!bastantes!menos!ya!que!parte!nos!las!proporciona!el!
propio! framework! Spring.! En! concreto! tendremos! que! aadir! las! siguientes! a! nuestro!
proyecto:!

387
Arquitectura*Java!

Cxft2.4.0!
Neethit3.0.0!
Wsdl4jt1.6.2!
Xmlschematcoret2.0!

6. Configuracin!del!framework!

En! este! apartado! nos! vamos! a! encargar! de! configurar! Apache! CXF! sobre! Spring.! Para!
ello!es!necesario!realizar!el!siguiente!conjunto!de!modificaciones:!!

Modificar! el! fichero! web.xml! y! aadir! el! servlet! de! apache! CXF! que! facilita! la!
integracion!con!nuestra!aplicacion!
Modificar!el!fichero!contextoAplicacion.xml!y!aadir!las!etiquetas!necesarias!de!
apache!CXF!

Vamos! ! a! modificar! el! fichero! web.xml! y! configurar! el! servlet! de! Apache! CXF! que! se!
encargara!de!gestionar!los!distintos!servicios!web.!A!continuacion!se!muestra!el!bloque!
de!cdigo!que!debemos!aadir!al!web.xml.!

Cdigo!23.3:!(web.xml)!

<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/servicios/*</url-pattern>
</servlet-mapping>

Una! vez! hecho! esto! estamos! en! disposicin! de! configurar! la! parte! relacionada! con!
Spring! Framework! y! dar! de! alta! nuestro! servicio.As! pues! vamos! a! ver! qu! elementos!
del!fichero!de!configuracin!de!Spring!debemos!modificar.!En!primer!lugar!es!necesario!
aadir! un! nuevo! namespace! a! los! que! ya! tenemos! para! poder! hacer! uso! de! las!
etiquetas!jaxws!!(ver!cdigo).!

Cdigo!23.4:!(contextoAplicacion.xml)!

xmlns:jaxws="http://cxf.apache.org/jaxws"
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd

388
www.arquitecturajava.com!

Hecho!esto,!aadiremos!varios!ficheros!xml!de!Apache!CXF!!al!fichero!de!Spring!

Cdigo!23.5:!(contextoAplicacion.xml)!

<import resource="classpath:META-INF/cxf/cxf.xml" />


<importresource="classpath:META-INF/cxf/cxf-extensionsoap.xml" />
<importresource="classpath:META-INF/cxf/cxf-servlet.xml" />
!

Tenemos! ya! importados! los! ficheros! que! Apache! ! CXF! necesita! para! trabajar.!
nicamente! necesitamos! configurar! el! servicio! web! a! nivel! de! Spring,! lo! cul! no!
presentar!problemas!(ver!cdigo).!

Cdigo!23.6:!(contextoAplicacion.xml)!

<jaxws:endpoint
id="servicioInformacionLibros"
implementor="com.arquitecturajava.aplicacion.serviciosexternos.
impl.ServicioInformacionLibrosCXF"
address="servicioInformacionLibros" />
</beans>

Como! podemos! ver! la! configuracin! es! sencilla:! en! primer! lugar! asignamos! un! id! al!
servicio!que!vamos!a!dar!de!alta!!

Cdigo!23.7:!(contextoAplicacion.xml)!

id="servicioInformacionLibros"

Una! vez! que! tenemos! definido! el! identificador! del! servicio,! definimos! qul! clase! se!
encarga!de!implementar!este!servicio.!

Cdigo!23.8:!(contextoAplicacion.xml)!

implementor="com.arquitecturajava.aplicacion.serviciosexternos.
impl.ServicioInformacionLibrosCXF"

Por! ultimo,! asignamos! la! direccin! (url)! desde! la! cul! accederemos! al! servicio! web! de!
nuestra!aplicacin.!

389
Arquitectura*Java!

Cdigo!23.9:!(contextoAplicacion.xml)!

address="servicioInformacionLibros"

Con! esta! configuracin! hemos! terminado! de! modificar! el! fichero! de! configuracin! de!
Spring.Podremos!acceder!al!servicio!a!travs!de!la!siguiente!URL:!

Cdigo!23.10:!(contextoAplicacion.xml)!

http://localhost:8080/Aplicacion18_1_Servicio_Web/servicios/servicioInformacionLibros?
wsdl
!

Esta! URL! nos! devuelve! el! fichero! WSDL! que! necesitamos! para! construir! un! cliente! y!
acceder!al!servicio!(ver!imagen).!

390
www.arquitecturajava.com!

Resumen!
En!este!captulo!hemos!introducido!brevemente!el!framework!Apache!CXF!y!como!este!
framework! se! integra! con! Spring! y! permite! la! construccin! de! Servicios! Web! de! una!
forma!relativamente!sencilla!.Adems!hemos!visto!cmo!definir!un!DTO!que!sirva!para!
transferir!informacin!entre!dos!sistemas.Los!DTO!no!son!siempre!necesarios!a!la!hora!
de! transferir! la! informacin,! depender! de! nuestra! situacin.! En! otros! momentos!
puede!ser!ms!prctico!simplemente!usar!objetos!de!negocio.!

!
!
!

!
!
!
!
!
!
!
!
!
!
391
Arquitectura*Java!

24.Administracin,y,pools!

En! el! captulo! anterior! hemos! diseado! un! servicio! web! usando! Apache! CXF! ! como!
framework! .No! vamos! a! aadir! ms! funcionalidad! a! la! aplicacin! :! podemos!
considerarla!terminada.!!

Este! captulo! intenta! aadir! algo! ms! basado! ! en! mis! experiencias! trabajando! con! la!
plataforma! JEE.Muchos! desarrolladores! ! construyen! aplicaciones! en! entornos! JEE! sin!
pensar!realmente!en!los!entornos!de!produccin!donde!stas!van!a!ser!ejecutadas.!Por!
as!decirlo,!trabajan!de!una!forma!totalmente!independiente!y!finalmente!entregan!un!
war!,ear!etc!olvidndose!del!resto.!Sin!embargo!muchas!veces!los!administradores!de!
sistemas! tienen! algo! que! decir! y! es! importante! disponer! en! nuestra! organizacin! de!
expertos! en! JEE! a! nivel! de! desarrollo,! pero! tambin! es! igual! de! importante! tener!
expertos!en!JEE!a!nivel!de!sistemas!ya!que!stos!!tienen!un!peso!clave!en!los!entornos!
de!produccin!.El!objetivo!de!este!captulo!no!es!ni!ms!ni!menos!que!revisar!nuestra!
aplicacin! y! ver! como! la! podramos! configurar! de! mejor! forma! para! un! administrador!
de!sistemas.!Para!ello!nos!centraremos!en!cmo!gestionar!los!pools!de!conexiones!y!las!
diferencias!de!visin!entre!el!equipo!de!desarrollo!y!el!de!sistemas.!

Objetivos!

Configuracin!de!la!aplicacin!para!administradores.!

!
392
www.arquitecturajava.com!

Tareas!

1. El!framework!Spring!y!pools.!
2. Pool!de!conexiones!y!Tomcat.!
3. Configuracin!de!Spring!va!JNDI.!

1. El!framework!Spring!y!Pools!

Hemos!gestionado!los!pools!de!conexiones!o!Datasource!a!travs!de!las!capacidades!de!
inyeccin! de! dependencia! que! tiene! Spring.! Concretamente! si! recordamos! hemos!
definido!a!nivel!de!Spring!un!pool!de!conexiones!de!la!siguiente!forma:!

Cdigo!24.1:!(contextoAplicacion.xml)!

<bean id="fuentedatos"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName" value="com.mysql.jdbc.Driver" />
<propertyname="url"
value="jdbc:mysql://localhost/arquitecturaJavaORM" />
<propertyname="username" value="root" />
<propertyname="password" value="java" />
</bean>

Nos! puede! parecer! en! un! ! primer! momento! correcto! como! desarrolladores! .Sin!
embargo! esta! configuracin! se! sale! de! la! configuracin! de! nuestro! servidor! de!
aplicaciones!:!!es!algo!completamente!independiente!y!gestionado!por!un!Framework!
concreto.!Por!lo!tanto!puede!darse!el!caso!de!que!el!administrador!de!sistemas!no!est!
al!tanto!ni!sepa!localizar!estos!recursos!(ver!imagen).!

393
Arquitectura*Java!

Como! la! imagen! muestra! nicamente! el! desarrollador! tiene! claro! cmo! se! ha!
configurado! el! pool! de! conexiones! usando! el! framework! Spring.! En! cambio! el!
administrador!desconoce!completamente!que!este!pool!de!conexiones!exista.!Una!vez!
hemos! identificado! el! problema! ,! debemos! reconfigurar! nuestra! aplicacin! para! que!!
encaje!de!forma!ms!natural!con!el!servidor!de!aplicaciones!que!estemos!usando!y!con!
las!tareas!de!administracin.!En!este!caso!nuestro!servidor!es!fcil!de!configurar!ya!que!
se! trata! de! Tomcat.! Tomcat! como! servlet! container! soporta! la! configuracin! ! de!
Datasources! o! ! pools! de! conexiones! a! nivel! de! administracin.! Vamos! a! verlo! en! la!
siguiente!tarea.!

2. Pool!de!conexiones!y!Tomcat!

Para!configurar!un!pool!de!conexiones!sobre!Tomcat!debemos!crear!un!nuevo!fichero!
de! configuracin! que! se! denomina! context.xml! ! y! que! se! encontrar! ubicado! en! la!
carpeta!METAtINF!de!nuestra!aplicacin!web!(ver!imagen).!

394
www.arquitecturajava.com!

El! fichero! en! cuestin! almacena! la! configuracin! necesaria! para! crear! un! pool! de!
conexiones! para! nuestra! aplicacin! a! nivel! de! servidor.! Veamos! el! contenido! del!
fichero:

Cdigo!24.2:!(context.xml)!

<Contextpath="/AplicacionFinal" docBase="AplicacionFinal"
reloadable="true" crossContext="true">
<Resourcename="jdbc/MiDataSource" auth="Container"
type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="root" password="java" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/arquitecturaJavaORM"/>
</Context>

El!fichero!define!una!etiqueta!Context!en!la!cul!se!declara!en!nombre!de!la!aplicacin!
que! va! a! disponer! del! pool! de! conexiones.! Una! vez! tenemos! definida! esta! parte,! la!
etiqueta! Resource! se! encarga! de! configurar! el! pool! de! conexiones! en! cuestin.! A!
continuacin!se!explican!las!distintas!propiedades!asignadas.!

name : Ruta de acceso al pool de conexiones


maxActive: Numero de conexiones activas en el pool
maxWait : Tiempo mximo de espera por una conexin definido en
milisegundos
user: Usuario de acceso para la conexin
password : Password de acceso para la conexin
driverClassName: Clase a instanciar a nivel de driver JDBC
url : Base de Datos a la que conectarnos
!

395
Arquitectura*Java!

Una!vez!realizadas!estas!operaciones!nuestro!servidor!ya!dispone!de!forma!pblica!de!
un!pool!!de!conexiones!para!nuestra!aplicacin!(ver!imagen).!

3. Configuracin!de!Spring!va!JNDI.!

Realizada! esta! operacin,! Tomcat! ha! dado! de! alta! un! nuevo! recurso! JNDI! a! nivel! del!
servidor!de!aplicaciones!,!!tendremos!que!modificar!la!estructura!de!nuestro!fichero!de!
configuracin!de!spring!(contextoAplicacion.xml)!para!que,!en!vez!de!crear!un!pool!de!
conexiones!propio,!delegue!en!el!pool!de!conexiones definido a nivel de servidor en
el rbol!jndi!(ver!imagen).!

396
www.arquitecturajava.com!

Para! configurar! el! framework! Spring! para! que! haga! uso! de! JNDI,! debemos! eliminar! la!
etiqueta!que!hace!referencia!a!un!datasource!que!hemos!creado!con!Spring!y!cambiarla!
por!un!datasource!que!delega!en!JNDI!(ver!imagen).!

Cdigo!24.4:!(contextoAplicacion.xml)!

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/MiDataSource"/>

De! esta! manera! el! framework! spring! delegar! en! los! recursos! JNDI! del! servidor! de!
aplicaciones!(ver!imagen).!

397
Arquitectura*Java!

Asi! pues! habremos! configurado! la! gestin! de! pools! de! conexiones! de! una! forma! ms!
amigable! de! cara! a! los! administradores! de! sistemas! y! habremos! asignado! las!
responsabilidades!de!una!manera!ms!correcta!(ver!imagen).!

398
www.arquitecturajava.com!

Para!que!!la!!etiqueta!anterior!!nos!funcione!correctamente!deberemos!dar!de!alta!un!
nuevo! namespace! a! nivel! del! fichero! de! configuracin! de! spring.! A! continuacin! se!
muestra!el!cdigo:

Cdigo!24.25:!(contexto.xml)!

xmlns:jee="http://www.springframework.org/schema/jee"
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd"

Una!vez!realizadas!estas!operaciones!la!aplicacin!funcionar!correctamente!utilizando!
el!pool!de!conexiones!de!tomcat.!

Resumen!
En! este! caso! el! nico! cambio! producido! en! la! aplicacin! es! la! creacin! de! un! pool! de!
conexiones! a! travs! de! los! ficheros! de! configuracin! del! servidor! ,de! tal! forma! que! la!
aplicacin! sea! ms! fcil! de! gestionar! por! parte! de! los! administradores! y! las!
responsabilidades! estn! mejor! repartidas,! algo! que! en! los! entornos! reales! es!
fundamental.!

!
!
!
!
!
!
!
!
!
!
!
!
!
!

399
Arquitectura*Java!

25.Conclusiones!

En! los! captulos! de! este! libro! hemos! ido! paso! a! paso! desarrollando! una! pequea!
aplicacin!JEE!.Para!ello!hemos!hecho!uso!de!principios!de!ingenieria,!de!frameworks!y!
de! patrones! de! diseo! diversos! .Todos! ellos! juntos! nos! han! permitido! desarrollar! una!
aplicacin!flexible.!Ahora!quizas!una!pregunta!dificil!de!responder!es!la!siguiente.!

Que!es!lo!mas!importante?!

1. Patrones!de!Diseo!
2. Frameworks!
3. Principios!de!Ingenieria!!

Para! la! mayor! parte! de! los! desarrolladores! lo! ms! importante! es! sin! ninguna! duda! el!
conjunto! de! frameworks! que! ha! de! utilizar! .Mi! experiencia! me! indica! que,! aunque!
evidentemente!esto!es!!clave!a!la!hora!de!desarrollar!una!arquitectura,!es!todava!ms!
importante! conocer! y! comprender! los! distintos! patrones! de! diseo! ! .Todos! los!
frameworks! estn! construidos! apoyndose! en! los! distintos! patrones! de! diseo! y! un!
conocimiento! slido! de! stos! nos! permitir! entender! de! una! forma! ms! natural! el!
funcionamiento!de!los!frameworks!.!Simplemente!por!recordar!algunos!de!los!ejemplos!
que!hemos!proporcionado!en!los!distintos!captulos:!

400
www.arquitecturajava.com!

JSF!como!framework!se!basa!en!un!patron!MVC2!
Spring!y!su!integracin!con!Hibernate!se!apoya!en!un!patrn!Template!
y!en!el!patrn!DAO!

Si!seguimos!profundizando!en!este!anlisis,!pronto!nos!daremos!cuenta!de!que!todos!
los!patrones!de!diseo!utilizados!en!los!distintos!captulos!aparecen!a!partir!del!uso!de!
uno! de! los! principios! de! ingenieria! de! software.! Por! ejemplo,! el! patron! MVC! aparece!
una!vez!que!hemos!dividido!las!responsabilidades!usando!el!principio!SRP!.Por!otro!lado!
el! patron! Template! aparece! al! hacer! uso! del! principio! DRY! en! una! jerarquia! de! clases!
concreta.! Por! lo! tanto! lo! ms! importante! para! los! arquitectos! es! conocer! estos!
principios!de!ingenieria!de!software!ya!que!nos!facilitar!sobremanera!el!entender!por!
qu! un! codigo! se! ha! de! construir! de! una! manera! u! otra! .He! aqu! un! diagrama! de! la!
relacin!entre!los!tres!conceptos:!

Hemos!visto!muchos!principios!durante!los!distintos!captulos!del!libro,!a!continuacin!
los!enumeramos:!

DRY!(Dont!Repeat!YourSelf)!
SRP!(Simple!responsibility!Principle)!

401
Arquitectura*Java!

IOC!(Inversion!of!Control)!
DIP!!(Dependency!Inversion!Principle)!
COC!(Convention!over!Configuration)!
OCP!(Open!Closed!Principle)!
LSP!(Liskov!Substitution!Principle)!
ISP!(Interface!Segregation!Principle)!

Un!subconjunto!de!este!grupo!de!principios!se!encuentra!unificado!en!un!acrnimo!al!
cul!cada!dia!se!!hace!ms!!referencia!!:!SOLID!!o!diseo!SOLID!,!que!hace!referencia!
a!un!desarrollo!que!cumple!con!los!siguientes!principios.!

SRP!
OCP!
LSP!
ISP!
DIP!

Apoyarnos!en!estos!principios!nos!mantendr!en!la!senda!correcta!a!la!hora!de!abordar!
los!distintos!desarrollos!:!de!ah!el!deriva!el!titulo!de!este!libro.!

1. JEE!un!ecosistema!

Hemos!desarrollado!durante!los!distintos!captulos!una!aplicacin!JEE!.Es!probable!que!
mucha! gente! pueda! pensar! ! que! son! Spring,! JPA! y! JSF! los! frameworks! o! estndares! a!
utilizar!a!la!hora!de!abordar!una!solucin!JEE.!Sin!embargo!hay!que!recordar!que!JEE!no!
es!a!dia!de!hoy!tanto!una!plataforma!como!un!ecosistema!donde!convergen!soluciones!
muy!!distintas!;!las!usadas!en!el!presente!libro!no!tienen!por!qu!ser!las!idneas!para!
todo! el! mundo! o! en! todas! las! situaciones.! Seguidamente! vamos! a! comentar! algunas!
que!pueden!substituir!o!ser!complementarias!a!las!que!hemos!visto:!

Enterprise! Java! Beans! ! (3.0,! 3.1):! En! el! libro! hemos! usado! Spring! como! framework!
principal,!sin!embargo!los!estndares!se!orientan!hacia!una!solucin!basada!en!!EJB!ya!
que!stos!han!madurado!mucho!y!son!una!opcin!tan!vlida!como!Spring!a!la!hora!de!
abordar!muchos!proyectos.!

Spring! MVC:! Hemos! usado! JSF! en! nuestra! aplicacin! pero! a! veces! los! estndares! se!
pueden! quedar! cortos! o! no! ser! lo! suficientemente! flexibles! para! lo! que! necesitamos! .!
Spring! MVC! puede! ser! a! dia! de! hoy! una! alternativa! muy! adecuada! a! la! capa! de!
presentacin!y!sobre!todo!muy!distinta!a!lo!que!JSF!representa.!

402
www.arquitecturajava.com!

JBoss!Seam:!Seams!es!un!framework!ubicado!a!nivel!de!abstraccin!por!encima!de!los!
EJBs!y!complementa!de!forma!slida!la!definicin!de!capa!de!presentacin!definida!por!
JSF.!

Groovy!y!Grails:Groovy!es!un!lenguaje!dinmico!basado!en!las!ideas!de!Ruby!y!Grails!es!
la! versin! de! Rails! para! este! lenguaje.! Si! estamos! interesados! en! desarrollos! agiles! y!
lenguajes! compactos! que! aceleren! el! desarrollo,! sta! puede! ser! tambin! una! buena!
alternativa!a!otras!soluciones.!

Android:! No! hemos! cubierto! la! parte! de! movilidad! en! este! libro! pero! a! da! de! hoy! es!
obligatorio!hacer!una!referencia!a!Android!a!la!hora!de!desarrollar!versiones!mviles!de!
nuestras!aplicaciones.!

HTML! 5! Frameworks! de! movilidad:! Por! ltimo! sern! cada! dia! ms! importantes! los!
frameworks!orientados!a!movilidad!de!HTML!5!que!permiten!el!desarrollo!de!una!nica!
aplicacin! que! funcione! en! varias! plataformas,! ya! que! recordemos! Android! solo!
representa! una! parte! de! este! pastel.! ! Ejemplos! de! estos! nuevos! frameworks! son!
PhoneGap!y!JQuery!Mobile.!

Resumen!
Hemos! utilizado! frameworks! ,patrones! y! principios! en! este! Libro.! Los! frameworks,!
aunque!nos!parezcan!importantes,!tienen!un!ciclo!de!vida!unos!vienen!y!otros!se!van!.!
En! cambio! los! principios! y! patrones! nos! acompaarn! y! nos! sern! tiles! durante! la!
carrera!profesional!que!tengamos.!Apostemos!de!una!forma!mas!slida!por!conocerlos.!
Para!terminar,!!si!algo!he!aprendido!estos!aos!de!las!plataformas!J2EE!y!JEE,!es!a!no!
ser!dogmtico!y!a!estar!abierto!a!!ideas!y!soluciones!nuevas!que!van!llegando.!Puede!
ser! que! el! prximo! Spring! Framework! ! o! el! prximo! Android! estn! a! la! vuelta! de! la!
esquina!:!es!necesario!tener!la!mente!abierta!para!aceptar!estas!evoluciones.!

403
Arquitectura*Java!

Bibliografa!
DOM! Scripting:! Web! Designwith! JavaScript! and! the! Document! Object! Model! by!
Jeremy!Keith!and!Jeffrey!Sambells!(Paperback!t!Dec!27,!2010)!!

Head! First! Servlets! and! JSP:! Passing! the! Sun! Certified! Web! Component! Developer!
Exam!by!Bryan!Basham,!Kathy!Sierra!and!Bert!Bates(Paperback!t!Apr!1,!2008)!

Java! Persistence! with! Hibernate! by! Christian! Bauer! and! Gavin! King! (Paperback! t!Nov!
24,!2006)!

Spring!in!Action!by!Craig!Walls(Paperback!t!Jun!29,!2011)!

Core!J2EE!Patterns:!Best!Practices!and!Design!Strategies!(2nd!Edition)!by!Deepak!Alur,!
Dan!Malks!and!John!Crupi(Hardcover!t!May!10,!2003)!

Apache!CXF!Web!ServiceDevelopment!

Murach's! Java! Servlets! and! JSP,! 2nd! Edition! by! Andrea! Steelman! and! Joel!
Murach(Paperback!t!Jan!21,!2008)!

Dependency!Injection!by!Dhanji!R.!Prasanna(Paperback!t!Sep!4,!2009)!

DesignPatterns:! Elements! of! Reusable! ObjecteOriented! Software! by! Erich! Gamma,!


Richard!Helm,!Ralph!Johnson!and!John!Vlissides(Hardcover!t!Nov!10,!1994)!

Core!Java!Server!Faces!(3rd!Edition)by!David!Geary!and!Cay!S.!Horstmann(Paperback!t
!Jun!6,!2010)!

Aspectj!in!Action:!Enterprise!AOP!with!Spring!Applications!by!RamnivasLaddad!and!Rod!
Johnson(Paperback!t!Oct!5,!2009)!

The! Pragmatic! Programmer:! From! Journey! to! MasterbyAndrew! Hunt! and! David!
Thomas(Paperback!t!Oct!30,!1999)!

Patterns! of! Enterprise! ApplicationArchitecture! by! Martin! Fowler(Hardcover! t!Nov! 15,!


2002)!

404
www.arquitecturajava.com!

405

También podría gustarte