Spring Roo se presenta como una herramienta ligera para hacer más rápido la consecución de resultado instantáneos, el liderazgo de este proyecto con certificación Spring está liderado por la empresa Disid que utiliza Spring Roo en sus proyectos y lleva varios años colaborando con Pivotal en su desarrollo.
El futuro de Spring Roo se muestra claro con este respaldo, después del primer contacto en Spring Roo Ejemplo básico con PostgreSQL en 6 pasos vamos a profundizar algo más. Esta guía de desarrollo la vamos a elaborar con un proyecto sencillo, pero que nos permite entrar con profundidad en la creación automática con Roo, probar los add-ons disponibles, …, como veremos a continuación.
Spring Roo se pretende diferenciar de otras herramientas por:
- Resultados rápidos
- 100% desarrollado en Java
- Fácil de usar
- Rápido y sencillo de borrar
- Totalmente libre
- Comunidad activa
- Integración tecnológica
- Extensión mediante Roo add-ons
- Arquitectura con certificación Spring
Spring Roo
A next-generation rapid application development tool for Java developers. With Roo you can easily build full Java applications in minutes.Spring Roo
Vamos a desarrollar una aplicación desde cero buscando cubrir las principales necesidades que nos encontraremos en un proyecto real, por eso, voy a cambiar el concepto, en anteriores publicaciones hablaba de tutorial, pero no lo es realmente (para eso ya está el de Spring Roo – Reference Documentation), sino más bien una guía en varias publicaciones, algo como: ¿Cómo desarrollar un proyecto con Spring Roo paso a paso? (How to develop a project with Spring Roo step by step?)
Esto es lo que vas a poder ver y probar:
- EL PROYECTO
- CONFIGURACIÓN DEL ENTORNO
- CREACIÓN DE LAS PRIMERAS ENTIDADES
- CREACIÓN Y CONFIGURACIÓN MVC WEB
- AÑADIENDO SPRING SECURITY
- APLICACIÓN MULTIIDIOMA (i18n)
Aplicación Web CRUD, segura y multiidioma con Spring Roo con PostgreSQL
Con Spring Roo definimos nuestra entidades, generamos la aplicación Web CRUD, le añadimos Spring Security y diferentes idiomas para la aplicación desde nuestra consola Roo.Código Xules
Si te gusta esta publicación puedes seguir a Spring Roo en Twitter y hacer un retweeet en alguno de estos tweets sobre la publicación:
Create an @springframework MVC webapp with #SpringRoo (ES) https://t.co/JVHkMkSpO5 Thx @XulesRun! #Java #PostgreSQL pic.twitter.com/l7QnePURcp
— Spring Roo (@SpringRoo) January 22, 2016
También te interesa estar al tanto del espectacular addon de Spring Roo gvNIX, sigue a gvNIX en twitter y haz un retweet si te gusta la publicación:
Aplicación Web CRUD, segura y multiidioma con #SpringRoo https://t.co/faEe5d3DiJ Gran artículo de @XulesRun #OpenSource #Java #PostgreSQL
— gvNIX (@gvNIX) January 27, 2016
1. EL PROYECTO
Vamos a crear un proyecto para comprobar el desarrollo de aplicaciones con el proyecto Spring Roo, no se pretende hacer una explicación exhaustiva del desarrollo de aplicaciones con Spring Roo, sino desarrollar una aplicación con una funcionalidad y una presentación que nos permita analizar en profundidad el funcionamiento de proyecto Spring Roo.
Definición del proyecto
El proyecto consiste en la administración de clientes para diferentes empresas, para ello se plantea la necesidad de tener la información de la empresa y de los clientes, cada empresa podrá tener múltiples clientes, para el caso de estudio se plantea que ambas entidades tengan los campos básicos y direcciones que podrán ser una o varias. Este es un proyecto base que uso en mi proyecto Learning Project consúltalo si necesitas más detalles del proyecto, te diré que se desarrolla con una base de datos propia y que todo el desarrollo se hará desde cero, con la ayuda y documentación que se nos facilita desde Spring Roo documentación.
Vamos a desarrollar una aplicación CRUD con la generación de código que nos proporciona Spring Roo para la base de datos customerdbroo, también, vamos a darle a nuestra aplicación las siguientes características:
- Seguridad: añadiremos control acceso.
- Multiidioma: nuestra aplicación debe soportar varios idiomas.
- Informes: inclusión de informes con JasperReports.
- Look & Fell Web UI: veremos como podemos modificar la presentación web de nuestro proyecto.
- Otras necesidades: según vayamos avanzando con el proyecto iremos profundizando en otras características.
Esquema SQL
Para desarrollar este esquema vamos a necesitar las siguientes tablas, a continuación, se explica su utilidad y algunas características básicas, el resto irá directamente sobre el código SQL, como puedes ver aquí con más detalle, estas son las tablas que utilizaremos:
Learning Project
|
||
TABLA
|
DESCRIPCIÓN
|
CARACTERÍSTICAS DE DISEÑO
|
cb_enterprise
|
Empresas de la aplicación, cada empresa tendrá sus clientes.
|
Las empresas tendrán definido inicialmente: idioma, país y moneda, así como otros campos básicos propios.
|
cb_customer
|
Tabla general de cliente, donde se almacenarán los clientes de las diferentes empresas.
|
Tendrán definido inicialmente: idioma, país, direcciones, empresas, métodos de pago y moneda, así como otros campos básicos propios.
|
cb_addresses
|
Tabla de registro de las direcciones, se asocian aquí las direcciones que tienen un cliente.
|
Registro para asociar las direcciones al cliente, cada cliente tendrá un número ilimitado de direcciones con cb_address relacionado mediante cb_addresses (es básicamente una tabla relacional)
|
cb_address
|
Tabla de dirección donde se guardan los datos de la dirección en sí.
|
Tabla de dirección que tendrá los campos generales de una dirección, así como números de teléfono, transportista y tipos de dirección.
|
cb_language
|
Tabla con los idiomas registrados en la aplicación, se podrá relacionar con múltiples tablas.
|
|
cb_currency
|
Tabla con las monedas registradas en la aplicación, se podrá relacionar con múltiples tablas.
|
|
cb_country
|
Tabla con los países registrados en la aplicación, se podrá relacionar con múltiples tablas.
|
Para cada país se especificará la moneda y el idioma utilizado por defecto.
|
cb_paymentmethod
|
Métodos de pago definidos para el cliente u otras entidades.
|
A continuación, una imagen con el el Esquema E-R de Customerdb donde se muestran las relaciones reales de la base de datos, con los nombres de las claves foráneas, …
El desarrollo de esta base de datos que utilizo en mi proyecto Learning Project lo puedes ver con más detalle en el desarrollo del proyecto con PostgreSQL, aquí explico el lenguaje SQL para su creación, por si quieres verla por ti mismo este es el código SQL la base de datos PostgreSQL para la base de datos customerdb:
PostgreSQL SQL - Creación de las tablas
Como veremos más adelante el nombre que utilizamos para nuestra base de datos que generaremos utilizando la consola de Spring Roo es customerdbroo, así podrás tener las dos bases de datos en paralelo e ir comparando.
2. CONFIGURACIÓN DEL ENTORNO
Preparación del entorno
Para estas pruebas vamos a trabajar con el entorno proporcionado por Spring Tool Suite (STS), aquí puedes descargar la versión que necesites para tu sistema operativo, Spring Tool Suite (STS) proporciona soporte para Spring Roo 2.0.0 está disponible a partir de STS 3.7.0, en el enlace de la descarga encontrarás toda la información.
Ahora vamos a incluir Roo en nuestro STS IDE:
- Abre tu IDE STS
- Abre el cuadro de mandos (dashboard) de STS
- Haz clic en el tab Extensions y busca Spring Roo
- Instala Spring IDE – Roo Extension.
- Reinicia STS
Configurando Spring Roo 2.0.0 en tu STS:
- Selecciona en el menú Window y abre «Preferences > Spring > Roo Support»
- En «Roo Support» pulsamos el botón «Add» para la nueva instalación.
- En «Roo Configure Roo Installation» pulsa el botón «Browse», entonces selecciona el directorio en el que tienes descomprimido Spring Roo 2.0.0
- Confirma la instalación
- Ahora Roo está instalado en tu STS
Con esto ya dejamos nuestro IDE configurado para utilizar Spring Roo.
Creación del proyecto y configuración
Con el IDE STS ya preparado para Spring Roo, vamos a crear el proyecto, para ello nos dirigimos al panel de control (dashboard) donde encontraremos una opción: Spring Roo Project que nos permite generar un proyecto Spring Roo como puedes ver en la imagen:
Ahora en la pantalla de creación de nuevo rellenamos la información que se nos pide como se muestra en la imagen y le damos a siguiente (next):
Una vez hecha la selección nos aparecerá el siguiente mensaje en pantalla: «Please click ‘Finish’ to create the new project using Roo», y solo nos quedará pulsar el botón de FINISH. Ahora ya tenemos nuestro proyecto creado y la consola para Spring Roo que utilizaremos para ir creando la unidad de persistencia, las tablas, y la generación MVC del proyecto web, a continuación, vamos a explicar estos pasos desarrollando nuestro proyecto.
Configuración de PostgreSQL
Vamos a realizar nuestra configuración con PostgreSQL para la base de datos que vamos a crear y que llamaremos customerdbroo.
jpa setup --provider HIBERNATE --database POSTGRES --databaseName customerdbroo
Al ejecutar esto en la consola Roo nos muestra las acciones realizadas, recuerda refrescar el proyecto para recargar los nuevos ficheros creados:
Como puedes ver en la imagen se han creado los ficheros de configuración de la aplicación, la persistencia y el que vamos a tocar ahora database.properties donde completamos el usuario y contraseña de acceso a la base de datos, así quedará finalmente:
#Updated at Wed Nov 04 23:04:43 CET 2015 #Wed Nov 04 23:04:43 CET 2015 database.driverClassName=org.postgresql.Driver database.url=jdbc\:postgresql\://cxserver\:5432/customerdbroo database.username=xulescode database.password=xulescode
Explora los ficheros creados para familiarizarte con el entorno.
3. CREACIÓN DE LAS PRIMERAS ENTIDADES
Como has podido ver este proyecto consta de 8 entidades, en esta primera parte vamos a crear las siguientes: cb_language, cb_currency, cb_country, cb_paymentmethod y cb_enterprise.
Creación de la entidad para cb_language
Ahora ya podemos crear nuestros objetos del dominio y los campos con los definiremos nuestra clase para cb_language. Ahora usaremos el comando entity jpa para crear nuestra entidad, este comando tiene una serie de atributos, los puedes ver en A.18.5. entity jpa con más detalle, los que vamos a utilizar por el momento son:
- –class que nos sirve para especificar con que dominio estamos, y que después, cuando creemos otras tablas, o posteriormente, queramos añadir nuevos campos nos permitirá especificar que entidad estamos modificando.
- –testAutomatically atributo que crea los test de integración para un objeto de dominio.
- –identifierField el nombre del campo id JPA field que e usará para la entidad.
- –identifierColumn The JPA identifier field column to use for this entity.
- –identifierTypeT he data type that will be used for the JPA identifier field (defaults to java.lang.Long).
Una vez aclarado esto creamos la entidad CbLanguage indicando la clave primaria ejecutando en la consola Roo:
entity jpa --class ~.domain.CbLanguage --testAutomatically --identifierField idLanguage --identifierType java.lang.String
&nsbp;
Acuérdate de refrescar el proyecto para ver las acciones realizadas, estas se indican en la consola como sigue:
Created SRC_MAIN_JAVA/org/xulescode/domain Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage.java Created SRC_TEST_JAVA/org/xulescode/domain Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageDataOnDemand.java Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageIntegrationTest.java Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Configurable.aj Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Jpa_Entity.aj Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Jpa_ActiveRecord.aj Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_ToString.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageDataOnDemand_Roo_Configurable.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageDataOnDemand_Roo_DataOnDemand.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageIntegrationTest_Roo_IntegrationTest.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageIntegrationTest_Roo_Configurable.aj
Ahora añadimos los campos, el primero que vamos a añadir es namelanguage que vamos a definir como clave única, para añadir un nuevo campo la estructura es sencilla usamos el comando field: seguido del tipo de dato, ahora podemos usar algunos atributos, en el apartado Field Commands de la documentación de referencia de Spring Roo tienes más atributos disponibles, los que utilizamos aquí son los siguientes:
- –fieldName namelanguage indicamos el nombre del campo
- –notNull indicamos que el campo no puede ser NULL.
- –sizeMax 60 indicamos el tamaño máximo, también podemos indicar el mínimo con sizeMin
- –class ~.domain.CbLanguage como ya expliqué antes nos sirve para indicar con que dominio estamos trabajando, ahora realmente no nos haría falta porque ya estamos trabajando dentro del dominio CbLanguage
- –unique indicamos que este campos es un único, para lo que creamos una clave única en la base de datos, de esto ya se encargar Spring Roo nosotros lo único que haremos es indicarlo con este parámetro.
Con lo que la creación de nuestro primer campo quedaría así:
field string --fieldName namelanguage --notNull --sizeMax 60 --unique --class ~.domain.CbLanguage
Este es el resultado que se muestra en nuestra consola para nuestro primer campo, lo indico simplemente para que te fijes que ahora en la consola estamos trabajando con el dominio CbLanguage (~.domain.CbLanguage roo>):
~.domain.CbLanguage roo>field string --fieldName namelanguage --notNull --sizeMax 60 --unique --class ~.domain.CbLanguage Updated SRC_MAIN_JAVA/org/xulescode/mode/domain/CbLanguage.java Updated SRC_TEST_JAVA/org/xulescode/mode/domain/CbLanguageDataOnDemand_Roo_DataOnDemand.aj Updated SRC_MAIN_JAVA/org/xulescode/mode/domain/CbLanguage_Roo_Jpa_ActiveRecord.aj Created SRC_MAIN_JAVA/org/xulescode/mode/domain/CbLanguage_Roo_JavaBean.aj
Añadimos el resto de campos sin profundizar de momento mucho más:
field string --fieldName isactive --notNull --sizeMax 1 --value "N" field string --fieldName languageiso --sizeMax 2 field string --fieldName countrycode --sizeMax 2 field string --fieldName isbaselanguage --notNull --sizeMax 1 --value "N"
Esta es el resultado de los campos que hemos creado en CbLanguage:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.persistence.Column; import org.springframework.beans.factory.annotation.Value; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idLanguage", identifierType = String.class) public class CbLanguage { /** */ @NotNull @Column(unique = true) @Size(max = 60) private String namelanguage; /** */ @NotNull @Value("N") @Size(max = 1) private String isactive; /** */ @Size(max = 2) private String languageiso; /** */ @Size(max = 2) private String countrycode; /** */ @NotNull @Value("N") @Size(max = 1) private String isbaselanguage; }
Como puedes ver no aparece idlanguage en nuestra clase, esto es debido a que Spring Roo hace está gestión automática, y como, normalmente es un valor que no se presenta al usuario lo gestiona automáticamente, en este proyecto hay tablas en que utilicemos la configuración, pero para está tabla la clave primaria será un valor que introducirá el usuario, como veremos a continuación.
Definiendo nuestra propia clave primaria
Como hacemos para definir nuestra propia clave primaria idlanguage que es una de tipo String y que queremos que sea el propio usuario quién le de valor. Como se puede ver hasta ahora hemos definido nuestra clave primaria en la anotación @RooJpaActiveRecord(identifierField = «idLanguage», identifierType = String.class), con esta indicación y la generación de código de Spring Roo la propiedad idlanguage se define dentro de la clase CbLanguage_Roo_Jpa_Entity.aj y no en CbLanguage, para esto se utiliza AspectJ que es un framewok poderoso y maduro para AOP (Aspect Oriented Programming) que sustenta muchos sistemas a gran escala, este es el código que se genera y que no es es editable:
// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO. // You may push code into the target .java compilation unit if you wish to edit any member(s). package org.xulescode.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Version; import org.xulescode.domain.CbLanguage; privileged aspect CbLanguage_Roo_Jpa_Entity { declare @type: CbLanguage: @Entity; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "idLanguage") private String CbLanguage.idLanguage; @Version @Column(name = "version") private Integer CbLanguage.version; public String CbLanguage.getIdLanguage() { return this.idLanguage; } public void CbLanguage.setIdLanguage(String id) { this.idLanguage = id; } public Integer CbLanguage.getVersion() { return this.version; } public void CbLanguage.setVersion(Integer version) { this.version = version; } }
Como base para este apartado estoy siguiendo la documentación de Spring Roo: 2.6.1. Edit, modify and customize the Roo-generated code, ahora utilicémoslo en nuestro proyecto usando la característica AJDT Refactoring Push-in de AspectJ, que nos permitirá traer la gestión de idlanguage a nuestra clase CbLanguage, veamos como:
- Editamos nuestra clase CbLanguage
- Posicionándonos sobre la declaración de la clase analizamos Cross References.
- Abrimos CbLanguage_Roo_Jpa_Entity.aj
- Hacemos un refactor / push-in para incluirlo en la clase original (a partir de ese momento Spring Roo deja en tus manos la gestión de la propiedad), y así podemos definirla como queramos, por ejemplo, añadir la notación para validar su tamaño (@Size), y mostrarla para que el usuario introduzca su valor.
- Aspect Refactoring > Push in
- Ahora ya aparece en nuestra clase CbLanguage
@Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "idLanguage") private String idLanguage; public String getIdLanguage() { return this.idLanguage; } public void setIdLanguage(String id) { this.idLanguage = id; }
Ahora ya podemos modificar la propiedad como queramos, y por ejemplo, eliminar la opción @GeneratedValue(strategy = GenerationType.AUTO) que no la queríamos y añadir un límite de longitud como queríamos inicialmente.
Si tienes abierta tu consola puedes ver la transmisión de los cambios en la consola Roo:
roo> Updated SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Jpa_ActiveRecord.aj
Finalmente, así es como queda definida nuestra clave primaria idlanguage:
@Id @Column(name = "idLanguage") @Size(max = 6) private String idLanguage;
Todos los comandos que ejecutamos en la consola Roo se almacenan en el archivo log.roo.
Creación de la entidad para cb_currency
Creamos la entidad CbCurrency indicando la clave primaria, que en este caso es un Integer con el nombre idcurrency ejecutando en la consola Roo:
entity jpa --class ~.domain.CbCurrency --testAutomatically --identifierField idcurrency --identifierType java.lang.Integer
Con lo que la creación de nuestro primer campo quedaría así:
roo>field string --fieldName currency --notNull --sizeMax 60 --unique --class ~.domain.CbCurrency ~.domain.CbCurrency roo>field string --fieldName description --notNull --sizeMax 255 ~.domain.CbCurrency roo>field string --fieldName isactive --notNull --sizeMax 1 --value "Y" ~.domain.CbCurrency roo>field string --fieldName isocode --notNull --sizeMax 3 --unique ~.domain.CbCurrency roo>field number --type java.lang.Double --fieldName precisionstd --notNull ~.domain.CbCurrency roo>field number --type java.lang.Double --fieldName precisioncost --notNull ~.domain.CbCurrency roo>field number --type java.lang.Double --fieldName precisionprize --notNull
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbCurrency:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; import org.springframework.beans.factory.annotation.Value; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idcurrency", identifierType = Integer.class) public class CbCurrency { /** */ @NotNull @Column(unique = true) @Size(max = 60) private String currency; /** */ @NotNull @Size(max = 255) private String description; /** */ @NotNull @Value("Y") @Size(max = 1) private String isactive; /** */ @NotNull @Size(max = 3) private String isocode; /** */ @NotNull @Size(max = 10) private String cursymbol; /** */ @NotNull private Double precisionstd; /** */ @NotNull private Double precisioncost; /** */ @NotNull private Double precisionprize; }
Aquí, será donde definamos las monedas para nuestro sistema, y que relacionaremos con países y otras tablas como veremos a continuación.
Creación de la entidad para cb_country
Creamos la entidad CbCountry que será nuestra tabla de países, indicando la clave primaria, que en este caso es un Integer con el nombre idcountry ejecutando en la consola Roo:
entity jpa --class ~.domain.CbCountry --testAutomatically --identifierField idcountry --identifierType java.lang.Integer
Creamos los campos para nuestra clase CbCountry
~.domain.CbCountry roo> field string --fieldName country --sizeMax 100 --unique ~.domain.CbCountry roo> field string --fieldName description --sizeMax 255 ~.domain.CbCountry roo> field string --fieldName countrycode --notNull --sizeMax 2 ~.domain.CbCountry roo> field string --fieldName hasregion --notNull --sizeMax 60 --value "N" ~.domain.CbCountry roo> field string --fieldName regionname --sizeMax 60 ~.domain.CbCountry roo> field string --fieldName expressionphone --sizeMax 20 ~.domain.CbCountry roo> field string --fieldName displaysequence --sizeMax 20 --notNull ~.domain.CbCountry roo> field string --fieldName isdefault --sizeMax 1 --value "N" ~.domain.CbCountry roo> field number --type java.lang.Double --fieldName ibannodigits ~.domain.CbCountry roo> field string --fieldName ibancountry --sizeMax 2 ~.domain.CbCountry roo> field boolean --fieldName isactive --notNull --value true
Profundicemos un poco más en Spring Roo, veamos como podemos relacionar las claves foráneas de nuestros campos de la tabla cb_country, idlanguage que lo tenemos que relacionar con la tabla de idiomas cb_language, es decir, CbLanguage; y idcurrency con la tabla de monedas del país cb_currency, es decir, CbCurrency.
El establecimiento de las relaciones con Spring Roo es muy fácil, realmente no necesitas tener conocimientos sobre las anotaciones JPA necesarias. Para este caso en el que nuestras claves foráneas están compuesta únicamente por el id de las tablas, básicamente utilizamos el comando reference para establecer una relación 1:m entre CbCountry y CbLanguage, por ejemplo, la sintaxis sería:
- field reference –fieldName CAMPO_REFERENCIA –type CLASE-DOMINIO-A-RELACIONAR
- CAMPO_REFERENCIA: idlanguage
- CLASE-DOMINIO-A-RELACIONAR: ~.domain.CbLanguage
Muy sencillo, así que en nuestra consola Roo ejecutamos dos líneas para establecer la relación de claves foráneas con las entidades CbLanguage y CbCurrency:
~.domain.CbCountry roo> field reference --fieldName idlanguage --type ~.domain.CbLanguage ~.domain.CbCountry roo> field reference --fieldName idcurrency --type ~.domain.CbCurrency
Como verás soy un poco pesado incluyendo siempre en que dominio de la consola Roo en la que me encuentro, ahora que estamos empezando me parece importante para no perder de vista que trabajamos en un dominio en concreto y que si, por ejemplo, hemos dejado el proyecto para otro día en la primera línea que introduzcamos debemos indicar a que entidad nos estamos refiriendo añadiendo: –class ~.domain.CbCountry para la entidad CbCountry, esto ya lo he hecho en la creación de la entidadCbCurrency por si no te habías dado cuenta.
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbCountry:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; import org.springframework.beans.factory.annotation.Value; import javax.persistence.ManyToOne; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idcountry", identifierType = Integer.class) public class CbCountry { /** */ @Column(unique = true) @Size(max = 100) private String country; /** */ @Size(max = 255) private String description; /** */ @NotNull @Size(max = 2) private String countrycode; /** */ @NotNull @Value("N") @Size(max = 60) private String hasregion; /** */ @Size(max = 60) private String regionname; /** */ @Size(max = 20) private String expressionphone; /** */ @NotNull @Size(max = 20) private String displaysequence; /** */ @Value("N") @Size(max = 1) private String isdefault; /** */ private Double ibannodigits; /** */ @Size(max = 2) private String ibancountry; /** */ @NotNull @Value("true") private Boolean isactive; /** */ @ManyToOne private CbLanguage idlanguage; /** */ @ManyToOne private CbCurrency idcurrency; }
Creación de la entidad para cb_paymentmethod
Creamos la entidad CbPaymentMethod que será nuestra tabla de métodos de pago, indicando la clave primaria, que en este caso es un Integer con el nombre idpaymentmethod ejecutando en la consola Roo:
roo> entity jpa --class ~.domain.CbPaymentmethod --testAutomatically --identifierField idpaymentmethod --identifierType java.lang.Integer
Creamos los campos para nuestra clase CbPaymentMethod
~.domain.CbPaymentmethod roo>field string --fieldName paymentmethod --sizeMax 100 --notNull --unique ~.domain.CbPaymentmethod roo>field string --fieldName description --sizeMax 150 ~.domain.CbPaymentmethod roo>field string --fieldName paymentterms --sizeMax 250 ~.domain.CbPaymentmethod roo>field string --fieldName paymententity --sizeMax 50
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbPaymentMethod:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idpaymentmethod", identifierType = Integer.class) public class CbPaymentmethod { /** */ @NotNull @Column(unique = true) @Size(max = 100) private String paymentmethod; /** */ @Size(max = 150) private String description; /** */ @Size(max = 250) private String paymentterms; /** */ @Size(max = 50) private String paymententity; }
Creación de la entidad para cb_enterprise
Para finalizar la creación de tablas en esta publicación finalizaremos con la creación de la tabla de empresas, cada una de ellas tendrá sus propios clientes como se puede ver en el esquema SQL. Creamos la entidad CbEnterprise indicando la clave primaria, que en este caso es un Integer con el nombre identerprise ejecutando en la consola Roo:
roo> entity jpa --class ~.domain.CbEnterprise --testAutomatically --identifierField identerprise --identifierType java.lang.Integer
Ahora añadimos el resto de campos de nuestra tabla:
~.domain.CbEnterprise roo>field number --type java.lang.Integer --fieldName identerprise --notNull ~.domain.CbEnterprise roo>field string --fieldName enterprise --sizeMax 150 --notNull --unique ~.domain.CbEnterprise roo>field string --fieldName description --sizeMax 250 ~.domain.CbEnterprise roo>field string --fieldName enterprisealias --sizeMax 100 ~.domain.CbEnterprise roo>field string --fieldName contact --sizeMax 250 ~.domain.CbEnterprise roo>field string --fieldName estate --sizeMax 30 ~.domain.CbEnterprise roo>field number --type java.lang.Double balance ~.domain.CbEnterprise roo>field string --fieldName ei --sizeMax 100 ~.domain.CbEnterprise roo>field string --fieldName enterprisepayer --sizeMax 20
Ya hemos creado nuestra clase CbEnterprise he tenido que cambiar el nombre de un campo ya que state a estate ya que es un nombre que no está permitido como se indica en nuestra consola Roo:
~.domain.CbEnterprise roo> field string --fieldName state --sizeMax 30 Reserved SQL keyword 'state' is not permitted as symbol name
Ahora relacionemos CbEnterprise con CbLanguage, CbCurrency, CbCountry y CbPaymentmethod,
roo>field reference --fieldName idlanguage --type ~.domain.CbLanguage --class ~.domain.CbEnterprise ~.domain.CbEnterprise roo>field reference --fieldName idcurrency --type ~.domain.CbCurrency ~.domain.CbEnterprise roo>field reference --fieldName idcountry --type ~.domain.CbCountry ~.domain.CbEnterprise roo>field reference --fieldName idpaymentmethod --type ~.domain.CbPaymentmethod
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbEnteprise:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; import javax.persistence.ManyToOne; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "identerprise", identifierType = Integer.class) public class CbEnterprise { /** */ @NotNull @Column(unique = true) @Size(max = 150) private String enterprise; /** */ @Size(max = 250) private String description; /** */ @Size(max = 100) private String enterprisealias; /** */ @Size(max = 250) private String contact; /** */ @Size(max = 30) private String estate; /** */ private Double balance; /** */ @Size(max = 100) private String ei; /** */ @Size(max = 20) private String enterprisepayer; /** */ @ManyToOne private CbLanguage idlanguage; /** */ @ManyToOne private CbCurrency idcurrency; /** */ @ManyToOne private CbCountry idcountry; /** */ @ManyToOne private CbPaymentmethod idpaymentmethod; }
Como Borrar un campo en Spring Roo
Es muy fácil confundirse al nombrar un campo, a todos nos ha pasado alguna vez, como hacemos para borrarlo y volverlo a cargar. Pues muy fácil, vamos a nuestra clase creada por ejemplo a CbEnterprise, con la que estamos trabajando ahora, y directamente buscamos un campo por ejemplo enterprisepayer y simplemente lo borramos, este es el código que tenemos que eliminar en CbEnterprise.java:
/** */ @Size(max = 20) private String enterprisepayer;
Y te preguntarás, ¿qué sucede?, pues mira tu consola Roo y lo entenderás, esta detecta el cambio y hace las acciones necesarias para propagar el cambio, esto es lo que te dirá tu consola:
roo> Updated SRC_TEST_JAVA/org/xulescode/domain/CbEnterpriseDataOnDemand_Roo_DataOnDemand.aj Updated SRC_MAIN_JAVA/org/xulescode/domain/CbEnterprise_Roo_Jpa_ActiveRecord.aj Updated SRC_MAIN_JAVA/org/xulescode/domain/CbEnterprise_Roo_JavaBean.aj
Ahora ejecutamos los test que hemos creado automáticamente con el comando para maven perform tests, como se explica con más detalle en el apartado de la documentación de referencia. Utilizando nuestro STS vamos a Run As > Maven test.
4. CREACIÓN Y CONFIGURACIÓN MVC WEB
Siguiendo la referencia del proyecto de ejemplo de la documentación de Spring Roo, a continuación, generamos la aplicación Web con la que gestionaremos los idiomas de la clase CbLanguage, así que para ello vamos a ejecutar los comandos web mvc. En primer lugar usaremos web mvc setup para configurar todos los controladores de la aplicación seguido a continuación del comando web mvc all:
~.domain.CbLanguage roo> web mvc setup ~.domain.CbLanguage roo> web mvc all --package ~.web
Una vez finalizado ya tenemos lista nuestra aplicación para funcionar.
Despliegue del proyecto y pruebas
Antes de ejecutar nuestro proyecto situándonos sobre el fichero pom.xml ejecutamos Run As >Maven install, una vez hecho esto debemos compilar nuestro proyecto, por eso, situándonos desde el mismo sitio ejecutamos ahora Run As >Maven build, y nos aparecerá un menú, tal que así:
Estamos utilizando M2Eclipse que nos proporciona una integración para Apache Maven dentro del IDE, como ves en la foto aparecen varias opciones, en tu caso, aparecerá una sin ninguna definición, y esto es porque aún no has definido ninguna meta (Goal), selecciona uno y donde pone Goals introduce package, que es el comando para compilar nuestro proyecto.
Hecho esto ya estamos listos para ejecutar nuestro proyecto, sitúate encima de él y selecciona la opción Run As > Run on Server. A continuación, te muestro como ejemplo la creación y visualización de una nueva moneda:
Actualizando el fichero de persistencia
Como puedes ver la aplicación está funcionando y lista, con la configuración que tenemos cada vez que ejecutemos el proyecto se creará de nuevo la base de datos, si no queremos esto simplemente editamos nuestro fichero persistence.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database --> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/> <property name="hibernate.connection.charSet" value="UTF-8"/> <!-- Uncomment the following two properties for JBoss only --> <!-- property name="hibernate.validator.apply_to_ddl" value="false" /--> <!-- property name="hibernate.validator.autoregister_listeners" value="false" /--> </properties> </persistence-unit> </persistence>
Aquí, modificamos la propiedad hibernate.hbm2ddl.auto, y la cambiamos de create a update, así, ya no borraremos los datos cada vez que ejecutemos el proyecto.
Añadiendo datos para pruebas vía SQL
Para poder probar mejor nuestra aplicación puedes añadir los datos que te facilito en este script SQL para poblar la base de datos con idiomas, monedas, países,…, este es el script:
PostgreSQL datos para CustomerdbrooPostgreSQL data for Customerdbroo
Acuérdate de modificar la unidad de persistencia si no la base de datos se borrará y creará de nuevo cada vez que ejecutes la aplicación.
Probando la aplicación
Vamos a ver de nuevo ahora nuestra aplicación con los datos que tenemos con las listas de las tablas:
Creando una empresa
Como ejemplo de la aplicación ahora que tenemos paíse, monedas, idiomas y métodos de pago ya creados, vamos a crear una nueva empresa. Accedemos desde el menú a Create new Cb Enterprise y nos aparece la pantalla de la imagen
Rellenamos los datos de la nueva empresa, y como podemos ver sin hacer ninguna programación de código (ya lo ha hecho por nosotros Roo) tenemos cargada la selección de países como se muestra en la imagen:
Después de la creación vemos la nueva empresa creada:
Por último, la lista de empresas actualizada:
5. AÑADIENDO SPRING SECURITY
Ahora vamos a configurar el control de acceso a nuestra aplicación, se creará un acceso vía login, y además veremos como restringir los accesos en frontend Web en función del role del usuario.
Añadimos Spring Security
Darle el acceso de seguridad a la aplicación lo hacemos instalando el Spring Security addon mediante el comando
~.web roo> security setup
Ahora ejecutamos: Run As > Maven install para descargar las librerías que hemos incorporado a nuestro proyecto al ejecutar security setup.
Al ejecutar el comando además de actualizar los ficheros ya existentes y añadir las librerías necesarias a nuestro fichero pom.xml ya que añadimos nuevas dependencias a nuestro proyecto, se crean dos ficheros nuevos:
Created SPRING_CONFIG_ROOT/applicationContext-security.xml Created SRC_MAIN_WEBAPP/WEB-INF/views/login.jspx
- login.jspx con lo que ya tenemos una nueva pantalla de login creada
- applicationContext-security.xml en este fichero será donde configuraremos los controles de acceso.
Configuramos Spring Security
En una primera aproximación hemos añadido control de acceso vía url a cbcountrys y cbenterprises, como puedes hacer de la siguiente forma:
<!-- HTTP security configurations --> <http auto-config="true" use-expressions="true"> <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" /> <logout logout-url="/resources/j_spring_security_logout" /> <!-- Configure these elements to secure URIs in your application --> <intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" /> <intercept-url pattern="/member/**" access="isAuthenticated()" /> <intercept-url pattern="/resources/**" access="permitAll" /> <intercept-url pattern="/login/**" access="permitAll" /> <intercept-url pattern="/**" access="isAuthenticated()" /> <!-- Configure these elements to secure URIs in your application --> <intercept-url pattern="/cbcountrys/**" access="hasRole('ROLE_ADMIN')"/> <intercept-url pattern="/cbenterprises/**" access="hasRole('ROLE_ADMIN')"/> <intercept-url pattern="/static/**" access="permitAll" /> </http>
Usa los usuarios de acceso creados por defecto para probar el sistema:
<!-- Configure Authentication mechanism --> <authentication-manager alias="authenticationManager"> <!-- SHA-256 values can be produced using 'echo -n your_desired_password | sha256sum' (using normal *nix environments) --> <authentication-provider> <password-encoder hash="sha-256" /> <user-service> <user name="admin" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" authorities="ROLE_ADMIN" /> <user name="user" password="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
Ejecuta el proyecto para ver el resultado, está será la pantalla de login que se ha creado por defecto:
Con Spring Roo también podemos configurar desde los controladores creados los accesos al borrado y actualización de nuestras entidades, por ejemplo, en el controlador CbEnterpriseController.java, vamos a ver como limitamos esto ajustando la anotación @RooWebScaffold, como se muestra en el ejemplo:
package org.xulescode.web; import org.springframework.roo.addon.web.mvc.controller.annotations.scaffold.RooWebScaffold; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.xulescode.domain.CbEnterprise; @RequestMapping("/cbenterprises") @Controller @RooWebScaffold(path = "cbenterprises", formBackingObject = CbEnterprise.class, delete=false, update=false) public class CbEnterpriseController { }
Estas anotaciones notificarán al shell de Roo para eliminar los métodos d delete y update de CbEnterpriseController, y también, ajustar las vistas relacionadas.
6. APLICACIÓN MULTIIDIOMA (i18n)
Incorporar más idiomas a nuestra aplicación es muy sencillo con Spring Roo simplemente tenemos que ejecutar web mvc language –code es para añadir el idioma español, simplemente ejecuta el mismo código con el código iso de i18n del idioma que quieras añadir y listo.
roo>web mvc language --code es Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_es.properties Created SRC_MAIN_WEBAPP/images/es.png Updated SRC_MAIN_WEBAPP/WEB-INF/views/footer.jspx
Este es el resultado:
Traduciendo nuestra aplicación
Como vimos en la imagen anterior las traducciones al español de la pantalla de login ya vienen configuradas por defecto, como se mostró en la consola Roo se crea un nuevo fichero para almacenar las traducciones español: messages_es.properties, aquí puedes ver la estructura y la carpeta i18n:
#menu global_menu_new=Crear nuevo {0} global_menu_list=Listar {0} global_menu_find=Buscar por {0} global_language_switch=Cambiar idioma a {0} global_language=Idioma global_sponsored=Patrocinado por SpringSource global_theme=Tema global_theme_alt=alt global_theme_standard=estándar global_generic={0} #welcome page welcome_titlepane=Bienvenido a {0} welcome_h3=Bienvenido a {0} welcome_text=Spring Roo proporciona herramientas interactivas, ligeras y adaptables al usuario que permiten entregar rápidamente aplicaciones empresariales Java de alto rendimiento.
Simplemente editamos el fichero messages_es.properties para completar las traducciones de nuestra de los mensajes de la aplicación. Para traducir todos los campos de nuestra aplicación necesitamos crear un nuevo fichero aplication_es.properties y ahí realizar las traducciones de los campos de nuestras clases:
application_name=Gestión de clientes label_org_xulescode_domain_cbcountry=País label_org_xulescode_domain_cbcountry_country=País label_org_xulescode_domain_cbcountry_countrycode=Código país label_org_xulescode_domain_cbcountry_description=Descripción label_org_xulescode_domain_cbcountry_displaysequence=Secuencia display label_org_xulescode_domain_cbcountry_expressionphone=Expresión teléfono label_org_xulescode_domain_cbcountry_hasregion=Tiene región label_org_xulescode_domain_cbcountry_ibancountry=País Iban label_org_xulescode_domain_cbcountry_ibannodigits=Nº dígitos Iban label_org_xulescode_domain_cbcountry_idcountry=id país label_org_xulescode_domain_cbcountry_idcountry_=Idcountry_ label_org_xulescode_domain_cbcountry_idcurrency=Moneda label_org_xulescode_domain_cbcountry_idlanguage=Idioma label_org_xulescode_domain_cbcountry_isactive=Activo label_org_xulescode_domain_cbcountry_isdefault=Por defecto label_org_xulescode_domain_cbcountry_plural=Países label_org_xulescode_domain_cbcountry_regionname=Región label_org_xulescode_domain_cbcountry_version=Versión label_org_xulescode_domain_cbcurrency=Moneda label_org_xulescode_domain_cbcurrency_currency=Moneda label_org_xulescode_domain_cbcurrency_cursymbol=Símbolo label_org_xulescode_domain_cbcurrency_description=Descripción label_org_xulescode_domain_cbcurrency_idcurrency=id moneda label_org_xulescode_domain_cbcurrency_idcurrency_=Idcurrency_ label_org_xulescode_domain_cbcurrency_idlanguage=Idioma label_org_xulescode_domain_cbcurrency_isactive=Activo label_org_xulescode_domain_cbcurrency_isocode=Código Iso label_org_xulescode_domain_cbcurrency_plural=Monedas ...
Así es como queda ahora:
Documentación utilizada
- Spring Roo Project: página principal del proyecto, desde aquí puedes acceder a toda la documentación (inglés).
- Spring Roo and JPA Entities: explicación y aclaración de las relaciones entre entidades en Spring Roo (inglés).
- Appendix A. Command Index: aquí encontrarás todos los comandos de Spring Roo listados alfabéticamente, con ellos se incluyen también las opciones que acepta cada uno.
- Apache Maven
- Maven in five minutes: por si no tienes ningún conocimiento sobre Maven, aquí tienes una introducción básica.
- Para preguntas sobre Spring Roo podemos usar StackOverflow , donde nos ayudarán a resolver nuestras dudas y ayudar con ello a conocer mejor la herramienta.
- Complementos (add-ons): aunque lo probaré en una nueva publicación me parece muy interesante para el desarrollo con Spring Roo el add-on suite: gvNIX, que incluye funcionalidades como integración con jQuery, Bootstrap, Dandelion-datatables, auditoria con Histórico de cambios, Jasper Reports,…
Espero que te haya sido útilXules
Guía Spring Roo 2
Estas son algunas de las ideas para la siguiente publicación:
- Finalizar el desarrollo de las entidades
- Añadir el add-on suite: gvNIX
- Modificar la presentación de los elementos
- Añadir informes con JasperReports
- …
Nos vemos pronto: …
Sorry the english version is not available yet
Spring Roo se presenta como una herramienta ligera para hacer más rápido la consecución de resultado instantáneos, el liderazgo de este proyecto con certificación Spring está liderado por la empresa Disid que utiliza Spring Roo en sus proyectos y lleva varios años colaborando con Pivotal en su desarrollo.
El futuro de Spring Roo se muestra claro con este respaldo, después del primer contacto en Spring Roo Ejemplo básico con PostgreSQL en 6 pasos vamos a profundizar algo más. Esta guía de desarrollo la vamos a elaborar con un proyecto sencillo, pero que nos permite entrar con profundidad en la creación automática con Roo, probar los add-ons disponibles, …, como veremos a continuación.
Spring Roo se pretende diferenciar de otras herramientas por:
- Resultados rápidos
- 100% desarrollado en Java
- Fácil de usar
- Rápido y sencillo de borrar
- Totalmente libre
- Comunidad activa
- Integración tecnológica
- Extensión mediante Roo add-ons
- Arquitectura con certificación Spring
Spring Roo
A next-generation rapid application development tool for Java developers. With Roo you can easily build full Java applications in minutes.Spring Roo
Vamos a desarrollar una aplicación desde cero buscando cubrir las principales necesidades que nos encontraremos en un proyecto real, por eso, voy a cambiar el concepto, en anteriores publicaciones hablaba de tutorial, pero no lo es realmente (para eso ya está el de Spring Roo – Reference Documentation), sino más bien una guía en varias publicaciones, algo como: ¿Cómo desarrollar un proyecto con Spring Roo paso a paso? (How to develop a project with Spring Roo step by step?)
Esto es lo que vas a poder ver y probar:
- EL PROYECTO
- CONFIGURACIÓN DEL ENTORNO
- CREACIÓN DE LAS PRIMERAS ENTIDADES
- CREACIÓN Y CONFIGURACIÓN MVC WEB
- AÑADIENDO SPRING SECURITY
- APLICACIÓN MULTIIDIOMA (i18n)
Aplicación Web CRUD, segura y multiidioma con Spring Roo con PostgreSQL
Con Spring Roo definimos nuestra entidades, generamos la aplicación Web CRUD, le añadimos Spring Security y diferentes idiomas para la aplicación desde nuestra consola Roo.Código Xules
1. EL PROYECTO
Vamos a crear un proyecto para comprobar el desarrollo de aplicaciones con el proyecto Spring Roo, no se pretende hacer una explicación exhaustiva del desarrollo de aplicaciones con Spring Roo, sino desarrollar una aplicación con una funcionalidad y una presentación que nos permita analizar en profundidad el funcionamiento de proyecto Spring Roo.
Definición del proyecto
El proyecto consiste en la administración de clientes para diferentes empresas, para ello se plantea la necesidad de tener la información de la empresa y de los clientes, cada empresa podrá tener múltiples clientes, para el caso de estudio se plantea que ambas entidades tengan los campos básicos y direcciones que podrán ser una o varias. Este es un proyecto base que uso en mi proyecto Learning Project consúltalo si necesitas más detalles del proyecto, te diré que se desarrolla con una base de datos propia y que todo el desarrollo se hará desde cero, con la ayuda y documentación que se nos facilita desde Spring Roo documentación.
Vamos a desarrollar una aplicación CRUD con la generación de código que nos proporciona Spring Roo para la base de datos customerdbroo, también, vamos a darle a nuestra aplicación las siguientes características:
- Seguridad: añadiremos control acceso.
- Multiidioma: nuestra aplicación debe soportar varios idiomas.
- Informes: inclusión de informes con JasperReports.
- Look & Fell Web UI: veremos como podemos modificar la presentación web de nuestro proyecto.
- Otras necesidades: según vayamos avanzando con el proyecto iremos profundizando en otras características.
Esquema SQL
Para desarrollar este esquema vamos a necesitar las siguientes tablas, a continuación, se explica su utilidad y algunas características básicas, el resto irá directamente sobre el código SQL, como puedes ver aquí con más detalle, estas son las tablas que utilizaremos:
Learning Project
|
||
TABLA
|
DESCRIPCIÓN
|
CARACTERÍSTICAS DE DISEÑO
|
cb_enterprise
|
Empresas de la aplicación, cada empresa tendrá sus clientes.
|
Las empresas tendrán definido inicialmente: idioma, país y moneda, así como otros campos básicos propios.
|
cb_customer
|
Tabla general de cliente, donde se almacenarán los clientes de las diferentes empresas.
|
Tendrán definido inicialmente: idioma, país, direcciones, empresas, métodos de pago y moneda, así como otros campos básicos propios.
|
cb_addresses
|
Tabla de registro de las direcciones, se asocian aquí las direcciones que tienen un cliente.
|
Registro para asociar las direcciones al cliente, cada cliente tendrá un número ilimitado de direcciones con cb_address relacionado mediante cb_addresses (es básicamente una tabla relacional)
|
cb_address
|
Tabla de dirección donde se guardan los datos de la dirección en sí.
|
Tabla de dirección que tendrá los campos generales de una dirección, así como números de teléfono, transportista y tipos de dirección.
|
cb_language
|
Tabla con los idiomas registrados en la aplicación, se podrá relacionar con múltiples tablas.
|
|
cb_currency
|
Tabla con las monedas registradas en la aplicación, se podrá relacionar con múltiples tablas.
|
|
cb_country
|
Tabla con los países registrados en la aplicación, se podrá relacionar con múltiples tablas.
|
Para cada país se especificará la moneda y el idioma utilizado por defecto.
|
cb_paymentmethod
|
Métodos de pago definidos para el cliente u otras entidades.
|
A continuación, una imagen con el el Esquema E-R de Customerdb donde se muestran las relaciones reales de la base de datos, con los nombres de las claves foráneas, …
El desarrollo de esta base de datos que utilizo en mi proyecto Learning Project lo puedes ver con más detalle en el desarrollo del proyecto con PostgreSQL, aquí explico el lenguaje SQL para su creación, por si quieres verla por ti mismo este es el código SQL la base de datos PostgreSQL para la base de datos customerdb:
PostgreSQL SQL - Creación de las tablas
Como veremos más adelante el nombre que utilizamos para nuestra base de datos que generaremos utilizando la consola de Spring Roo es customerdbroo, así podrás tener las dos bases de datos en paralelo e ir comparando.
2. CONFIGURACIÓN DEL ENTORNO
Preparación del entorno
Para estas pruebas vamos a trabajar con el entorno proporcionado por Spring Tool Suite (STS), aquí puedes descargar la versión que necesites para tu sistema operativo, Spring Tool Suite (STS) proporciona soporte para Spring Roo 2.0.0 está disponible a partir de STS 3.7.0, en el enlace de la descarga encontrarás toda la información.
Ahora vamos a incluir Roo en nuestro STS IDE:
- Abre tu IDE STS
- Abre el cuadro de mandos (dashboard) de STS
- Haz clic en el tab Extensions y busca Spring Roo
- Instala Spring IDE – Roo Extension.
- Reinicia STS
Configurando Spring Roo 2.0.0 en tu STS:
- Selecciona en el menú Window y abre «Preferences > Spring > Roo Support»
- En «Roo Support» pulsamos el botón «Add» para la nueva instalación.
- En «Roo Configure Roo Installation» pulsa el botón «Browse», entonces selecciona el directorio en el que tienes descomprimido Spring Roo 2.0.0
- Confirma la instalación
- Ahora Roo está instalado en tu STS
Con esto ya dejamos nuestro IDE configurado para utilizar Spring Roo.
Creación del proyecto y configuración
Con el IDE STS ya preparado para Spring Roo, vamos a crear el proyecto, para ello nos dirigimos al panel de control (dashboard) donde encontraremos una opción: Spring Roo Project que nos permite generar un proyecto Spring Roo como puedes ver en la imagen:
Ahora en la pantalla de creación de nuevo rellenamos la información que se nos pide como se muestra en la imagen y le damos a siguiente (next):
Una vez hecha la selección nos aparecerá el siguiente mensaje en pantalla: «Please click ‘Finish’ to create the new project using Roo», y solo nos quedará pulsar el botón de FINISH. Ahora ya tenemos nuestro proyecto creado y la consola para Spring Roo que utilizaremos para ir creando la unidad de persistencia, las tablas, y la generación MVC del proyecto web, a continuación, vamos a explicar estos pasos desarrollando nuestro proyecto.
Configuración de PostgreSQL
Vamos a realizar nuestra configuración con PostgreSQL para la base de datos que vamos a crear y que llamaremos customerdbroo.
jpa setup --provider HIBERNATE --database POSTGRES --databaseName customerdbroo
Al ejecutar esto en la consola Roo nos muestra las acciones realizadas, recuerda refrescar el proyecto para recargar los nuevos ficheros creados:
Como puedes ver en la imagen se han creado los ficheros de configuración de la aplicación, la persistencia y el que vamos a tocar ahora database.properties donde completamos el usuario y contraseña de acceso a la base de datos, así quedará finalmente:
#Updated at Wed Nov 04 23:04:43 CET 2015 #Wed Nov 04 23:04:43 CET 2015 database.driverClassName=org.postgresql.Driver database.url=jdbc\:postgresql\://cxserver\:5432/customerdbroo database.username=xulescode database.password=xulescode
Explora los ficheros creados para familiarizarte con el entorno.
3. CREACIÓN DE LAS PRIMERAS ENTIDADES
Como has podido ver este proyecto consta de 8 entidades, en esta primera parte vamos a crear las siguientes: cb_language, cb_currency, cb_country, cb_paymentmethod y cb_enterprise.
Creación de la entidad para cb_language
Ahora ya podemos crear nuestros objetos del dominio y los campos con los definiremos nuestra clase para cb_language. Ahora usaremos el comando entity jpa para crear nuestra entidad, este comando tiene una serie de atributos, los puedes ver en A.18.5. entity jpa con más detalle, los que vamos a utilizar por el momento son:
- –class que nos sirve para especificar con que dominio estamos, y que después, cuando creemos otras tablas, o posteriormente, queramos añadir nuevos campos nos permitirá especificar que entidad estamos modificando.
- –testAutomatically atributo que crea los test de integración para un objeto de dominio.
- –identifierField el nombre del campo id JPA field que e usará para la entidad.
- –identifierColumn The JPA identifier field column to use for this entity.
- –identifierTypeT he data type that will be used for the JPA identifier field (defaults to java.lang.Long).
Una vez aclarado esto creamos la entidad CbLanguage indicando la clave primaria ejecutando en la consola Roo:
entity jpa --class ~.domain.CbLanguage --testAutomatically --identifierField idLanguage --identifierType java.lang.String
&nsbp;
Acuérdate de refrescar el proyecto para ver las acciones realizadas, estas se indican en la consola como sigue:
Created SRC_MAIN_JAVA/org/xulescode/domain Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage.java Created SRC_TEST_JAVA/org/xulescode/domain Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageDataOnDemand.java Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageIntegrationTest.java Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Configurable.aj Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Jpa_Entity.aj Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Jpa_ActiveRecord.aj Created SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_ToString.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageDataOnDemand_Roo_Configurable.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageDataOnDemand_Roo_DataOnDemand.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageIntegrationTest_Roo_IntegrationTest.aj Created SRC_TEST_JAVA/org/xulescode/domain/CbLanguageIntegrationTest_Roo_Configurable.aj
Ahora añadimos los campos, el primero que vamos a añadir es namelanguage que vamos a definir como clave única, para añadir un nuevo campo la estructura es sencilla usamos el comando field: seguido del tipo de dato, ahora podemos usar algunos atributos, en el apartado Field Commands de la documentación de referencia de Spring Roo tienes más atributos disponibles, los que utilizamos aquí son los siguientes:
- –fieldName namelanguage indicamos el nombre del campo
- –notNull indicamos que el campo no puede ser NULL.
- –sizeMax 60 indicamos el tamaño máximo, también podemos indicar el mínimo con sizeMin
- –class ~.domain.CbLanguage como ya expliqué antes nos sirve para indicar con que dominio estamos trabajando, ahora realmente no nos haría falta porque ya estamos trabajando dentro del dominio CbLanguage
- –unique indicamos que este campos es un único, para lo que creamos una clave única en la base de datos, de esto ya se encargar Spring Roo nosotros lo único que haremos es indicarlo con este parámetro.
Con lo que la creación de nuestro primer campo quedaría así:
field string --fieldName namelanguage --notNull --sizeMax 60 --unique --class ~.domain.CbLanguage
Este es el resultado que se muestra en nuestra consola para nuestro primer campo, lo indico simplemente para que te fijes que ahora en la consola estamos trabajando con el dominio CbLanguage (~.domain.CbLanguage roo>):
~.domain.CbLanguage roo>field string --fieldName namelanguage --notNull --sizeMax 60 --unique --class ~.domain.CbLanguage Updated SRC_MAIN_JAVA/org/xulescode/mode/domain/CbLanguage.java Updated SRC_TEST_JAVA/org/xulescode/mode/domain/CbLanguageDataOnDemand_Roo_DataOnDemand.aj Updated SRC_MAIN_JAVA/org/xulescode/mode/domain/CbLanguage_Roo_Jpa_ActiveRecord.aj Created SRC_MAIN_JAVA/org/xulescode/mode/domain/CbLanguage_Roo_JavaBean.aj
Añadimos el resto de campos sin profundizar de momento mucho más:
field string --fieldName isactive --notNull --sizeMax 1 --value "N" field string --fieldName languageiso --sizeMax 2 field string --fieldName countrycode --sizeMax 2 field string --fieldName isbaselanguage --notNull --sizeMax 1 --value "N"
Esta es el resultado de los campos que hemos creado en CbLanguage:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.persistence.Column; import org.springframework.beans.factory.annotation.Value; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idLanguage", identifierType = String.class) public class CbLanguage { /** */ @NotNull @Column(unique = true) @Size(max = 60) private String namelanguage; /** */ @NotNull @Value("N") @Size(max = 1) private String isactive; /** */ @Size(max = 2) private String languageiso; /** */ @Size(max = 2) private String countrycode; /** */ @NotNull @Value("N") @Size(max = 1) private String isbaselanguage; }
Como puedes ver no aparece idlanguage en nuestra clase, esto es debido a que Spring Roo hace está gestión automática, y como, normalmente es un valor que no se presenta al usuario lo gestiona automáticamente, en este proyecto hay tablas en que utilicemos la configuración, pero para está tabla la clave primaria será un valor que introducirá el usuario, como veremos a continuación.
Definiendo nuestra propia clave primaria
Como hacemos para definir nuestra propia clave primaria idlanguage que es una de tipo String y que queremos que sea el propio usuario quién le de valor. Como se puede ver hasta ahora hemos definido nuestra clave primaria en la anotación @RooJpaActiveRecord(identifierField = «idLanguage», identifierType = String.class), con esta indicación y la generación de código de Spring Roo la propiedad idlanguage se define dentro de la clase CbLanguage_Roo_Jpa_Entity.aj y no en CbLanguage, para esto se utiliza AspectJ que es un framewok poderoso y maduro para AOP (Aspect Oriented Programming) que sustenta muchos sistemas a gran escala, este es el código que se genera y que no es es editable:
// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO. // You may push code into the target .java compilation unit if you wish to edit any member(s). package org.xulescode.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Version; import org.xulescode.domain.CbLanguage; privileged aspect CbLanguage_Roo_Jpa_Entity { declare @type: CbLanguage: @Entity; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "idLanguage") private String CbLanguage.idLanguage; @Version @Column(name = "version") private Integer CbLanguage.version; public String CbLanguage.getIdLanguage() { return this.idLanguage; } public void CbLanguage.setIdLanguage(String id) { this.idLanguage = id; } public Integer CbLanguage.getVersion() { return this.version; } public void CbLanguage.setVersion(Integer version) { this.version = version; } }
Como base para este apartado estoy siguiendo la documentación de Spring Roo: 2.6.1. Edit, modify and customize the Roo-generated code, ahora utilicémoslo en nuestro proyecto usando la característica AJDT Refactoring Push-in de AspectJ, que nos permitirá traer la gestión de idlanguage a nuestra clase CbLanguage, veamos como:
- Editamos nuestra clase CbLanguage
- Posicionándonos sobre la declaración de la clase analizamos Cross References.
- Abrimos CbLanguage_Roo_Jpa_Entity.aj
- Hacemos un refactor / push-in para incluirlo en la clase original (a partir de ese momento Spring Roo deja en tus manos la gestión de la propiedad), y así podemos definirla como queramos, por ejemplo, añadir la notación para validar su tamaño (@Size), y mostrarla para que el usuario introduzca su valor.
- Aspect Refactoring > Push in
- Ahora ya aparece en nuestra clase CbLanguage
@Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "idLanguage") private String idLanguage; public String getIdLanguage() { return this.idLanguage; } public void setIdLanguage(String id) { this.idLanguage = id; }
Ahora ya podemos modificar la propiedad como queramos, y por ejemplo, eliminar la opción @GeneratedValue(strategy = GenerationType.AUTO) que no la queríamos y añadir un límite de longitud como queríamos inicialmente.
Si tienes abierta tu consola puedes ver la transmisión de los cambios en la consola Roo:
roo> Updated SRC_MAIN_JAVA/org/xulescode/domain/CbLanguage_Roo_Jpa_ActiveRecord.aj
Finalmente, así es como queda definida nuestra clave primaria idlanguage:
@Id @Column(name = "idLanguage") @Size(max = 6) private String idLanguage;
Todos los comandos que ejecutamos en la consola Roo se almacenan en el archivo log.roo.
Creación de la entidad para cb_currency
Creamos la entidad CbCurrency indicando la clave primaria, que en este caso es un Integer con el nombre idcurrency ejecutando en la consola Roo:
entity jpa --class ~.domain.CbCurrency --testAutomatically --identifierField idcurrency --identifierType java.lang.Integer
Con lo que la creación de nuestro primer campo quedaría así:
roo>field string --fieldName currency --notNull --sizeMax 60 --unique --class ~.domain.CbCurrency ~.domain.CbCurrency roo>field string --fieldName description --notNull --sizeMax 255 ~.domain.CbCurrency roo>field string --fieldName isactive --notNull --sizeMax 1 --value "Y" ~.domain.CbCurrency roo>field string --fieldName isocode --notNull --sizeMax 3 --unique ~.domain.CbCurrency roo>field number --type java.lang.Double --fieldName precisionstd --notNull ~.domain.CbCurrency roo>field number --type java.lang.Double --fieldName precisioncost --notNull ~.domain.CbCurrency roo>field number --type java.lang.Double --fieldName precisionprize --notNull
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbCurrency:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; import org.springframework.beans.factory.annotation.Value; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idcurrency", identifierType = Integer.class) public class CbCurrency { /** */ @NotNull @Column(unique = true) @Size(max = 60) private String currency; /** */ @NotNull @Size(max = 255) private String description; /** */ @NotNull @Value("Y") @Size(max = 1) private String isactive; /** */ @NotNull @Size(max = 3) private String isocode; /** */ @NotNull @Size(max = 10) private String cursymbol; /** */ @NotNull private Double precisionstd; /** */ @NotNull private Double precisioncost; /** */ @NotNull private Double precisionprize; }
Aquí, será donde definamos las monedas para nuestro sistema, y que relacionaremos con países y otras tablas como veremos a continuación.
Creación de la entidad para cb_country
Creamos la entidad CbCountry que será nuestra tabla de países, indicando la clave primaria, que en este caso es un Integer con el nombre idcountry ejecutando en la consola Roo:
entity jpa --class ~.domain.CbCountry --testAutomatically --identifierField idcountry --identifierType java.lang.Integer
Creamos los campos para nuestra clase CbCountry
~.domain.CbCountry roo> field string --fieldName country --sizeMax 100 --unique ~.domain.CbCountry roo> field string --fieldName description --sizeMax 255 ~.domain.CbCountry roo> field string --fieldName countrycode --notNull --sizeMax 2 ~.domain.CbCountry roo> field string --fieldName hasregion --notNull --sizeMax 60 --value "N" ~.domain.CbCountry roo> field string --fieldName regionname --sizeMax 60 ~.domain.CbCountry roo> field string --fieldName expressionphone --sizeMax 20 ~.domain.CbCountry roo> field string --fieldName displaysequence --sizeMax 20 --notNull ~.domain.CbCountry roo> field string --fieldName isdefault --sizeMax 1 --value "N" ~.domain.CbCountry roo> field number --type java.lang.Double --fieldName ibannodigits ~.domain.CbCountry roo> field string --fieldName ibancountry --sizeMax 2 ~.domain.CbCountry roo> field boolean --fieldName isactive --notNull --value true
Profundicemos un poco más en Spring Roo, veamos como podemos relacionar las claves foráneas de nuestros campos de la tabla cb_country, idlanguage que lo tenemos que relacionar con la tabla de idiomas cb_language, es decir, CbLanguage; y idcurrency con la tabla de monedas del país cb_currency, es decir, CbCurrency.
El establecimiento de las relaciones con Spring Roo es muy fácil, realmente no necesitas tener conocimientos sobre las anotaciones JPA necesarias. Para este caso en el que nuestras claves foráneas están compuesta únicamente por el id de las tablas, básicamente utilizamos el comando reference para establecer una relación 1:m entre CbCountry y CbLanguage, por ejemplo, la sintaxis sería:
- field reference –fieldName CAMPO_REFERENCIA –type CLASE-DOMINIO-A-RELACIONAR
- CAMPO_REFERENCIA: idlanguage
- CLASE-DOMINIO-A-RELACIONAR: ~.domain.CbLanguage
Muy sencillo, así que en nuestra consola Roo ejecutamos dos líneas para establecer la relación de claves foráneas con las entidades CbLanguage y CbCurrency:
~.domain.CbCountry roo> field reference --fieldName idlanguage --type ~.domain.CbLanguage ~.domain.CbCountry roo> field reference --fieldName idcurrency --type ~.domain.CbCurrency
Como verás soy un poco pesado incluyendo siempre en que dominio de la consola Roo en la que me encuentro, ahora que estamos empezando me parece importante para no perder de vista que trabajamos en un dominio en concreto y que si, por ejemplo, hemos dejado el proyecto para otro día en la primera línea que introduzcamos debemos indicar a que entidad nos estamos refiriendo añadiendo: –class ~.domain.CbCountry para la entidad CbCountry, esto ya lo he hecho en la creación de la entidadCbCurrency por si no te habías dado cuenta.
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbCountry:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; import org.springframework.beans.factory.annotation.Value; import javax.persistence.ManyToOne; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idcountry", identifierType = Integer.class) public class CbCountry { /** */ @Column(unique = true) @Size(max = 100) private String country; /** */ @Size(max = 255) private String description; /** */ @NotNull @Size(max = 2) private String countrycode; /** */ @NotNull @Value("N") @Size(max = 60) private String hasregion; /** */ @Size(max = 60) private String regionname; /** */ @Size(max = 20) private String expressionphone; /** */ @NotNull @Size(max = 20) private String displaysequence; /** */ @Value("N") @Size(max = 1) private String isdefault; /** */ private Double ibannodigits; /** */ @Size(max = 2) private String ibancountry; /** */ @NotNull @Value("true") private Boolean isactive; /** */ @ManyToOne private CbLanguage idlanguage; /** */ @ManyToOne private CbCurrency idcurrency; }
Creación de la entidad para cb_paymentmethod
Creamos la entidad CbPaymentMethod que será nuestra tabla de métodos de pago, indicando la clave primaria, que en este caso es un Integer con el nombre idpaymentmethod ejecutando en la consola Roo:
roo> entity jpa --class ~.domain.CbPaymentmethod --testAutomatically --identifierField idpaymentmethod --identifierType java.lang.Integer
Creamos los campos para nuestra clase CbPaymentMethod
~.domain.CbPaymentmethod roo>field string --fieldName paymentmethod --sizeMax 100 --notNull --unique ~.domain.CbPaymentmethod roo>field string --fieldName description --sizeMax 150 ~.domain.CbPaymentmethod roo>field string --fieldName paymentterms --sizeMax 250 ~.domain.CbPaymentmethod roo>field string --fieldName paymententity --sizeMax 50
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbPaymentMethod:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "idpaymentmethod", identifierType = Integer.class) public class CbPaymentmethod { /** */ @NotNull @Column(unique = true) @Size(max = 100) private String paymentmethod; /** */ @Size(max = 150) private String description; /** */ @Size(max = 250) private String paymentterms; /** */ @Size(max = 50) private String paymententity; }
Creación de la entidad para cb_enterprise
Para finalizar la creación de tablas en esta publicación finalizaremos con la creación de la tabla de empresas, cada una de ellas tendrá sus propios clientes como se puede ver en el esquema SQL. Creamos la entidad CbEnterprise indicando la clave primaria, que en este caso es un Integer con el nombre identerprise ejecutando en la consola Roo:
roo> entity jpa --class ~.domain.CbEnterprise --testAutomatically --identifierField identerprise --identifierType java.lang.Integer
Ahora añadimos el resto de campos de nuestra tabla:
~.domain.CbEnterprise roo>field number --type java.lang.Integer --fieldName identerprise --notNull ~.domain.CbEnterprise roo>field string --fieldName enterprise --sizeMax 150 --notNull --unique ~.domain.CbEnterprise roo>field string --fieldName description --sizeMax 250 ~.domain.CbEnterprise roo>field string --fieldName enterprisealias --sizeMax 100 ~.domain.CbEnterprise roo>field string --fieldName contact --sizeMax 250 ~.domain.CbEnterprise roo>field string --fieldName estate --sizeMax 30 ~.domain.CbEnterprise roo>field number --type java.lang.Double balance ~.domain.CbEnterprise roo>field string --fieldName ei --sizeMax 100 ~.domain.CbEnterprise roo>field string --fieldName enterprisepayer --sizeMax 20
Ya hemos creado nuestra clase CbEnterprise he tenido que cambiar el nombre de un campo ya que state a estate ya que es un nombre que no está permitido como se indica en nuestra consola Roo:
~.domain.CbEnterprise roo> field string --fieldName state --sizeMax 30 Reserved SQL keyword 'state' is not permitted as symbol name
Ahora relacionemos CbEnterprise con CbLanguage, CbCurrency, CbCountry y CbPaymentmethod,
roo>field reference --fieldName idlanguage --type ~.domain.CbLanguage --class ~.domain.CbEnterprise ~.domain.CbEnterprise roo>field reference --fieldName idcurrency --type ~.domain.CbCurrency ~.domain.CbEnterprise roo>field reference --fieldName idcountry --type ~.domain.CbCountry ~.domain.CbEnterprise roo>field reference --fieldName idpaymentmethod --type ~.domain.CbPaymentmethod
Una vez ejecutados todos los comandos por consola este el resultado en nuestra clase CbEnteprise:
package org.xulescode.domain; import org.springframework.roo.addon.javabean.annotations.RooJavaBean; import org.springframework.roo.addon.javabean.annotations.RooToString; import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; import javax.validation.constraints.NotNull; import javax.persistence.Column; import javax.validation.constraints.Size; import javax.persistence.ManyToOne; @RooJavaBean @RooToString @RooJpaActiveRecord(identifierField = "identerprise", identifierType = Integer.class) public class CbEnterprise { /** */ @NotNull @Column(unique = true) @Size(max = 150) private String enterprise; /** */ @Size(max = 250) private String description; /** */ @Size(max = 100) private String enterprisealias; /** */ @Size(max = 250) private String contact; /** */ @Size(max = 30) private String estate; /** */ private Double balance; /** */ @Size(max = 100) private String ei; /** */ @Size(max = 20) private String enterprisepayer; /** */ @ManyToOne private CbLanguage idlanguage; /** */ @ManyToOne private CbCurrency idcurrency; /** */ @ManyToOne private CbCountry idcountry; /** */ @ManyToOne private CbPaymentmethod idpaymentmethod; }
Como Borrar un campo en Spring Roo
Es muy fácil confundirse al nombrar un campo, a todos nos ha pasado alguna vez, como hacemos para borrarlo y volverlo a cargar. Pues muy fácil, vamos a nuestra clase creada por ejemplo a CbEnterprise, con la que estamos trabajando ahora, y directamente buscamos un campo por ejemplo enterprisepayer y simplemente lo borramos, este es el código que tenemos que eliminar en CbEnterprise.java:
/** */ @Size(max = 20) private String enterprisepayer;
Y te preguntarás, ¿qué sucede?, pues mira tu consola Roo y lo entenderás, esta detecta el cambio y hace las acciones necesarias para propagar el cambio, esto es lo que te dirá tu consola:
roo> Updated SRC_TEST_JAVA/org/xulescode/domain/CbEnterpriseDataOnDemand_Roo_DataOnDemand.aj Updated SRC_MAIN_JAVA/org/xulescode/domain/CbEnterprise_Roo_Jpa_ActiveRecord.aj Updated SRC_MAIN_JAVA/org/xulescode/domain/CbEnterprise_Roo_JavaBean.aj
Ahora ejecutamos los test que hemos creado automáticamente con el comando para maven perform tests, como se explica con más detalle en el apartado de la documentación de referencia. Utilizando nuestro STS vamos a Run As > Maven test.
4. CREACIÓN Y CONFIGURACIÓN MVC WEB
Siguiendo la referencia del proyecto de ejemplo de la documentación de Spring Roo, a continuación, generamos la aplicación Web con la que gestionaremos los idiomas de la clase CbLanguage, así que para ello vamos a ejecutar los comandos web mvc. En primer lugar usaremos web mvc setup para configurar todos los controladores de la aplicación seguido a continuación del comando web mvc all:
~.domain.CbLanguage roo> web mvc setup ~.domain.CbLanguage roo> web mvc all --package ~.web
Una vez finalizado ya tenemos lista nuestra aplicación para funcionar.
Despliegue del proyecto y pruebas
Antes de ejecutar nuestro proyecto situándonos sobre el fichero pom.xml ejecutamos Run As >Maven install, una vez hecho esto debemos compilar nuestro proyecto, por eso, situándonos desde el mismo sitio ejecutamos ahora Run As >Maven build, y nos aparecerá un menú, tal que así:
Estamos utilizando M2Eclipse que nos proporciona una integración para Apache Maven dentro del IDE, como ves en la foto aparecen varias opciones, en tu caso, aparecerá una sin ninguna definición, y esto es porque aún no has definido ninguna meta (Goal), selecciona uno y donde pone Goals introduce package, que es el comando para compilar nuestro proyecto.
Hecho esto ya estamos listos para ejecutar nuestro proyecto, sitúate encima de él y selecciona la opción Run As > Run on Server. A continuación, te muestro como ejemplo la creación y visualización de una nueva moneda:
Actualizando el fichero de persistencia
Como puedes ver la aplicación está funcionando y lista, con la configuración que tenemos cada vez que ejecutemos el proyecto se creará de nuevo la base de datos, si no queremos esto simplemente editamos nuestro fichero persistence.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database --> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/> <property name="hibernate.connection.charSet" value="UTF-8"/> <!-- Uncomment the following two properties for JBoss only --> <!-- property name="hibernate.validator.apply_to_ddl" value="false" /--> <!-- property name="hibernate.validator.autoregister_listeners" value="false" /--> </properties> </persistence-unit> </persistence>
Aquí, modificamos la propiedad hibernate.hbm2ddl.auto, y la cambiamos de create a update, así, ya no borraremos los datos cada vez que ejecutemos el proyecto.
Añadiendo datos para pruebas vía SQL
Para poder probar mejor nuestra aplicación puedes añadir los datos que te facilito en este script SQL para poblar la base de datos con idiomas, monedas, países,…, este es el script:
PostgreSQL datos para CustomerdbrooPostgreSQL data for Customerdbroo
Acuérdate de modificar la unidad de persistencia si no la base de datos se borrará y creará de nuevo cada vez que ejecutes la aplicación.
Probando la aplicación
Vamos a ver de nuevo ahora nuestra aplicación con los datos que tenemos con las listas de las tablas:
Creando una empresa
Como ejemplo de la aplicación ahora que tenemos paíse, monedas, idiomas y métodos de pago ya creados, vamos a crear una nueva empresa. Accedemos desde el menú a Create new Cb Enterprise y nos aparece la pantalla de la imagen
Rellenamos los datos de la nueva empresa, y como podemos ver sin hacer ninguna programación de código (ya lo ha hecho por nosotros Roo) tenemos cargada la selección de países como se muestra en la imagen:
Después de la creación vemos la nueva empresa creada:
&nbps;
Por último, la lista de empresas actualizada:
5. AÑADIENDO SPRING SECURITY
Ahora vamos a configurar el control de acceso a nuestra aplicación, se creará un acceso vía login, y además veremos como restringir los accesos en frontend Web en función del role del usuario.
Añadimos Spring Security
Darle el acceso de seguridad a la aplicación lo hacemos instalando el Spring Security addon mediante el comando
~.web roo> security setup
Ahora ejecutamos: Run As > Maven install para descargar las librerías que hemos incorporado a nuestro proyecto al ejecutar security setup.
Al ejecutar el comando además de actualizar los ficheros ya existentes y añadir las librerías necesarias a nuestro fichero pom.xml ya que añadimos nuevas dependencias a nuestro proyecto, se crean dos ficheros nuevos:
Created SPRING_CONFIG_ROOT/applicationContext-security.xml Created SRC_MAIN_WEBAPP/WEB-INF/views/login.jspx
- login.jspx con lo que ya tenemos una nueva pantalla de login creada
- applicationContext-security.xml en este fichero será donde configuraremos los controles de acceso.
Configuramos Spring Security
En una primera aproximación hemos añadido control de acceso vía url a cbcountrys y cbenterprises, como puedes hacer de la siguiente forma:
<!-- HTTP security configurations --> <http auto-config="true" use-expressions="true"> <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" /> <logout logout-url="/resources/j_spring_security_logout" /> <!-- Configure these elements to secure URIs in your application --> <intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" /> <intercept-url pattern="/member/**" access="isAuthenticated()" /> <intercept-url pattern="/resources/**" access="permitAll" /> <intercept-url pattern="/login/**" access="permitAll" /> <intercept-url pattern="/**" access="isAuthenticated()" /> <!-- Configure these elements to secure URIs in your application --> <intercept-url pattern="/cbcountrys/**" access="hasRole('ROLE_ADMIN')"/> <intercept-url pattern="/cbenterprises/**" access="hasRole('ROLE_ADMIN')"/> <intercept-url pattern="/static/**" access="permitAll" /> </http>
Usa los usuarios de acceso creados por defecto para probar el sistema:
<!-- Configure Authentication mechanism --> <authentication-manager alias="authenticationManager"> <!-- SHA-256 values can be produced using 'echo -n your_desired_password | sha256sum' (using normal *nix environments) --> <authentication-provider> <password-encoder hash="sha-256" /> <user-service> <user name="admin" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" authorities="ROLE_ADMIN" /> <user name="user" password="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
Ejecuta el proyecto para ver el resultado, está será la pantalla de login que se ha creado por defecto:
Con Spring Roo también podemos configurar desde los controladores creados los accesos al borrado y actualización de nuestras entidades, por ejemplo, en el controlador CbEnterpriseController.java, vamos a ver como limitamos esto ajustando la anotación @RooWebScaffold, como se muestra en el ejemplo:
package org.xulescode.web; import org.springframework.roo.addon.web.mvc.controller.annotations.scaffold.RooWebScaffold; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.xulescode.domain.CbEnterprise; @RequestMapping("/cbenterprises") @Controller @RooWebScaffold(path = "cbenterprises", formBackingObject = CbEnterprise.class, delete=false, update=false) public class CbEnterpriseController { }
Estas anotaciones notificarán al shell de Roo para eliminar los métodos d delete y update de CbEnterpriseController, y también, ajustar las vistas relacionadas.
6. APLICACIÓN MULTIIDIOMA (i18n)
Incorporar más idiomas a nuestra aplicación es muy sencillo con Spring Roo simplemente tenemos que ejecutar web mvc language –code es para añadir el idioma español, simplemente ejecuta el mismo código con el código iso de i18n del idioma que quieras añadir y listo.
roo>web mvc language --code es Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_es.properties Created SRC_MAIN_WEBAPP/images/es.png Updated SRC_MAIN_WEBAPP/WEB-INF/views/footer.jspx
Este es el resultado:
Traduciendo nuestra aplicación
Como vimos en la imagen anterior las traducciones al español de la pantalla de login ya vienen configuradas por defecto, como se mostró en la consola Roo se crea un nuevo fichero para almacenar las traducciones español: messages_es.properties, aquí puedes ver la estructura y la carpeta i18n:
#menu global_menu_new=Crear nuevo {0} global_menu_list=Listar {0} global_menu_find=Buscar por {0} global_language_switch=Cambiar idioma a {0} global_language=Idioma global_sponsored=Patrocinado por SpringSource global_theme=Tema global_theme_alt=alt global_theme_standard=estándar global_generic={0} #welcome page welcome_titlepane=Bienvenido a {0} welcome_h3=Bienvenido a {0} welcome_text=Spring Roo proporciona herramientas interactivas, ligeras y adaptables al usuario que permiten entregar rápidamente aplicaciones empresariales Java de alto rendimiento.
Simplemente editamos el fichero messages_es.properties para completar las traducciones de nuestra de los mensajes de la aplicación. Para traducir todos los campos de nuestra aplicación necesitamos crear un nuevo fichero aplication_es.properties y ahí realizar las traducciones de los campos de nuestras clases:
application_name=Gestión de clientes label_org_xulescode_domain_cbcountry=País label_org_xulescode_domain_cbcountry_country=País label_org_xulescode_domain_cbcountry_countrycode=Código país label_org_xulescode_domain_cbcountry_description=Descripción label_org_xulescode_domain_cbcountry_displaysequence=Secuencia display label_org_xulescode_domain_cbcountry_expressionphone=Expresión teléfono label_org_xulescode_domain_cbcountry_hasregion=Tiene región label_org_xulescode_domain_cbcountry_ibancountry=País Iban label_org_xulescode_domain_cbcountry_ibannodigits=Nº dígitos Iban label_org_xulescode_domain_cbcountry_idcountry=id país label_org_xulescode_domain_cbcountry_idcountry_=Idcountry_ label_org_xulescode_domain_cbcountry_idcurrency=Moneda label_org_xulescode_domain_cbcountry_idlanguage=Idioma label_org_xulescode_domain_cbcountry_isactive=Activo label_org_xulescode_domain_cbcountry_isdefault=Por defecto label_org_xulescode_domain_cbcountry_plural=Países label_org_xulescode_domain_cbcountry_regionname=Región label_org_xulescode_domain_cbcountry_version=Versión label_org_xulescode_domain_cbcurrency=Moneda label_org_xulescode_domain_cbcurrency_currency=Moneda label_org_xulescode_domain_cbcurrency_cursymbol=Símbolo label_org_xulescode_domain_cbcurrency_description=Descripción label_org_xulescode_domain_cbcurrency_idcurrency=id moneda label_org_xulescode_domain_cbcurrency_idcurrency_=Idcurrency_ label_org_xulescode_domain_cbcurrency_idlanguage=Idioma label_org_xulescode_domain_cbcurrency_isactive=Activo label_org_xulescode_domain_cbcurrency_isocode=Código Iso label_org_xulescode_domain_cbcurrency_plural=Monedas ...
Así es como queda ahora:
Documentación utilizada
- Spring Roo Project: página principal del proyecto, desde aquí puedes acceder a toda la documentación (inglés).
- Spring Roo and JPA Entities: explicación y aclaración de las relaciones entre entidades en Spring Roo (inglés).
- Appendix A. Command Index: aquí encontrarás todos los comandos de Spring Roo listados alfabéticamente, con ellos se incluyen también las opciones que acepta cada uno.
- Apache Maven
- Maven in five minutes: por si no tienes ningún conocimiento sobre Maven, aquí tienes una introducción básica.
- Para preguntas sobre Spring Roo podemos usar StackOverflow , donde nos ayudarán a resolver nuestras dudas y ayudar con ello a conocer mejor la herramienta.
- Complementos (add-ons): aunque lo probaré en una nueva publicación me parece muy interesante para el desarrollo con Spring Roo el add-on suite: gvNIX, que incluye funcionalidades como integración con jQuery, Bootstrap, Dandelion-datatables, auditoria con Histórico de cambios, Jasper Reports,…
Espero que te haya sido útilXules
Guía Spring Roo 2
Estas son algunas de las ideas para la siguiente publicación:
- Finalizar el desarrollo de las entidades
- Añadir el add-on suite: gvNIX
- Modificar la presentación de los elementos
- Añadir informes con JasperReports
- …
Nos vemos pronto: …
Saludos.
Extraordinaria guía , me ha ayudado muchísimo.
Todo muy bien explicado y detallado , me he enterado muy bien de como se realizan todos los procedimientos.
Quisiera comentarte algo que me sucede y tengo curiosidad de como se resuelve :
Dentro del IDE Eclipse , en Roll Shell , introduzco el siguiente comando :
perform test
– Me aparece este error:
ests run: 45, Failures: 0, Errors: 8, Skipped: 0
[INFO] ————————————————————————
[INFO] BUILD FAILURE
[INFO] ————————————————————————
[INFO] Total time: 10.909 s
[INFO] Finished at: 2016-05-14T17:56:11+02:00
[INFO] Final Memory: 14M/200M
[INFO] ————————————————————————
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12:test (default-test) on project CustomerdbRoo: There are test failures.
[ERROR]
[ERROR] Please refer to C:\Users\Raulv\Documents\EclipseSpringRoo\CustomerdbRoo\target\surefire-reports for the individual test results.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
~.domain.CbEnterprise roo-gvNIX>
He leído todos los foros que he podido sobre este problema.
He configurado el maven y demás lo mejor posible.
No encuentro la solución.
¿ Sabes por casualidad como arreglar este fallo ?
De todas formas , 1 millón de gracias por la guía , es un gran trabajo.
Si estas interesado en crear aplicaciones multiidioma para Java, yo recomiendo altamente esta rápida y intuitiva herramienta en línea para la localización de software: https://poeditor.com/
Hola Sogar.
Spring Roo facilita mucho más que una aplicación multiidioma, no conozco poeditor, pero la revisaré, gracias por la aportación.
Saludos.
Hola Julio, algún email para contactarte.
Gracia
Hola Dante.
Me puedes contactar por el blog, en las redes sociales publicadas o en el email: jynovo@codigoxules.org
Saludos.