Sei sulla pagina 1di 36

DesdeCero

con Spring e Hibernate





Nicols Cornaglia















http://nikofactory.blogspot.com
2004



Capitulo 1 - ntroduccin
1-2
Contenidos
1 Introduccin 1-4
2 Preparacin del entorno 2-5
2.1 Directorios 2-5
2.2 Instalacin SDK 2-5
2.3 Instalacin Eclipse 2-5
3 El proyecto 1parte 3-7
3.1 Anlisis 3-7
3.2 Creacin del proyecto en eclipse 3-8
3.3 Un aproximacin a la arquitectura 3-9
3.4 Test driven development 3-10
3.4.1 Anlisis 3-10
3.4.2 JUnit 3-10
3.4.3 El primer caso de prueba 3-10
3.5 Cosmtica 3-16
3.5.1 Fonts 3-16
3.5.2 Tabs 3-16
3.5.3 JavaDocs 3-17
3.6 Mas desarrollo 3-18
3.6.1 Refinamiento de Project 3-18
3.6.2 Mas clases 3-19
4 Persistencia 4-23
4.1 Introduccin a Hibernate 4-23
4.2 Xdoclet <doing> 4-25
4.3 Ant <todo> 4-29
4.4 MySQL <todo> 4-29
4.5 Test Cases <todo> 4-29
4.5.1 DBUnit <todo> 4-29
5 Uniendo todo con Spring 5-30
5.1 Inyeccin de dependencia 5-30
5.2 Spring <todo> 5-30
5.3 El Contexto <todo> 5-30
6 Coverage 6-31
6.1.1 Emma <todo> 6-31
7 Documentacin 7-32
7.1.1 Javadoc <todo> 7-32
7.1.2 java2html <todo> 7-32
8 ACEGI 8-33
9 CVS 9-34
Capitulo 1 - ntroduccin
1-3
9.1 WinCVS <todo> 9-34
10 Continuous Integration <todo> 10-35
11 El proyecto 2parte (Web) 11-36
11.1 Tomcat <todo> 11-36
11.2 El proyecto <todo> 11-36
11.3 Spring MVC <todo> 11-36
11.4 Sitemesh <todo> 11-36
11.5 Test Cases <todo> 11-36
11.5.1 jWebUnit <todo> 11-36

