Thursday, February 11, 2010

Relación One-to-Many en Spring Roo

En un pasado post hable un poco de los primeros pasos con Sprign Roo.

En este post hare un muy pequeño proyecto con Spring Roo pero me enfocare en ver como hacer entidades con relaciones de uno a muchos (maestro-esclavo).

Ok, pues empecemos.

Primero crearemos el proyecto indicándole el paquete raíz del mismo.


roo> project --topLevelPackage prueba.springroo.relonetomany --projectName relacion-onetomany
Created D:\Abaddon\Projects\JAbaddon\Code\SpringRoo\RelacionOneToMany\pom.xml
Created SRC_MAIN_JAVA
Created SRC_MAIN_RESOURCES
Created SRC_TEST_JAVA
Created SRC_TEST_RESOURCES
Created SRC_MAIN_WEBAPP
Created SRC_MAIN_RESOURCES\META-INF\spring
Created SRC_MAIN_RESOURCES\META-INF\spring\applicationContext.xml
Created SRC_MAIN_RESOURCES\META-INF\spring\log4j.properties


Ahora hay que definir el método de persistencia para el proyecto. Usaremos MySQL con Hibernate.


prueba.springroo.relonetomany roo> persistence setup --provider HIBERNATE --database MYSQL --databaseName rel_one_many
Created SRC_MAIN_RESOURCES\META-INF\persistence.xml
Created SRC_MAIN_RESOURCES\META-INF\spring\database.properties
please enter your database details in src/main/resources/database.properties
Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext.xml
Managed ROOT\pom.xml
Managed SRC_MAIN_RESOURCES\META-INF\spring\database.properties


El nombre de base de datos que usamos fue "rel_one_many" así que hay que asegurarnos de tener una base de datos con ese nombre en nuestro MySQL.

En el comando "persistence setup" tambien se puede especificar el usuario y password que usaremos para conectarnos a la base de datos con "--userName" y "--password" respectivamente. Como aqui no lo especificamos asi sera necesario especificarlo en el archivo "src/main/resources/database.properties" para que podamos conectarnos a la base de datos sin problemas.

Lo siguiente sera configurar el logging a un nivel de DEBUG.


prueba.springroo.relonetomany roo> logging setup --level DEBUG
Managed SRC_MAIN_RESOURCES\META-INF\spring\log4j.properties


Ahora para propositos de este ejemplo usaremos usaremos las entidades Grupo y Alumno para representar una relación de uno a muchos donde el Grupo tiene uno o mas Alumnos.

Empecemos creando la entidad Grupo con las propiedades: nombre y fecha de registro.


prueba.springroo.relonetomany roo> entity --class prueba.springroo.relonetomany.dominio.Grupo --testAutomatically
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo.java
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoDataOnDemand.java
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoIntegrationTest.java
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_Entity.aj
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_ToString.aj
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_Configurable.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoIntegrationTest_Roo_Configurable.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoDataOnDemand_Roo_DataOnDemand.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoIntegrationTest_Roo_IntegrationTest.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoDataOnDemand_Roo_Configurable.aj
~.dominio.Grupo roo> field string --fieldName nombre --notNull
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo.java
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_JavaBean.aj
Managed SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_ToString.aj
~.dominio.Grupo roo> field date --fieldName fechaRegistro --type java.util.Date --notNull
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo.java
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_JavaBean.aj
Managed SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\GrupoDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_ToString.aj


La siguiente entidad que crearemos sera Alumno, el cual tendrá las propiedades: nombre, apellido, fecha de nacimiento y numero de credencial.


~.dominio.Grupo roo> entity --class prueba.springroo.relonetomany.dominio.Alumno --testAutomatically
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno.java
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand.java
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoIntegrationTest.java
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_Entity.aj
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_ToString.aj
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_Configurable.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoIntegrationTest_Roo_Configurable.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand_Roo_DataOnDemand.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoIntegrationTest_Roo_IntegrationTest.aj
Created SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand_Roo_Configurable.aj
~.dominio.Alumno roo> field string --fieldName nombre --notNull
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno.java
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_JavaBean.aj
Managed SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_ToString.aj
~.dominio.Alumno roo> field date --fieldName fechaNacimiento --type java.util.Date --notNull
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno.java
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_JavaBean.aj
Managed SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_ToString.aj
~.dominio.Alumno roo> field number --fieldName numeroBoleta --type java.lang.Long --notNull
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno.java
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_JavaBean.aj
Managed SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_ToString.aj
~.dominio.Alumno roo> field string --fieldName apellido --notNull
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno.java
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_JavaBean.aj
Managed SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_ToString.aj


Ya teniendo las dos entidades ahora vamos a relacionarlas. Lo primero que haremos sera indicar que la entidad Grupo tendrá muchos Alumnos con el comando "field set":


