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

Logo_SpringRoo

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:

  1. EL PROYECTO
  2. CONFIGURACIÓN DEL ENTORNO
  3. CREACIÓN DE LAS PRIMERAS ENTIDADES
  4. CREACIÓN Y CONFIGURACIÓN MVC WEB
  5. AÑADIENDO SPRING SECURITY
  6. 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:

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:


 

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, …

Learning Project Customerdb Database Entity Relation

Esquema E-R de Customerdb propuesto en Learning Project

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:

 
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:

Spring Roo Project Creación del proyecto

Spring Roo Project Creación del proyecto

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):

Spring Roo Project Creación del nuevo proyecto

Spring Roo Project Creación del nuevo proyecto

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:

Spring Roo Project - Roo configuración de la base de datos

Spring Roo Project – Roo configuración de la base de datos

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:

  1. Editamos nuestra clase CbLanguage
  2. Posicionándonos sobre la declaración de la clase analizamos Cross References.
  3. Abrimos CbLanguage_Roo_Jpa_Entity.aj
  4. 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
  5. 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í:

Spring Roo Project Roo Maven package

Spring Roo Project Roo Maven package

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:

 
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

Spring Roo Project - Nueva empresa

Spring Roo Project – Nueva empresa


 
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:
Spring Roo Project - Rellenamos los datos de la nueva empresa

Spring Roo Project – Rellenamos los datos de la nueva empresa


 
Después de la creación vemos la nueva empresa creada:
Spring Roo Project - Creación empresa Código Xules

Spring Roo Project – Creación empresa Código Xules


 
Por último, la lista de empresas actualizada:
Spring Roo Project - Lista de empresas con la nueva creada

Spring Roo Project – Lista de empresas con la nueva creada

 

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 security setup:

~.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:

Spring Roo Project - Security Login

Spring Roo Project – Security Login

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:

Spring Roo Project - Multiidioma i18n

Spring Roo Project – Multiidioma i18n

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:

Spring Roo Project - Países con menú traducido

Spring Roo Project – Países con menú traducido

Spring Roo Project - País

Spring Roo Project – País


 

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

Logo_SpringRoo

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:

  1. EL PROYECTO
  2. CONFIGURACIÓN DEL ENTORNO
  3. CREACIÓN DE LAS PRIMERAS ENTIDADES
  4. CREACIÓN Y CONFIGURACIÓN MVC WEB
  5. AÑADIENDO SPRING SECURITY
  6. 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, …

Learning Project Customerdb Database Entity Relation

Esquema E-R de Customerdb propuesto en Learning Project

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:

 
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:

Spring Roo Project Creación del proyecto

Spring Roo Project Creación del proyecto

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):

Spring Roo Project Creación del nuevo proyecto

Spring Roo Project Creación del nuevo proyecto

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:

Spring Roo Project - Roo configuración de la base de datos

Spring Roo Project – Roo configuración de la base de datos

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:

  1. Editamos nuestra clase CbLanguage
  2. Posicionándonos sobre la declaración de la clase analizamos Cross References.
  3. Abrimos CbLanguage_Roo_Jpa_Entity.aj
  4. 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
  5. 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í:

Spring Roo Project Roo Maven package

Spring Roo Project Roo Maven package

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:

 
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

Spring Roo Project - Nueva empresa

Spring Roo Project – Nueva empresa


 
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:
Spring Roo Project - Rellenamos los datos de la nueva empresa

Spring Roo Project – Rellenamos los datos de la nueva empresa


 
Después de la creación vemos la nueva empresa creada:
Spring Roo Project - Creación empresa Código Xules

Spring Roo Project – Creación empresa Código Xules


&nbps;
Por último, la lista de empresas actualizada:
Spring Roo Project - Lista de empresas con la nueva creada

Spring Roo Project – Lista de empresas con la nueva creada

 

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 security setup:

~.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:

Spring Roo Project - Security Login

Spring Roo Project – Security Login

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:

Spring Roo Project - Multiidioma i18n

Spring Roo Project – Multiidioma i18n

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:

Spring Roo Project - Países con menú traducido

Spring Roo Project – Países con menú traducido

Spring Roo Project - País

Spring Roo Project – País


 

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: …