Capitulo 1 - ntroduccin
1-4
1 Introduccin
El presente libro sera una guia rapida para comenzar un proyecto de desarrollo de
soItware, utilizando Java, varias tecnicas bien conocidas, varios productos del mercado
open source y patterns estandar, pero de ninguna manera pretende ser la unica o mejor
Iorma de hacer las cosas, es solo una mas.
Al mismo tiempo que discurren los capitulos se creara, desde cero, una aplicacion
totalmente Iuncional. Esta aplicacion es parte de otro proyecto open source llamado
'MwM, una herramienta de planiIicacion y control de iteraciones para proyectos de
desarrollo de soItware.
Por lo tanto, este libro no explicara con largos capitulos dedicados a la teoria, las
tecnicas utilizadas, sino que aplicara el 'ensear con el ejemplo, con un lenguaje
coloquial, que tanto hace Ialta a los recien iniciados para no abrumarse con la cantidad
de conocimientos necesarios para ser un buen desarrollador de soItware.
Utilizaremos Spring Framework para el middleware y el web tier, e Hibernate para la
persistencia, pero la aplicacion se complementara con otros productos del mercado.
Antes de comenzar, un especial reconocimiento a Matt Raible
(http://raibledesigns.com/page/rd), por su constante esIuerzo de divulgacion, y porque este
libro no seria posible sin su ejemplo y motivacion con AppFuse
(http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse) y Spring Live
(http://www.springlive.com).
Capitulo 2 - Preparacin del entorno
2-5
2 Preparacin del entorno
Se presume que utilizaremos Windows para el desarrollo, por lo que se utilizara siempre
/ para los paths, y no \ como deberan utilizar los usuarios Linux / Unix.
2.1 Directorios
La estructura de directorios elegida para ordenar nuestro trabajo sera la siguiente:

Puede estar en cualquier disco duro y dentro de cualquier otra carpeta, pero de aqui en
adelante nos reIeriremos a work\ como nuestra carpeta principal para simpliIicar. En
vuestra conIiguracion, deberan reemplazar todas las apariciones de work\ con el path
completo que han elegido, por ejemplo C:\work\.
En ella estaran las demas carpetas, donde instalaremos las aplicaciones (apps),
desplegaremos las apis necesarias (extracts) y guardaremos nuestro(s) proyecto(s)
(workspace).
2.2 Instalacin SDK
Por supuesto que (si no lo han hecho ya) deberemos descargar e instalar el SDK de
Java. Para ello iremos a la web de Sun (http://java.sun.com/), buscar el vinculo 'J2SE
1.4.2 SDK, seguir las pantallas de conIirmacion y descargarlo en work\downloads. No
es necesario descargarnos tambien el netBeans, ya que hemos elegido eclipse para
nuestro desarrollo, asi que deberemos tener cuidado en elegir bien el vinculo. Hay que
asegurarse tambien que bajamos la version correspondiente a nuestro sistema operativo,
y que elegimos la opcion 'oIIline, lo que nos permitira descargarnos el SDK entero y
tenerlo para Iuturas ocasiones.
Una vez bajado el .exe, lo ejecutaremos para instalarlo en work\jdks, en una carpeta con
el mismo nombre de la version del SDK. Si hemos bajado la version 1.4.2-05 por
ejemplo, lo instalaremos en la carpeta work\jdks\j2sdk1.4.2_05. Mas adelante
podremos obtener e instalar aqui diIerentes versiones de Java e incluso maquinas
virtuales de diIerentes vendedores para comparar perIormance y compatibilidad.
Tambien crearemos la variable de entorno JAVA_HOME=work\jdks\j2sdk1.4.2_05 y
agregaremos %JAVA_HOME%\bin a la variable de entorno PATH.
2.3 Instalacin Eclipse
El IDE elegido para trabajar es eclipse (http://www.eclipse.org), aunque IntelliJ IDEA
(http://www.jetbrains.com/idea/) y netBeans (http://www.netbeans.org/) son dos opciones
viables.
Capitulo 2 - Preparacin del entorno
2-6
Luego de haber bajado el eclipse de la web, descompactaremos el .zip en
work\apps\eclipse, y crearemos un acceso directo a eclipse.exe, agregandole el
parametro '-data work\workspace, para indicarle cual sera la carpeta de trabajo donde
guardara nuestros proyectos.
Si ejecutamos el acceso directo, la primer pantalla que veremos sera la siguiente:

Cerrando esta vista, veremos la perspectiva por deIecto de eclipse: Resources.
Capitulo 3 - El proyecto 1 parte
3-7
3 El proyecto 1 parte
Un poco de analisis no viene mal, ni siquiera para un desarrollador.
Ironias aparte, diremos que nuestra aplicacion debera proveer a sus usuarios una interIaz
web para mantener un proyecto de desarrollo de soItware utilizando la metodologia XP
(Extreme Programming).
En esta metodologia (http://www.extremeprogramming.org), una buena parte de los
esIuerzos corresponden a asignar las diIerentes User Stories a las iteraciones en las
cuales se desarrollaran (Iteration Planning) y a los releases en los que estaran
disponibles para el usuario Iinal (Release Planning). Es aqui donde nuestra aplicacion
oIrecera sus servicios.
Si ser muy Iormales, diremos que los User Stories son escenarios de uso del sistema,
escritos por el cliente y que sirven para estimar el esIuerzo necesario.
Luego de obtener un numero razonable de User Stories (haciendo que el usuario las
escriba con o sin nuestra 'ayuda), los desarrolladores estiman cuanto tardaran, en
tiempo ideal, en desarrollar la Iuncionalidad. En base a estas estimaciones sabremos
cuantas podemos agrupar para no pasarnos de nuestra 'velocity, termino por el cual se
conoce al indice de productividad.
Las User Stories se agrupan luego en iteraciones, periodos de tiempo predeIinidos todos
iguales entre si, en los cuales las desarrollaremos. Y por ultimo, las stories se agrupan
en releases, o versiones de nuestra aplicacion para mostrar al cliente.
Por ejemplo, si en la iteracion anterior hemos hecho 5 stories de 3 dias cada una, mas 2
stories de 5 dias, tendremos una velocidad de 5*32*525. Por lo que en la siguiente
iteracion, la suma de las estimaciones no debera superar 25.
3.1 Anlisis
Tal vez parezca recursivo, pero podemos utilizar XP para analizar nuestra aplicacion
XP, por lo que comenzaremos a deIinir nuestros propios User Stories de la siguiente
Iorma:
S01 Creacion de un proyecto. El usuario debe crear un proyecto, asignandole nombre, y
Iechas de inicio y Iinalizacion (entre otros). Se quiere una interIaz web.
S02 Creacion de una iteracion. Se crea una iteracion para un proyecto, con Iechas de
inicio y Iin.
S03 Creacion de un release. Se necesita crear y modiIicar un release, con sus Iechas.
S04 Creacion de un story. El Cliente hace un story, por lo que es necesario agregarla al
sistema. Contiene un nombre y, opcionalmente, el release, iteracion, estimado en
tiempo y tareas asociadas.
S05 Asignacion de un story a una iteracion. Una vez decidido en que iteracion haremos
este story, se ingresa en el sistema.
S06 Asignacion de un story a un release. Una vez decidido en que release haremos este
story, se ingresa en el sistema.
S07 Se requiere un listado de las iteraciones de un proyecto, con el esIuerzo estimado,
actual y restante.
Capitulo 3 - El proyecto 1 parte
3-8
Como se puede ver, la Iorma de escribirlos diIiere de un User Story a otro, ya que los
clientes son los encargados de hacerlo, y su Iorma de expresarse no siempre es la
misma.
Pero con esto tenemos suIiciente como para comenzar nuestro proyecto. Deberiamos
ahora estimar cada Story y asignarla a una iteracion. Pero como este no es un libro sobre
XP, sino una guia rapida para comenzar a desarrollar, asumiremos que tenemos tiempo
inIinito e iremos escogiendo stories para hacer a medida que necesitemos. Y como
seremos nuestro propio cliente, las reuniones Iormales con el cliente, para que nos
detalle cada story, las asumiremos como realizadas.
3.2 Creacin del proyecto en eclipse
Vamos pues a lo que nos interesa, que es crear el proyecto en eclipse.
Tanto desde la perspectiva por deIecto de eclipse Resources como desde mi preIerida,
Java, podemos utilizar el menu y crear un proyecto: File/New/Project/Java Project.
Con lo que tendremos la pantalla inicial para especiIicar el nombre de proyecto, en este
caso mwm:

En la siguiente pantalla agregaremos una carpeta src para nuestros Iuentes:
Capitulo 3 - El proyecto 1 parte
3-9

y conIirmaremos la caja de dialogo que nos presenta eclipse para actualizar la carpeta de
salida a bin:

con lo que Iinalizaremos la creacion, obteniendo el siguiente resultado en la perspectiva
Java:

3.3 Un aproximacin a la arquitectura
Sabemos que sera una aplicacion con un componente web (S01), que requerira una base
de datos para guardar proyectos, iteraciones, etc. (S01, S02, S03, etc.), una jerarquia de
clases simple por ahora, pero con componentes muy interesantes: proyecto (S01)
iteracion (S02) story (S04) tarea (S04) y ciertos calculos sobre los datos de estas
clases (S07).
En base estos requerimientos y a nuestra experiencia podemos saber que contendra
ciertos componentes:
Clases java contenidas en paquetes.
Persistencia en base de datos.
InterIaz web.
Una capa de componentes de negocio.
Capitulo 3 - El proyecto 1 parte
3-10
3.4 Test driven development
El primer impulso es comenzar con un public class Project{} como siempre, pero
esta vez intentaremos una aproximacion diIerente a nuestra Iorma de desarrollar
soItware: TDD - Test driven development (http://www.testdriven.com).
En lugar de escribir codigo y luego comprobar su Iuncionamiento, TDD establece que
primero se escriben los casos de prueba (unit tests), y luego se crea el codigo necesario
para satisIacerlos. Esto Iuerza el tener todos (o casi todos) los casos de prueba para
nuestro codigo y un alto desacoplamiento del codigo al tener las clases (como minimo)
dos usuarios desde el inicio: la aplicacion cliente y los casos de prueba.
3.4.1 Anlisis
Que datos podemos obtener de nuestra primer user story (S01)?
Que necesitamos modelar una jerarquia de objetos tal que nos permita oIrecer al usuario
una Iorma de crear proyectos. Y que estos proyectos tienen unas propiedades, hasta
ahora 'dueo, 'Iecha de inicio y 'Iecha de Iinalizacion.
Separando por ahora la parte de interaccion web con el usuario, podemos asegurar, con
bastante conIianza, que necesitaremos una clase a la que podriamos llamar Project, a la
cual le deberiamos podemos asignar las propiedades antes mencionadas.
Pues bien, hagamos un caso de prueba que compruebe esta Iuncionalidad. Para ello
necesitaremos una herramienta que Iacilite las comprobaciones, y la que utilizaremos
sera JUnit.
3.4.2 JUnit
JUnit (http://www.junit.org) es una herramienta Java para pruebas unitarias y de
regresion, que provee una jerarquia de clases y deIine un lenguaje comun para escribir y
ejecutar casos de prueba repetibles. Mediante reIlexion, examina las clases de prueba y
ejecuta los metodos sealados, examinando el resultado de los mismos.
Muchos de los IDEs actuales proveen soporte para JUnit, considerado ya el estandar
para pruebas unitarias en Java.
En la practica, tendremos que crear una clase heredada de TestCase, agregarle metodos
llamados test* para contener el codigo de prueba, y utilizar 'Assertions para
comprobar el resultado del mismo (assertNull(), AssertEquals(). Tambien
podremos agrupar casos de prueba en 'Suites, para ejecutar en Iorma conjunta
diIerentes casos de prueba con elementos en comun.
3.4.3 El primer caso de prueba
Si bien podriamos hacerlo desde cero, utilizaremos las Iuncionalidades de eclipse para
crear nuestro primer caso de prueba.
Antes que nada crearemos una nueva carpeta Iuente a la que llamaremos test para
nuestros casos de prueba, desde el menu File/New/Source Folder:
Capitulo 3 - El proyecto 1 parte
3-11

Esto no lleva tambien a querer modiIicar las propiedades del proyecto, con el botn
derecho/Properties/Java Build Path, para cambiar el orden de nuestro Java Build
Path y poner la carpeta test en segundo lugar, luego de src.

Finalmente accederemos al menu File/New/JUnit Test Case y Eclipse nos propondra
en este momento que agreguemos al build path el .jar necesario para la ejecutar las
clases de prueba:

Luego de elegir la opcion Yes, aparecera la caja de dialogo donde elegiremos las
opciones de eclipse para crear el caso de prueba:
Capitulo 3 - El proyecto 1 parte
3-12

En el Source Folder pondremos el recien creado test, como nombre de package
com.mwm.model y como nombre ProjectTest. Tambien haremos que nos cree los
metodos setUp() y tearDown(), poniendo las marcas necesarias.
Luego de aceptar las opciones con Finish, el resultado Iinal en la perspectiva Java sera
el siguiente:


Y el codigo generado para com\mwm\model\ProjectTest.java es el siguiente:
/*
* Created on Oct 14, 2004
*
Capitulo 3 - El proyecto 1 parte
3-13
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package com.mwm.model;

import junit.framework.TestCase;

/**
* @author ncornag
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class ProjectTest extends TestCase {

/**
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
}

/*
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}

}
Crearemos ahora un metodo capaz de comprobar la creacion de un objeto de la clase
Project, y la asignacion de sus correspondientes propiedades.
Lo que primero haremos sera tener siempre disponible una propiedad del caso de prueba
de tipo Project, creandola en el metodo setUp(), metodo que se ejecutara antes de
ejecutar cada metodo de prueba. Tambien aprovecharemos el metodo tearDown() para
'limpiar los cambios que pudieramos haber hecho y dejar todo listo para la ejecucion
del siguiente metodo de test.
Luego, crearemos el metodo testNewProject(), con la Iuncionalidad necesaria para
asegurarnos el correcto Iuncionamiento de la clase Project.
El resultado Iinal es el siguiente (sin comentarios por simplicidad):
public class ProjectTest extends TestCase {
private Project project;

protected void setUp() throws Exception {
super.setUp();
project = new Project();
}

protected void tearDown() throws Exception {
super.tearDown();
project = null;
Capitulo 3 - El proyecto 1 parte
3-14
}

public void testNewProject() throws Exception {
project.setName("Mi primer proyecto");
project.setStartDate(new Date(0));
project.setEndDate(new Date(0));
assertEquals("Name", "Mi primer proyecto", project.getName());
assertNotNull("StartDate", project.getStartDate());
assertNotNull("EndDate", project.getEndDate());
}
}
Lo que estamos haciendo en este metodo de prueba testNewProject(), es utilizar la
instancia de Project creada inmediatamente antes en el metodo setUp(), inicializar sus
propiedades, y asegurarnos luego que podemos recuperar la inIormacion.
Para veriIicar el nombre del proyecto, utilizamos el metodo assertEquals(String arg0,
Object arg1, Object arg2) de JUnit, donde indicaremos en el primer argumento un
string para ser visualizado en caso de error, el objeto esperado en el segundo argumento
y el objeto a comprobar en el tercero.
Para las Iechas, por ejemplo, utilizaremos assertNotNull(String arg0, Object arg1),
donde utilizaremos de la misma Iorma el primer argumento, y en el segundo enviaremos
el objeto a comprobar su no nulidad.
Si alguno de los metodos 'assert Ialla, el metodo se da por Iinalizado y Iallado.
Pero lo que tenemos en este punto es una clase de prueba que ni siquiera compila. Pero
ese es el punto. Ahora estamos 'obligados a hacer una clase Project, con los metodos
necesarios para asignarle ciertas propiedades, tal y como establece nuestro S01.
Por lo tanto, crearemos una nueva clase (File/New/Class), con el minimo codigo
necesario para satisIacer los requerimientos del caso de prueba:
/*
* Created on Oct 14, 2004
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package com.mwm.model;

import java.util.Date;

/**
* @author ncornag
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class Project {

//~ Properties =============================================================
private String name;
private Date startDate;
private Date endDate;

Capitulo 3 - El proyecto 1 parte
3-15
//~ Getter/Setters =========================================================

/**
* @return Returns the endDate.
*/
public Date getEndDate() {
return endDate;
}
/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @return Returns the startDate.
*/
public Date getStartDate() {
return startDate;
}
/**
* @param endDate The endDate to set.
*/
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
/**
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* @param startDate The startDate to set.
*/
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
}
Nuestro caso de prueba compila ahora correctamente, ya que hemos creado la nueva
clase en com.mwm.model (el mismo package que el caso de prueba aunque bajo la carpeta
Iuente src).
Solo nos queda comprobar su correcto Iuncionamiento, eligiendo la clase ProjectTest
con el boton de la derecha, y eligiendo la opcion del menu Run/Junit Test. Se nos
abrira la vista Junit, en la cual podemos observar que todo ha Iuncionado tal como era
de esperar (una barra verde nos lo indica):
Capitulo 3 - El proyecto 1 parte
3-16

Se podria decir que no tiene mucho sentido comprobar los accesores/mutadores
(getters/setters) de una propiedad por lo trivial de los metodos, y se tendria razon por lo
que en adelante no comprobaremos mas que los metodos 'realmente Iuncionales. Sin
embargo, al hacerlo hemos aprendido los Iundamentos de TDD y la utilizacion de JUnit,
asi como las capacidades de eclipse al respecto.
3.5 Cosmtica
Aprovecharemos esta instancia del proyecto, donde tenemos ya deIinidas algunas
clases, para cambiar ciertas caracteristicas del entorno en el que trabajamos.
3.5.1 Fonts
Personalmente preIiero tener mucho espacio en la ventana de edicion de codigo, para lo
cual es necesario cambiar, en las preIerencias, la Iuente por deIecto del editor.

3.5.2 Tabs
Los espacios deberian ser la Iorma elegida de identar, ya que aseguran una correcta
visualizacion de nuestro codigo en diIerentes sistemas operativos, y para ello deberemos
marcar la opcion Insert spaces for tab:
Capitulo 3 - El proyecto 1 parte
3-17

3.5.3 JavaDocs
Los JavaDocs son una Iorma estandar de documentar nuestro codigo, y eclipse nos
provee plantillas para que al momento de creacion de una clase o metodo, se inserte el
correspondiente cometario. Lo que haremos ahora es modiIicar algunos detalles de estas
plantillas en Window/Preferences/Java/Code Style/Code Templates/Comments:
Para las clases (Types), agregaremos un link al nombre de la clase java, pero con
extension .html, para permitiros mas adelante generar paginas html con el codigo Iuente
y tenerlas vinculadas a los javadocs. Tambien agregaremos nuestro nombre delante del
tag @author, (aqui podemos poner una direccion de correo electronico con los tags
adecuados: <a href="mailto:nombre@dominio.com">Nombre</a>), y unos tags especiales
para el CVS (mas sobre esto adelante).

No esta de mas reIorzar en este momento la idea de documentacion, con tres simples
palabras: documentar, documentar, documentar.
Unas lineas de comentario en los javadocs y algunas en lugares estrategicos del codigo
no consume ningun tiempo extra, y ayudara a los demas (y a nosotros mismos) a
entender el codigo resultante.
En los metodos sobrescritos (Overriding methods) pondremos:
/**
* ${see_to_overridden}
*/
Capitulo 3 - El proyecto 1 parte
3-18
En los nuevos archivos de clase (Code/New Java Files) suprimiremos los comentarios,
quedandonos con:
${package_declaration}

${typecomment}
${type_declaration}
Y por ultimo el Catch block body podemos dejarlo como esta por ahora, y cambiarlo
mas adelante por:
log.error("Error: " + ${exception_var}.getMessage());
si decidimos utilizar Log4J para las trazas de errores (mas sobre esto adelante).
Por ultimo, no debemos olvidar de modiIicar los comentarios ya generados por eclipse
para nuestras dos clases Project y ProjectTest (Alt+Shift+J sobre el nombre de
metodo o clase), asi como tambien cambiar los tabs de ambos Iicheros a espacios
(Alt+Shift+F sobre el codigo).
3.6 Mas desarrollo
Este metodo de escribir el caso de prueba y luego escribir el minimo codigo (KISS) que
lo satisIaga (TDD), lo continuaremos practicando a lo largo de todo el ciclo de vida del
proyecto. KISS son las siglas de 'Keep It Simple Stupid (Mantenlo simple estupido)
3.6.1 Refinamiento de Project
Continuaremos ahora nuestro desarrollo agregando propiedades que sabemos (el cliente
nos ha dicho) son del proyecto.
Por ejemplo, la interIaz debera ser accesible por diIerentes empresas, por lo que cada
proyecto debera tener asociado una. Para ello, deberiamos hacer un metodo que pruebe
la asignacion y posterior recupero de esta propiedad en la clase Project.
Pero hemos elegido no hacer casos de prueba sobre estos metodos, por lo que tenemos
tres caminos:
1. Ignorar este requerimiento y no hacer algo que quizas no necesitemos, siguiendo
la practica YAGNI de XP. YAGNI son las siglas de 'You Aren`t Gonna Need
It (No lo vas a necesitar)
2. Agregamos las propiedades necesarias en la clase, sin su metodo de veriIicacion.
3. Revemos nuestra politica y agregamos metodos de veriIicacion para los
accesores y mutadores.
YAGNI no signiIica que no hagamos diseo para nuestra aplicacion, y al disear la
clase Project, sabemos positivamente que necesitaremos ciertas propiedades. Y
tambien estamos convencidos de no hacer pruebas sobre metodos triviales, por lo que
optaremos por la opcion 2, y agregaremos company y description a la clase Project:
private String description;
private Company company;
con sus correspondientes accesores y mutadores, utilizando eclipse para crearlos como
ya hemos visto anteriormente.
Para que este ultimo cambio compile correctamente, nos veremos necesitado de crear
una clase Company, que por ahora contendra solo su mas obvia propiedad, el nombre:
package com.mwm.model;
Capitulo 3 - El proyecto 1 parte
3-19

/**
* <p>
* <a href="Company.java.html"><i>View Source</i></a>
* </p>
*
* @author Nicolas Cornaglia
* @version $Revision:$ $Date:$
*/
public class Company {

//~ Properties ===========================================================
private String name;

//~ Getters/Setters ======================================================

/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
}
3.6.2 Mas clases
Segun lo que sabemos del story S02 tenemos una entidad llamada iteracion asociada de
0..n al proyecto. Esta iteracion tiene como propiedades el nombre, la descripcion y las
Iechas de inicio y de Iin.
Comenzaremos pues, agregando un metodo de prueba a nuestro ProjectTest:
/**
* Test put & remove a Iteration
* @throws Exception
*/
public void testPutRemoveIteration() throws Exception {
Long id = new Long(1);
Iteration iteration = new Iteration();
iteration.setId(id);
project.addIteration(iteration);
assertEquals("Iteration", iteration, project.getIteration(id));
assertEquals("Iteration project", project,
project.getIteration(id).getProject());
project.removeIteration(iteration);
assertNull("Iteration not removed", project.getIteration(id));
}
Capitulo 3 - El proyecto 1 parte
3-20
En este punto nuestra clase no compila, ya que no existe todavia la clase Iteration, y la
clase Project no tiene los metodos addIteration(), getIteration() ni
removeIteration(). Tambien hemos agregado un identiIicador de iteracion, para
permitirnos obtener y remover cada instancia de la clase.
Nos queda pues hacer lo necesario para satisIacer el caso de prueba que hemos
diseado, crear la clase Iteration:
public class Iteration {
//~ Properties ===========================================================
private Long id;
private String name;
private String description;
private Project project;
private Date startDate;
private Date endDate;
//~ Getter/Setters =======================================================
.
.
.
}
y agregar la relacion con Project (con sus respectivos accesores y mutadores), y los
metodos Ialtantes para administrar las iteraciones:
private Map iterations = new HashMap();

public Iteration getIteration(Long id) {
return null;
}
public void addIteration(Iteration iteration) {
}
public void removeIteration(Iteration iteration) {
}
con lo que nuestra clase de prueba compilara, pero dara error al ejecutarse:

Capitulo 3 - El proyecto 1 parte
3-21
porque los metodos que hemos creado eran solo plantillas de lo que necesitaremos, y
getIteration(id) devuelve null, haciendo que JUnit nos muestre un error en la linea
52: junit.framework.AssertionFailedError: Iteration expected:
com.mwm.model.Iteration@3ee284 but was: <null>, indicando que la sentencia
assertEquals("Iteration", iteration, project.getIteration(id));
ha Iallado.
Hagamos entonces que estos metodos realicen algo util:
/**
* @param id
* @return
*/
public Iteration getIteration(Long id) {
return (Iteration)iterations.get(id);
}

/**
* @param key
* @param iteration
*/
public void addIteration(Iteration iteration) {
iteration.setProject(this);
iterations.put(iteration.getId(), iteration);
}

/**
* @param key
*/
public void removeIteration(Iteration iteration) {
iterations.remove(iteration.getId());
}
y obtendremos la 'deseada barra verde al ejecutar el caso de prueba:

Otra Iorma de crear una clase o un metodo que no existen todavia, es hacer clic sobre el
icono de error de la izquierda del codigo y utilizar las ayudas que oIrece eclipse:
Capitulo 3 - El proyecto 1 parte
3-22

Capitulo 4 - Persistencia
4-23
4 Persistencia
4.1 Introduccin a Hibernate
Las clases persistentes son aquellas que estan relacionadas con tablas en la base de
datos. Supongamos una version simpliIicada de nuestra clase Project:
package com.mwm.model;
public class Project {
private Long id;
private String name;
private Company company;

public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
en ella tenemos tres atributos: el nombre, una reIerencia a Company y un identiIicador de
instancia que hemos agregado.
El identiIicador, en este caso un Long, podria haber sido cualquier objeto y nos permitira
acceder a la clave primaria en la base de datos. Este y resto de los atributos tiene sus
respectivos accesores / mutadores como cualquier JavaBean y la clase tiene deIinida
implicitamente el constructor por deIecto (sin argumentos) necesario para que Hibernate
pueda ejecutar Constructor.newInstance().
Estas caracteristicas de nuestras clases persistentes, hacen que se no dependa
especiIicamente de ninguna tecnologia de persistencia, clases o interIaces tal y como
sucede con EJB y los entity beans. Por lo que podemos instanciar y comprobar el
Iuncionamiento de la clase aIuera de cualquier contenedor, tal como ya comprobamos
en ProjectTest.
La siguiente clase, Company, la deIiniremos asi:
package com.mwm.model;
public class Company {
private Long id;
Capitulo 4 - Persistencia
4-24
private String name;

public Long getId() {
return id;
}
public void setId() {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Como hacemos para que Hibernate persista estas clases? DeIiniendo (manualmente o
con ayuda de herramientas) un Iichero XML por clase donde especiIicaremos la
inIormacion necesaria, y utilizando las interIaces Session y Transaction de Hibernate.
El Iichero XML (XML mapping document) deIine de que manera las propiedades de la
clase Project se corresponden con columnas de la tabla project de la base de datos.
Para Project crearemos Project.hbm.xml en el classpath:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="com.mwm.model.Project"
table="project">
<id
name="id"
column="id">
<generator class="native"/>
</id>
<property
name="name"
column="name"/>
<many-to-one
name="company"
cascade="all"
column="company_id"/>
</class>
</hibernate-mapping>
Y para Company crearemos Company.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="com.mwm.model.Company"
Capitulo 4 - Persistencia
4-25
table="company">
<id
name="id"
column="id">
<generator class="native"/>
</id>
<property
name="name"
column="name"/>
</class>
</hibernate-mapping>
Asumiendo que existe en nuestro classpath un Iichero hibernate.properties con los
parametros de conexion a la base de datos (entre otros posibles), podremos crear un
proyecto y persistirlo:
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;

...

Configuration cfg = new Configuration();
cfg.addResource("Project.hbm.xml");
cfg.addResource("Company.hbm.xml");
SessionFactory sf = cfg.buildSessionFactory();

Session s = sf.openSession();
Transaction tx = s.beginTransaction();

Company company = new Company();
company.setName("Mi empresa");
Project project = new Project();
project.setName("MwM");
project.setCompany(company);

s.save(project);
tx.commit();
s.close();
con lo cual Hibernate generara las siguientes sentencias SQL:
insert into company (id, name)
values (1, Mi empresa);
insert into project (id, name, id_company)
values (1, MwM, 1);
Como se puede ver, simplemente guardando Project Hibernate guarda tambien ,
mediante cascade save, los objetos dependientes como Company.
4.2 Xdoclet <doing>
Una gran tarea a realizar en un proyecto de esta clase, es el mantenimiento de los
descriptores de Hibernate. Para ayudarnos a automatizar esta tarea utilizaremos XDoclet
Capitulo 4 - Persistencia
4-26
(http://xdoclet.sourceIorge.net/xdoclet/), una herramienta de generacion de codigo que
permite la programacion orientada a atributos.
Con ella, podemos agregar meta-data (atributos) en Iorma de tags a los Iuentes java,
para luego post procesarlos y obtener codigo adicional, por ejemplo:
/**
* <p>
* <a href="Project.java.html"> <i>View Source </i> </a>
* </p>
*
* @author Nicolas Cornaglia
* @version $Revision:$ $Date:$
*
* @hibernate.class table="project"
*/
public class Project {
agregando el atributo @hibernate.class a Project.java, justo antes de la deIinicion de
la clase, le decimos a XDoclet que en el momento de la generacion de los descriptores
(ya veremos mas adelante como), genere el siguiente tag dentro del descriptor
Project.hbm.xml:
<class
name="com.mwm.model.Project"
table="project"
dynamic-update="false"
dynamic-insert="false"
>
Los tags tienen diIerentes opciones que podemos conIigurar, como por ejemplo el
nombre de la tabla en la base de datos (table=project) para el tag
@hibernate.class. Tambien vemos como XDoclet agrega valores por deIecto a los
atributos del descriptor.
El siguiente paso es especiIicarle a XDoclet cual es nuestro id de clase agregando
@hibernate.id column="id" a getIteration(), que lo genere la base de datos:
generator-class="native" y que los valores null del id identiIican las clases no
persistidas: unsaved-value="null".
/**
* @param id
* @return
*
* @hibernate.id column="id" generator-class="native" unsaved-value="null"
*/
public Iteration getIteration(Long id) {
return (Iteration) iterations.get(id);
}
Podriamos por supuesto haber elegido otra tactica para la generacion de ids, por ejemplo
generarlos nosotros mismos, o utilizar otro valor para identiIicar los ids no persistidos,
pero por ahora veamos el resultado:
<id
name="id"
column="id"
type="java.lang.Long"
unsaved-value="null"
Capitulo 4 - Persistencia
4-27
>
<generator class="native">
</generator>
</id>
Agregando el tag @hibernate.property al getter de la propiedad name, similar a lo que
haremos para description, startDate y endDate:
/**
* @return Returns the name.
*
* @hibernate.property not-null="true"
*/
public String getName() {
return name;
}
obtenemos el siguiente tag en el descriptor:
<property
name="name"
type="java.lang.String"
update="true"
insert="true"
access="property"
column="name"
not-null="true"
/>
que hara que la propiedad name de nuestra clase corresponda con la columna name de la
tabla, a la vez que impide insertar valores en null.
Para la empresa asociada al proyecto, tendremos que utilizar un @hibernate.many-to-
one, ya que una empresa puede tener varios proyectos al mismo tiempo:
/**
* @return Returns the company.
*
* @hibernate.many-to-one column="company_id" not-null="true"
* class="com.mwm.model.Company"
* outer-join="true"
*/
public Company getCompany() {
return company;
}
para obtener:
<many-to-one
name="company"
class="com.mwm.model.Company"
cascade="none"
outer-join="true"
update="true"
insert="true"
access="property"
column="company_id"
not-null="true"
/>
Capitulo 4 - Persistencia
4-28
Y nuestro ultimo y mas complicado caso que nos lleva a agregar las opciones para
generar el descriptor de la propiedad iterations:
/**
* @return Returns the iterations.
*
* @hibernate.map name="iterations" inverse="true" lazy="false"
* cascade="all-delete-orphan"
* @hibernate.collection-one-to-many class="com.mwm.model.Iteration"
* @hibernate.collection-key column="project_id"
* @hibernate.collection-index column="id" type="long"
*/
public Map getIterations() {
return iterations;
}
Donde le diremos que persista nuestra coleccion de iteraciones con @hibernate.map, que
obtenga la coleccion cuando se instancie el proyecto y no recien cuando se acceda a la
propiedad con lazy="false", que borre las iteraciones cuando se borre el proyecto con
cascade="all-delete-orphan", que se puede navegar en Iorma inversa, desde la
iteracion al proyecto con inverse="true", que la relacion es uno a muchos con
@hibernate.collection-one-to-many, que la clave del Map donde guardaremos las
iteraciones es el id de la iteracion con @hibernate.collection-index column="id"
type="long" y que la clave para saber que iteraciones son de este proyecto, dentro de la
tabla donde se guarden las iteraciones es el id de proyecto con @hibernate.collection-
key column="project_id".
<map
name="iterations"
lazy="false"
sort="unsorted"
outer-join="auto"
inverse="true"
cascade="all-delete-orphan"
>
<key
column="project_id"
>
</key>
<index
column="id"
type="long"
/>
<one-to-many
class="com.mwm.model.Iteration"
/>
</map>
Solo nos queda hacer lo mismo con los tags de las clases restantes: Company e
Iteration.

Capitulo 4 - Persistencia
4-29
4.3 Ant <todo>
Utilizacion de Ant para la generacion de los descriptores.
4.4 MySQL <todo>
Descargar MySQL 4.x de http://www.mysql.com, e instalar en work\apps\mysql
4.5 Test Cases <todo>
4.5.1 DBUnit <todo>
Capitulo 5 - Uniendo todo con 8pring
5-30
5 Uniendo todo con Spring
5.1 Inyeccin de dependencia
Inyeccion de dependencia, tambien conocido por su nombre mas generico inversion de
control, es un pattern (patron) de creacion de objetos, es decir que es un pattern que dice
algo acerca de como un objeto es creado.
Si tenemos dos clases que dependen una de la otra, hay varias Iormas de establecer ese
tipo de dependencia. La Iorma mas simple es hacer que la clase A que depende de B,
instancie B. Pero eso acopla mucho las clases entre si.
Hay otro pattern muy popular usado Irecuentemente en J2EE llamado 'service locator,
que basicamente establece que la clase A busca la clase B en un service locator para su
utilizacion. Esto Iavorece un acoplamiento menos Iuerte que el metodo anterior, pero
este sigue existiendo.
Inyeccion de dependencia en cambio, hace que la clase que necesita algo no lo cree, ni
lo busque en algun lugar, sino que lo obtenga por inyeccion, mediante un constructor o
un mutador (setter).
Podriamos deIinir por consiguiente a la inyeccion de dependencia como un termino
utilizado para describir el desacoplamiento entre la implementacion de un objeto y la
construccion de otro objeto del cual depende.
Siendo mas Iormales y utilizando la literatura al respecto (Expert One-on-One
J2EE Development without EJB, Rod Johnson y Juergen Hoeller, 2004, Wiley
Publishing, Inc.), podemos utilizar el siguiente esquema para mostrar los diIerentes
tipos de inversion de control:
Contenedores todo~
5.2 Spring <todo>
5.3 El Contexto <todo>
Inversi n de Cont rol
El framework es responsable del ciclo
de vida del obj eto
Bsqueda de
Dependencias
El objeto implementa una API
especfica del contenedor
Inyecci n de
Dependencias
No hay dependencias a una API
especfica del contenedor
Inyecci n por medi o
de Const r uc t ores
Los objetos son asignados mediante
argumentos de constructores
Inyecci n por medi o
de Mut adores
Los objetos son asignados mediante
propi edades JavaBean
Capitulo 6 - Coverage
6-31
6 Coverage
6.1.1 Emma <todo>
Capitulo 7 - Documentacin
7-32
7 Documentacin
7.1.1 Javadoc <todo>
7.1.2 java2html <todo>
Capitulo 8 - ACEG
8-33
8 ACEGI
Por que hace un salto de pagina ?

Capitulo 9 - CV8
9-34
9 CVS
9.1 WinCVS <todo>
Capitulo 10 - Continuous ntegration <todo>
10-35
10 Continuous Integration <todo>
Capitulo 11 - El proyecto 2 parte {Web}
11-36
11 El proyecto 2 parte (Web)
11.1 Tomcat <todo>
Descargar Tomcat 5.x de http://jakarta.apache.org/tomcat, e instalar en
work\apps\tomcat
11.2 El proyecto <todo>
MVC
Struts, Spring, Webwork
11.3 Spring MVC <todo>
11.4 Sitemesh <todo>
11.5 Test Cases <todo>
11.5.1 jWebUnit <todo>

Potrebbero piacerti anche