~.dominio.Alumno roo> field set --fieldName alumnos --element prueba.springroo.relonetomany.dominio.Alumno --class prueba.springroo.relonetomany.dominio.Grupo --mappedBy grupo
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo.java
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Grupo_Roo_ToString.aj


Hay que notar aquí que en el momento en que escribimos el comando Spring Roo estaba bajo el contexto de la entidad Alumno (noten la cadena que hay antes del promt de "roo>" y que dice "~.dominio.Alumno"), por esa razón es necesario usar la opción "--class" para indicarle a que clase se le agregara el campo que se esta creando.

Otro punto en el que hay que poner atención es la opción "--mappedBy" la cual la nombramos como "grupo". Esto le dice a Spring Roo que la relación one-to-many estará mapeada por la propiedad "grupo" en los elementos que están del lado "many" de la relación (los contenidos).

Ahora en con la entidad Alumno hacemos la relación hacia el Grupo usando "field reference":


~.dominio.Grupo roo> field reference --fieldName grupo --class prueba.springroo.relonetomany.dominio.Alumno --type prueba.springroo.relonetomany.dominio.Grupo --notNull
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno.java
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_JavaBean.aj
Managed SRC_TEST_JAVA\prueba\springroo\relonetomany\dominio\AlumnoDataOnDemand_Roo_DataOnDemand.aj
Managed SRC_MAIN_JAVA\prueba\springroo\relonetomany\dominio\Alumno_Roo_ToString.aj


La opción "--type" indica el tipo de la referencia que estamos creando en la entidad.

Ok, las relaciones ya están configuradas. Ahora vamos a crear los controladores web con el comando "controller all" (para crear todos los controladores de cada una de las entidades) dentro del paquete "prueba.springroo.relonetomany.web"


~.dominio.Alumno roo> controller all --package prueba.springroo.relonetomany.web
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\web
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\web\GrupoController.java
Created SRC_MAIN_WEBAPP\WEB-INF\spring
Created SRC_MAIN_WEBAPP\WEB-INF\spring\webmvc-config.xml
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\web\GrupoController_Roo_Controller.aj
Created SRC_MAIN_WEBAPP\images
Created SRC_MAIN_WEBAPP\images\nl.png
Created SRC_MAIN_WEBAPP\images\update.png
Created SRC_MAIN_WEBAPP\images\es.png
Created SRC_MAIN_WEBAPP\images\delete.png
Created SRC_MAIN_WEBAPP\images\add.png
Created SRC_MAIN_WEBAPP\images\resultset_previous.png
Created SRC_MAIN_WEBAPP\images\resultset_next.png
Created SRC_MAIN_WEBAPP\images\favicon.ico
Created SRC_MAIN_WEBAPP\images\banner-graphic.png
Created SRC_MAIN_WEBAPP\images\resultset_last.png
Created SRC_MAIN_WEBAPP\images\gb.png
Created SRC_MAIN_WEBAPP\images\springsource-logo.png
Created SRC_MAIN_WEBAPP\images\it.png
Created SRC_MAIN_WEBAPP\images\show.png
Created SRC_MAIN_WEBAPP\images\sv.png
Created SRC_MAIN_WEBAPP\images\list.png
Created SRC_MAIN_WEBAPP\images\resultset_first.png
Created SRC_MAIN_WEBAPP\images\de.png
Created SRC_MAIN_WEBAPP\styles
Created SRC_MAIN_WEBAPP\styles\standard.css
Created SRC_MAIN_WEBAPP\styles\alt.css
Created SRC_MAIN_WEBAPP\WEB-INF\classes
Created SRC_MAIN_WEBAPP\WEB-INF\classes\standard.properties
Created SRC_MAIN_WEBAPP\WEB-INF\classes\alt.properties
Created SRC_MAIN_WEBAPP\WEB-INF\layouts
Created SRC_MAIN_WEBAPP\WEB-INF\layouts\default.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\layouts\layouts.xml
Created SRC_MAIN_WEBAPP\WEB-INF\views
Created SRC_MAIN_WEBAPP\WEB-INF\views\views.xml
Created SRC_MAIN_WEBAPP\WEB-INF\views\resourceNotFound.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\index.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\uncaughtException.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\dataAccessFailure.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\controller-index.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\tags
Created SRC_MAIN_WEBAPP\WEB-INF\tags\language.tagx
Created SRC_MAIN_WEBAPP\WEB-INF\tags\theme.tagx
Created SRC_MAIN_WEBAPP\WEB-INF\tags\pagination.tagx
Created SRC_MAIN_WEBAPP\WEB-INF\i18n
Created SRC_MAIN_WEBAPP\WEB-INF\i18n\messages_sv.properties
Created SRC_MAIN_WEBAPP\WEB-INF\i18n\messages.properties
Created SRC_MAIN_WEBAPP\WEB-INF\i18n\messages_nl.properties
Created SRC_MAIN_WEBAPP\WEB-INF\i18n\messages_it.properties
Created SRC_MAIN_WEBAPP\WEB-INF\i18n\messages_es.properties
Created SRC_MAIN_WEBAPP\WEB-INF\i18n\messages_de.properties
Created SRC_MAIN_WEBAPP\WEB-INF\i18n\application.properties
Managed SRC_MAIN_WEBAPP\WEB-INF\i18n\application.properties
Created SRC_MAIN_WEBAPP\WEB-INF\views\grupo
Created SRC_MAIN_WEBAPP\WEB-INF\views\grupo\list.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\grupo\show.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\grupo\create.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\menu.jspx
Managed SRC_MAIN_WEBAPP\WEB-INF\i18n\application.properties
Managed SRC_MAIN_WEBAPP\WEB-INF\views\menu.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\grupo\update.jspx
Managed SRC_MAIN_WEBAPP\WEB-INF\i18n\application.properties
Managed SRC_MAIN_WEBAPP\WEB-INF\views\menu.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\grupo\views.xml
Created SRC_MAIN_WEBAPP\WEB-INF\urlrewrite.xml
Created SRC_MAIN_WEBAPP\WEB-INF\web.xml
Managed SRC_MAIN_WEBAPP\WEB-INF\web.xml
Managed ROOT\pom.xml
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\web\AlumnoController.java
Managed SRC_MAIN_WEBAPP\WEB-INF\web.xml
Managed ROOT\pom.xml
Created SRC_MAIN_JAVA\prueba\springroo\relonetomany\web\AlumnoController_Roo_Controller.aj
Created SRC_MAIN_WEBAPP\WEB-INF\views\alumno
Created SRC_MAIN_WEBAPP\WEB-INF\views\alumno\list.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\alumno\show.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\alumno\create.jspx
Managed SRC_MAIN_WEBAPP\WEB-INF\i18n\application.properties
Managed SRC_MAIN_WEBAPP\WEB-INF\views\menu.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\alumno\update.jspx
Managed SRC_MAIN_WEBAPP\WEB-INF\i18n\application.properties
Managed SRC_MAIN_WEBAPP\WEB-INF\views\menu.jspx
Created SRC_MAIN_WEBAPP\WEB-INF\views\alumno\views.xml


Ahora hay que probar todo el código para ver si todo esta bien. Recuerden crear la base de datos, configurar el usuario y password de la base de datos y sobre todo levantar la base de datos para que las pruebas se puedan conectar y ejecutar correctamente. Entonces, para ejecutar las pruebas usamos el comando:


~.web roo> perform tests


el cual nos debe indicar, entre otras cosas, un mensaje "BUILD SUCCESSFUL" y si no fue asi algo hicimos mal (asi que hay que volver a empezar desde el principio de este post).

Para ver todo esto corriendo ya en Tomcat simplemente hay que salirnos de la consola de Spring Roo y en el mismo folder del proyecto ejecutar el comando de maven:


$ mvn tomcat:run


Una vez que este corriendo Tomcat hay que ir a la direccion http://localhost:8080/relacion-onetomany/ y naveguen en la pequeña aplicación para que vean la funcionalidad de la relación one-to-many con Spring Roo.



Notaran que al crear Alumnos si no hay Grupos registrados no les muestra la propiedad para indicar el Grupo al que pertenece el Alumno, pero si crean Grupos y después crean Alumnos ya tienen la posibilidad de seleccionar a que grupo va a pertenecer el Alumno que estén creando.

2 comments:

djose said...

hola espero que estes bien.. e hecho tu dos ejercisio de spring roo pero no se por que me muestra los formularios el me crea la base de datos segun las clases entity y me muestra unas vistas con los menus pero al seleccionar una opcion me dice:

Recurso Solicitado No Encontrado

Lo sentimos, no hemos encontrado el recurso que buscaba.

No entiendo por que si hago exactamento lo mismo que tu tutorial.. alguna idea??

al compilarlo en tomcat los errores que veo son estos no se si tengan q ver:

TomcatAspectJWeavingClassLoader@1c1ac46] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
[TomcatAspectJWeavingClassLoader@1c1ac46] error aspect 'org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl' woven into 'entidad.Persona_Roo_Entity' must be defined to the weaver (placed on the aspectpath, or defined in an aop.xml file if using LTW).
[TomcatAspectJWeavingClassLoader@1c1ac46] error aspect 'org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect' woven into 'entidad.Persona_Roo_Entity' must be defined to the weaver (placed on the aspectpath, or defined in an aop.xml file if using LTW).

gracias..

Rafael Gutiérrez said...

Hola que tal djose,

Que versión de maven tienes instalado? porque he escuchado que tiene Roo tiene problemas del maven 2.0.8 para abajo.

Si tienes una versión anterior, actualizara y vuelve a intentar.