2.0.0.M1

gvNIX, un Add-On Suite de Spring Roo | www.gvnix.org

2010 © Dirección General de Tecnologías de la Información - Conselleria de Hacienda y Administración Pública - Generalitat Valenciana. Esta obra está bajo la licencia Reconocimiento-Compartir bajo la misma licencia 3.0 España de Creative Commons. Puede copiarla, distribuirla y comunicarla públicamente siempre que especifique sus autores y comparta cualquier obra derivada bajo la misma licencia.

1. Información General

gvNIX es un entorno de trabajo Java de código abierto para el desarrollo rápido de aplicaciones web altamente productivo, flexible y que no compromete la calidad de los proyectos.

gvNIX trabaja sobre la herramienta de desarrollo Spring Roo ampliando sus funcionalidades básicas con componentes de alto nivel funcional.

gvNIX está patrocinado por la Dirección General de Tecnologías de la Información y la Comunicación (DGTIC) de la Conselleria de Hacienda y Modelo Económico de la Generalitat Valenciana (Comunidad Valenciana, España), gestionado por la Asociación gvSIG y dirigido por DISID. gvNIX se consolida como estándar para desarrollo Java de la DGTIC de la Generalitat Valenciana.

gvNIX está disponible dentro del proyecto de Migración a Software de fuentes abiertas gvPONTIS.

2. Requisitos

Antes de empezar a trabajar con la herramienta de desarrollo gvNIX, es aconsejable conocer cómo funciona Spring Roo. Para ello, se recomienda leer la documentación de referencia.

gvNIX crea aplicaciones web basadas en Spring Framework y en el conjunto de tecnologías de Spring, por lo que es necesario tener conocimientos del framework Spring y tecnologías relacionadas como Spring MVC, Spring Data JPA, Spring Security, etc.

Para poder trabajar con la herramienta de desarrollo gvNIX en un entorno de desarrollo, es necesario disponer de los siguientes componentes:

  • Spring Roo 2.0+ descargado y descomprimido.

  • Versión más actual de Java JDK 6 instalado en el sistema. Se recomienda utiliar Java 7, aunque se dispone de soporte para Java 8. (Más información).

  • Maven 3.0.5 o superior (http://maven.apache.org/).

  • Conexión a Internet para poder instalar de forma correcta gvNIX en la distribución de Spring Roo y descargar las dependencias de los proyectos generados.

Solo es posible utilizar gvNIX 2.0+ sobre las versiones 2.0 de Spring Roo en adelante. Esto es debido a que la instalación de distribuciones es una característica de las últimas versiones de Spring Roo.

3. Instalar gvNIX

Para instalar el gvNIX sobre una distribución de Spring Roo. es necesario que Roo conozca donde están alojados todos los componentes que forman parte de gvNIX. Por ello, es necesario instalar en nuestra distribución de Spring Roo el repositorio donde se encuentran dichos componentes.

Sigue los siguientes pasos para instalar el repositorio de gvNIX en tu distribución de Spring Roo 2.0+:

  1. Ejecuta la consola de Spring Roo 2.0+:

    bash:~$ cd /tmp/new_project
    bash:~$ ~/software/spring-roo-2.0/bin/roo.sh
  2. Accede al "Roo Market Place" y copia la URL del repositorio de gvNIX (http://repository.gvnix.org/index.xml).

  3. Ejecuta el siguiente comando en tu consola de Spring Roo 2.0+ para instalar el repositorio anterior:

    roo> addon repository add --url http://repository.gvnix.org/index.xml
  4. Valida que se ha instalado el repositorio de forma correcta listando los componentes que están disponibles en dicho repositorio. Para ello, ejecuta el siguiente comando:

    roo> addon repository introspect
  5. Si todo ha salido bien, aparecerá un listado mostrando todos los componente que forman parte de la distribución gvNIX.

    Not Installed        gvNIX - Addon - Bootstrap3 support (2.0.0.M1)
    Not Installed        gvNIX - Addon - Co-official languages of Spain (2.0.0.M1)
    Not Installed        gvNIX - Addon - Dynamic Configuration (2.0.0.M1)
    Not Installed        gvNIX - Addon - GEO Support (2.0.0.M1)
    Not Installed        gvNIX - Addon - JPA layer services (2.0.0.M1)
    Not Installed        gvNIX - Addon - Loupe Fields (2.0.0.M1)
    Not Installed        gvNIX - Addon - Monitoring Support (2.0.0.M1)
    Not Installed        gvNIX - Addon - Optimistic Concurrency Control (2.0.0.M1)
    Not Installed        gvNIX - Addon - Services Management (2.0.0.M1)
    Not Installed        gvNIX - Addon - Typical Security (2.0.0.M1)
    Not Installed        gvNIX - Addon - Web Datatables Addon (2.0.0.M1)
    Not Installed        gvNIX - Addon - Web MVC (JSP) layer services (2.0.0.M1)
    Not Installed        gvNIX - Addon - Web MVC Bindings (2.0.0.M1)
    Not Installed        gvNIX - Addon - Web MVC Dialogs (2.0.0.M1)
    Not Installed        gvNIX - Addon - Web MVC Menu (2.0.0.M1)
    Not Installed        gvNIX - Addon - Web Report (2.0.0.M1)
    Not Installed        gvNIX - Annotations - GEO Support (2.0.0.M1)
    Not Installed        gvNIX - Annotations - JPA layer services (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Loupe Fields (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Optimistic Concurrency Control (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Services Management (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Web Datatables Addon (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Web MVC (JSP) layer services (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Web MVC Bindings (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Web MVC Dialogs (2.0.0.M1)
    Not Installed        gvNIX - Annotations - Web Report (2.0.0.M1)
    Not Installed        gvNIX - Roo Addon Suite (2.0.0.M1)
    Not Installed        gvNIX - Support Module (2.0.0.M1)
  6. Ahora que ya tienes instalado el repositorio que contiene los componentes de gvNIX, continuamos con la instalación de los mismos. Para ello ejecuta el siguiente comando:

    roo> addon suite install name --symbolicName org.gvnix.roo.addon.suite
  7. Valida que se ha instalado el Roo Add-On Suite de gvNIX ejecutando el siguiente comando:

    roo> addon suite list
  8. Si todo ha salido bien, aparecerá un listado mostrando todos los Roo Add-On Suites que tienes instalados en tu distribución de Spring Roo:

    Getting all 'Roo Addon Suites' installed on Spring Roo Shell...
    
       org.osgi.service.subsystem.root
       org.gvnix.roo.addon.suite
    
    2 Roo Addon Suites were found at your Spring Roo installation
  9. Para finalizar, valida que todos los componentes de gvNIX se han instalado correctamente en la distribución de Spring Roo ejecutando el siguiente comando:

    roo> addon list
  10. Si todo ha salido bien, al final del listado que aparecerá en la consola, podrás ver todos los componentes de gvNIX instalados y activados del siguiente modo:

       86|Active     |    1|gvNIX - Annotations - GEO Support (2.0.0.M1)
       87|Active     |    1|gvNIX - Addon - Dynamic Configuration (2.0.0.M1)
       88|Active     |    1|gvNIX - Addon - Loupe Fields (2.0.0.M1)
       89|Active     |    1|gvNIX - Addon - Web MVC (JSP) layer services (2.0.0.M1)
       90|Active     |    1|gvNIX - Annotations - Web Datatables Addon (2.0.0.M1)
       91|Active     |    1|gvNIX - Addon - JPA layer services (2.0.0.M1)
       92|Active     |    1|gvNIX - Addon - Web Datatables Addon (2.0.0.M1)
       93|Active     |    1|gvNIX - Annotations - Web MVC (JSP) layer services (2.0.0.M1)
       94|Active     |    1|gvNIX - Addon - Services Management (2.0.0.M1)
       95|Active     |    1|gvNIX - Annotations - Web Report (2.0.0.M1)
       96|Active     |    1|gvNIX - Addon - Co-official languages of Spain (2.0.0.M1)
       97|Active     |    1|gvNIX - Annotations - Optimistic Concurrency Control (2.0.0.M1)
       98|Active     |    1|gvNIX - Addon - Web MVC Dialogs (2.0.0.M1)
       99|Active     |    1|gvNIX - Annotations - Services Management (2.0.0.M1)
      100|Active     |    1|gvNIX - Addon - Monitoring Support (2.0.0.M1)
      101|Active     |    1|gvNIX - Addon - Bootstrap3 support (2.0.0.M1)
      102|Active     |    1|gvNIX - Annotations - Web MVC Dialogs (2.0.0.M1)
      103|Active     |    1|gvNIX - Addon - GEO Support (2.0.0.M1)
      104|Active     |    1|gvNIX - Addon - Optimistic Concurrency Control (2.0.0.M1)
      105|Active     |    1|gvNIX - Support Module (2.0.0.M1)
      106|Active     |    1|gvNIX - Annotations - Loupe Fields (2.0.0.M1)
      107|Active     |    1|gvNIX - Annotations - JPA layer services (2.0.0.M1)
      108|Active     |    1|gvNIX - Addon - Web Report (2.0.0.M1)
      109|Active     |    1|gvNIX - Annotations - Web MVC Bindings (2.0.0.M1)
      110|Active     |    1|gvNIX - Addon - Typical Security (2.0.0.M1)
      111|Active     |    1|gvNIX - Addon - Web MVC Menu (2.0.0.M1)
      112|Active     |    1|gvNIX - Addon - Web MVC Bindings (2.0.0.M1)

Una vez hecho esto, ya se puede trabajar con el entorno gvNIX desde la línea de comandos. Sin embargo, se recomienda utilizar un IDE de desarrollo que permita integrar el entorno gvNIX como, por ejemplo STS o Eclipse.

I. Introducción

1. Introducción

1.1. ¿Qué es gvNIX?

gvNIX es un entorno de trabajo Java de código abierto para el desarrollo rápido de aplicaciones web sobre tecnología Spring. Sus funcionalidades hacen que sea un entorno altamente productivo, flexible y que no compromete la calidad de los proyectos.

Está compuesto por una serie de herramientas de código abierto distribuídas en forma de "Spring Roo Add-On Suite" a través de un repositorio OSGi R5. Esto le proporciona un amplio apoyo por parte de importantes organizaciones como Spring y Pivotal. Añade funcionalidades de alto nivel a las prestaciones que ya se obtienen con Spring Roo para mejorar la productividad.

gvNIX está patrocinado por la Dirección General de Tecnologías de la Información y la Comunicación (DGTIC) de la Conselleria de Hacienda y Modelo Económico de la Generalitat Valenciana (Comunidad Valenciana, España), gestionado por la Asociación gvSIG y dirigido por DISID.

gvNIX está disponible dentro del proyecto de Migración a Software de fuentes abiertas gvPONTIS.

1.2. ¿Qué es Spring Roo?

Spring Roo es un entorno de trabajo Java que permite el desarrollo de aplicaciones web de forma rápida y cómoda para el desarrollador. Sus principales características son:

  • Generación de código en Java (lenguaje estático).

  • Eliminar el trabajo tedioso centrando el desarrollo en la lógica de negocio.

  • Convención sobre configuración.

  • Desarrollo dirigido por el dominio (Domain-Driven Development):

    • Diseño dirigido por el modelo de entidades.

    • Lógica en las entidades (Real Object Oriented), eliminando capas redundantes.

    • Otras capas opcionales (servicios, DAOs, …​).

  • Crea un proyecto en segundos.

  • Realimentación: añade valor durante todo el ciclo de vida.

  • No incorpora elementos adicionales al entorno de ejecución, por lo que no penaliza la velocidad ni la memoria de la aplicación.

  • Recibe instrucciones a través de una consola interactiva con autocompletado y ayuda en línea.

  • Extensible usando bundles OSGi.

  • Aprovecha el conocimiento: no necesita más conocimiento que el necesario para el desarrollo de aplicaciones JEE.

1.3. ¿Qué es un "Roo Add-On Suite"?

Los "Roo Add-On Suites" son la mejor manera de empaquetar y distribuir conjuntos de Add-Ons para que puedan ser instalados en distribuciones de Spring Roo de forma rápida y sencilla.

Están basados en subsistemas de OSGi R5, los cuales permiten instalar un conjunto de componentes sobre la distribución de Spring Roo sin comprometer su modularidad.

Por todo lo anterior, decimos que gvNIX es un "Spring Roo Add-On Suite" que puede ser instalado en distribuciones de Spring Roo para ampliar sus funcionalidades básicas.

1.4. ¿Qué ofrece gvNIX?

gvNIX aprovecha las características de Spring Roo y aporta su propia filosofía, ofrecer al desarrollador componentes de alto valor funcional para aplicaciones corporativas:

  • Control de concurrencia a nivel de aplicación sin campos en base de datos.

  • Utilidades de generación de consultas.

  • Utilidades de modificaciones múltiples de entidades.

  • Gestión de temas visuales utilizando jQuery, Bootstrap, HTML5 y CSS3.

  • Gestión de la visualización de excepciones.

  • Gestión de mensajes de usuario en ventana modal.

  • Gestión de la estructura de páginas en el menú.

  • Gestión de patrones de visualización de entidades y sus relaciones utilizando el componente Datatables.

  • Gestión de transformación de cadenas vacías a valores nulos.

  • Gestión de servicios locales y servicios web (importación y exposición).

  • Control de acceso (autenticación y autorización).

  • Gestión de configuraciones por entorno.

  • Generación de documentos (reportes).

  • Gestión de relaciones utilizando componente Lupa.

  • Gestión de información geográfica.

  • Generación de GeoPortales interactivos.

2. Empezando con gvNIX: Tutorial (I)

En este capítulo generaremos una aplicación sencilla paso a paso de forma rápida para que puedas ver y entender cómo se trabaja con la herramienta de desarrollo gvNIX en un proyecto básico.

Los detalles sobre la generación del código y la explicación de cada uno de los comandos ejecutados, se mostrarán en las siguientes secciones de este manual.

2.1. ¿Qué aprenderás?

En este tutorial aprenderás como crear una aplicación desde cero utilizando la herramienta de desarrollo gvNIX sobre el IDE STS.

Las principales características de gvNIX que veremos en este tutorial son las siguientes:

  • Creación de un proyecto

  • Configurarción de persistencia

  • Generación del modelo de entidades

  • Generación de métodos de búsqueda

  • Generación de capa web

  • Componente Datatables y Bootstrap

  • Patrones de Pantalla

  • Ejecución de una aplicación en un servidor Tomcat

  • Edición de datos en linea

  • Componente Lupa

  • Instalación y gestión de menú

  • Aplicar seguridad a nuestra aplicación

  • Generación de informes utilizando Jasper Reports

  • Tests funcionales y Tests de integración

  • Generación de servicios web.

2.2. Detalles de la aplicación

La aplicación que se va a generar está basada en la aplicación de ejemplo Petclinic de Spring. Los usuarios de esta aplicación son empleados de una clínica veterinaria, que a lo largo de su jornada laboral, necesitan gestionar información sobre veterinarios, clientes y sus mascotas.

Después de esta pequeña introducción sobre la aplicación que se va a desarrollar, hemos generado un diagrama de clases simple para el modelo de entidades de esta aplicación:

Petclinic UML

Para sacar el máximo partido a las funcionalidades de gvNIX y Spring Roo, es recomendable que las aplicaciones se generen siguiendo la filosofía del diseño guiado por el dominio.

Hay que tener en cuenta que la aplicación que se va a generar no será una aplicación real, ya que normalmente necesitaría una serie de trabajos adicionales para personalizar la capa web, implementar lógica de negocio, etc..

2.3. Paso 1: Crear un proyecto

A continuación, vamos a crear un nuevo proyecto desde STS. Para ello accede a "New > Project…​ > Spring > Spring Roo Project" como se muestra en la imagen:

Nuevo proyecto

Una vez seleccionado el tipo de proyecto que queremos generar, configura el proyecto:

Configuración del Proyecto

Nombre del Proyecto: petclinic

Top level package: com.springsource.petclinic

Al clicar sobre Next y Finish se generará el nuevo proyecto y seguidamente se iniciará la consola de Spring Roo.

Consola de gvNIX

IMPORTANTE Antes de continuar con el tutorial es necesario que valides que ĺa distribución de Spring Roo que estás utilizando tiene instalados los componentes de gvNIX.

Para ello, ejecuta el siguiente comando:

roo> addon suite list

Debe mostrarse el siguiente contenido:

roo> addon suite list
Getting all 'Roo Addon Suites' installed on Spring Roo Shell...

   org.osgi.service.subsystem.root
   org.gvnix.roo.addon.suite

2 Roo Addon Suites were found at your Spring Roo installation
roo>

En caso de que solo aparezca el Roo Add-On Suite por defecto "org.osgi.service.subsystem.root", significará que no has instalado de forma correcta gvNIX.

Sigue los pasos de la sección anterior para instalar los componentes de gvNIX sobre la distribución de Spring Roo antes de continuar con el tutorial.

2.4. Paso 2: Configurar persistencia

¿Ya aparecen los componentes de gvNIX instalados en tu distribución de Roo? Si no es así, sigue los pasos de la sección anterior para instalar los componentes de gvNIX sobre la distribución de Spring Roo antes de continuar con el tutorial.

Vamos a configurar la persistencia de nuestro proyecto. En este caso vamos a utilizar HIBERNATE como ORM y el tipo de base de datos HYPERSONIC_PERSISTENT.

Para ello, ejecutamos el siguiente comando sobre la consola de gvNIX en STS:

roo> jpa setup --provider HIBERNATE --database HYPERSONIC_PERSISTENT

2.5. Paso 3: Generar modelo de entidades

Siguiendo el modelo de entidades propuesto anteriormente, ejecutaremos los siguientes comandos para generar nuestro dominio:

Crea todas las entidades de nuestra aplicación ejecutando los siguientes comandos:

 entity jpa --class ~.domain.Pet --sequenceName PET_SEQ
 entity jpa --class ~.domain.Visit --sequenceName VISIT_SEQ
 entity jpa --class ~.domain.AbstractPerson --abstract
 entity jpa --class ~.domain.Vet --extends ~.domain.AbstractPerson
 entity jpa --class ~.domain.Owner --extends ~.domain.AbstractPerson

Crea los enumerados PetType y Speciality ejecutando los siguientes comandos:

 enum type --class ~.reference.PetType
 enum constant --name Dog
 enum constant --name Cat
 enum constant --name Bird
 enum type --class ~.reference.Specialty
 enum constant --name Cardiology
 enum constant --name Dentistry
 enum constant --name Nutrition

Añade todos los campos a las entidades ejecutando los siguientes comandos:

 field string --fieldName firstName --sizeMin 3 --sizeMax 30 --class ~.domain.AbstractPerson
 field string --fieldName lastName --notNull --sizeMin 3 --sizeMax 30
 field string --fieldName address --notNull --sizeMax 50 --sizeMin 1
 field string --fieldName city --notNull --sizeMax 30
 field string --fieldName telephone --notNull
 field string --fieldName homePage --sizeMax 30
 field string --fieldName email --sizeMax 30 --sizeMin 6
 field date --fieldName birthDay --type java.util.Date --notNull
 field string --fieldName description --sizeMax 255 --class ~.domain.Visit
 field date --fieldName visitDate --type java.util.Date --notNull --past
 field reference --fieldName pet --type ~.domain.Pet --notNull
 field reference --fieldName vet --type ~.domain.Vet
 field boolean --fieldName sendReminders --notNull --primitive --class ~.domain.Pet
 field string --fieldName name --notNull --sizeMin 1
 field number --fieldName weight --type java.lang.Float --notNull --min 0
 field reference --fieldName owner --type ~.domain.Owner
 field enum --fieldName type --type ~.reference.PetType --notNull
 field date --fieldName employedSince --type java.util.Calendar --notNull --past --class ~.domain.Vet
 field enum --fieldName specialty --type ~.reference.Specialty --notNull false
 field set --class ~.domain.Owner --fieldName pets --type ~.domain.Pet --mappedBy owner --notNull false --cardinality ONE_TO_MANY
 field set --class ~.domain.Vet --fieldName visits --type ~.domain.Visit --mappedBy vet --notNull false --cardinality ONE_TO_MANY
 field reference --fieldName owner --type ~.domain.Owner --class ~.domain.Vet
 field set --fieldName vets --type ~.domain.Vet --class ~.domain.Owner --cardinality ONE_TO_MANY --mappedBy owner
 field set --fieldName visits --type ~.domain.Visit --class ~.domain.Pet --cardinality ONE_TO_MANY --mappedBy pet

2.6. Paso 4: Métodos de búsqueda

Para ser capaces de filtrar los registros guardados en nuestra base de datos, es necesario que nuestras entidades dispongan de unos métodos de búsqueda.

Para instalarlos, ejecutaremos los siguientes comandos:

finder add --finderName findPetsByNameAndWeight --class ~.domain.Pet
finder add --finderName findPetsByOwner
finder add --finderName findPetsBySendRemindersAndWeightLessThan
finder add --finderName findPetsByTypeAndNameLike
finder add --finderName findVisitsByDescriptionAndVisitDate --class ~.domain.Visit
finder add --finderName findVisitsByVisitDateBetween
finder add --finderName findVisitsByDescriptionLike

2.7. Paso 5: Capa web

En este momento ya disponemos de nuestro modelo de entidades generado. Ahora, es necesario que generemos la capa web de nuestra aplicación para que los usuarios puedan acceder a ella a través de un navegador.

En primer lugar instalamos todos los componentes web de nuestra aplicación como imágenes, estilos css, tagx, etc…​ utilizando el siguiente comando:

web mvc setup

A continuación, generamos la capa web de todas las entidades de nuestro proyecto ejecutando el siguiente comando:

web mvc all --package ~.web

Para generar las vistas de los métodos de búsqueda añadidos anteriormente y que el usuario pueda realizar búsquedas de forma visual, ejecutaremos el siguiente comando:

web mvc finder all

Si necesitas instalar varios idiomas en tu aplicación, puedes ejecutar los siguientes comandos:

web mvc language --code es
web mvc language --code de

2.8. Paso 6: Instalar JQuery, Datatables y Bootstrap

A continuación, incluiremos la librería JQuery en nuestro proyecto generado. Además, incluiremos el componente Datatables que utilizaremos en las vistas de listado y finalmente, transformaremos la apariencia de nuestra aplicación para que se muestre con estilo Bootstrap.

Para instalar jQuery en nuestro proyecto, ejecutamos el siguiente comando:

web mvc jquery setup

Para que todas nuestras vistas utilicen componentes jQuery, utilizaremos el siguiente comando:

web mvc jquery all

Seguimos con el tutorial instalando el componente Datatables en nuestro proyecto con el siguiente comando:

web mvc datatables setup

De momento solo instalamos los componentes Datatables, pero nuestras vistas de listado no lo están utilizando.

Para finalizar este punto, transformamos la apariencia de nuestra aplicación a Bootstrap con el siguiente comando:

web mvc bootstrap setup

2.9. Paso 7: Edición en linea y Selección Múltiple

Entre las múltiples funcionalidades que ofrece el componente Datatables, el cual hemos incluido en el paso anterior, encontramos la edición en linea y la selección múltiple.

La funcionalidad de edición en linea permite a los usuarios crear y editar registros directamente desde el componente Datatable sin abandonar el listado.

La funcionalidad de selección múltiple permite seleccionar varios registros mostrados en el componente Datatables para así, aplicar acciones sobre ellos, como puede ser editar o eliminar.

Para que los Datatables que utilicemos en nuestra aplicación sean capaces de incluir estas funcionalidades , ejecutaremos los siguientes comandos:

jpa gvnix setup
jpa batch all
web mvc batch setup
web mvc batch all

2.10. Paso 8: Patrones de Pantalla

En este punto, vamos a definir una serie de patrones de pantalla "maestro > detalle" utilizando el componente Datatables añadido en el paso anterior.

2.10.1. Creación de Maestros

A continuación creamos todas las vistas maestras de nuestra aplicación:

web mvc datatables add --type ~.web.VetController --mode show
web mvc datatables add --type ~.web.PetController
web mvc datatables add --type ~.web.OwnerController
web mvc datatables add --type ~.web.VisitController --inline true --ajax true

Utiliza el parámetro --mode con valor show para mostrar un único registro por página. Utiliza el parámetro --inlineEditing para habilitar la edición en linea.

2.10.2. Creación de Detalles

Después de crear los maestros, continuamos generando los detalles.

Para generar el patrón de pantalla "Maestro Owners > Detalle Pets" ejecutaremos el siguiente comando:

web mvc datatables detail add --type ~.web.OwnerController --property pets

Para generar el patrón de pantalla "Maestro Owners > Detalle Vets" ejecutaremos el siguiente comando:

web mvc datatables detail add --type ~.web.OwnerController --property vets

Para generar el patrón de pantalla "Maestro Owners > Detalle Pet > Detalle Visit" ejecutaremos el siguiente comando:

web mvc datatables detail add --type ~.web.PetController --property visits

Para generar el patrón de pantalla "Maestro Owners > Detalle Vet > Detalle Visit" ejecutaremos el siguiente comando:

web mvc datatables detail add --type ~.web.VetController --property visits

El ejemplo anterior muestra un patrón de pantalla de tres niveles. (Maestro, detalle y detalle de detalle)

2.11. Paso 9: Primera ejecución

En este momento vamos a ejecutar nuestra aplicación en un servidor Tomcat.

En primer lugar, es necesario añadir el servidor Tomcat a nuestro IDE STS. Para ello, seguiremos los siguientes pasos:

  • En la pestaña "Servers" añadiremos un nuevo servidor utilizando "New…​ > Server".

  • Aparecerá una ventana como la siguiente, donde seleccionaremos el servidor "Apache Tomcat v6.0":

Nuevo Servidor
  • Seleccionamos el directorio donde tengamos descargado nuestro apache-tomcat. Si no lo tienes descargado, puedes hacer click sobre el botón "Download and Install" y se descargará de forma automática:

Configurar servidor
  • A continuación, añadimos nuestra aplicación generada al servidor Tomcat:

Nueva app

Ahora que ya tenemos un servidor Tomcat configurado y nuestra aplicación añadida, podemos arrancar el servidor Tomcat utilizando el botón de "Play" con el servidor Tomcat seleccionado:

Botones Servers

Otra forma de arrancar nuestro proyecto es hacer click derecho sobre el proyecto en STS y seleccionando la opción "Run as…​ > Run On Server", seleccionamos el servidor sobre el cual queremos ejecutar nuestro proyecto y presionamos "Finish" para iniciar la ejecución.

Ejecutar aplicación en servidor

Una vez haya arrancado, podemos acceder a la URL http://localhost:8080/petclinic/ desde nuestro navegador para visualizar la aplicación generada.

Estado de la aplicación

2.12. Paso 10: Componente Lupa

El componente lupa provee funcionalidades para buscar datos relacionados de forma rápida y sencilla utilizando AJAX.

Para instalar el componente lupa en nuestra aplicación generada, es necesario ejecutar el siguiente comando:

web mvc loupe setup

A continuación, añadimos una serie de funcionalidades necesarias para el correcto funcionamiento del componente en la capa controladora:

web mvc loupe set --controller ~.web.VisitController

Finalmente, convertimos los elementos "combobox" a componentes lupa utilizando los siguientes comandos:

web mvc loupe field --controller ~.web.VisitController --field pet --caption name --additionalFields name,weight --max 5
web mvc loupe field --controller ~.web.VisitController --field vet

2.13. Paso 11: Instalación del Menú

gvNIX provee un menú mucho más personalizable que el definido inicialmente por Spring Roo. Por ello, se aconseja que todas las aplicaciones incorporen el menú de gvNIX utilizando este sencillo comando:

menu setup

2.14. Paso 12: Aplicar Seguridad

Aplicar seguridad a un proyecto es muy sencillo con gvNIX. Utilizando el siguiente comando, se añade seguridad a nuestro proyecto generado utilizando Spring Security.

security setup

2.15. Paso 13: Gestión de Informes

A continuación, incluiremos las funcionalidades necesarias para generar un informe sobre los "Owners" que tenemos registrados en nuestro sistema petclinic. Para ello, ejecutamos los siguientes comandos:

web report setup
web report add --controller ~.web.OwnerController --reportName report_owners

2.16. Paso 14: Control de concurrencia

Configuraremos el control de concurrencia sobre la entidad "Pet" de nuestro proyecto, para así evitar que se pierdan los datos guardados cuando varios usuarios editan un mismo registro.

Para ello, basta con ejecutar el siguiente comando:

occ checksum set --entity ~.domain.Pet

2.17. Paso 15: Tests funcionales y tests de integración

En este momento, vamos a añadir una serie de tests funcionales y tests de integración a nuestra aplicación generada. Para los tests funcionales utilizaremos Selenium y para los tests de integración utilizaremos JUnit.

Añadimos los tests funcionales a todas las vistas de nuestro proyecto utilizando los siguientes comandos:

selenium test --controller ~.web.OwnerController
selenium test --controller ~.web.PetController
selenium test --controller ~.web.VetController
selenium test --controller ~.web.VisitController

Añadimos los tests de integración a cada una de las entidades de nuestro proyecto utilizando los siguientes comandos:

test integration --entity ~.domain.Vet
test integration --entity ~.domain.Owner
test integration --entity ~.domain.Pet
test integration --entity ~.domain.Visit

2.18. Paso 16: Servicios web

Para acabar con esta guía rápida sobre las funcionalidades disponibles en la herramienta de desarrollo gvNIX, serviremos varios servicios web desde nuestra aplicación generada.

Para ello, ejecutamos los siguientes comandos:

remote service define ws --class ~.services.PetsServices --serviceName ws_get_all_pets
remote service operation --name ws_list_pets --service ~.services.PetsServices

Estos servicios estarán disponibles en http://localhost:8080/petclinic/services y podrán ser consumidos por aplicaciones externas.

2.19. Resultado

Después de seguir este rápido tutorial donde se muestran algunas de las funcionalidades que ofrece la herramienta gvNIX, tendremos una aplicación adaptativa (responsive UI) que podrá ser visualizada en cualquier dispositivo ya sea ordenadores, tablets o incluso móviles. La aplicación adaptativa generada tendrá el siguiente aspecto:

Login
Alta de una mascota
Listado de mascotas
Edición en linea

Ahora que ya conoces las funcionalidades básicas de gvNIX, te recomendamos que continues leyendo este manual. Algunas secciones que pueden interesarte son:

3. gvNIX avanzado: Componentes GEO (Tutorial II)

En este capítulo actualizaremos la aplicación generada en la primera parte de este tutorial incluyendo componentes de tipo geográfico.

Los detalles sobre la generación del código y la explicación de cada uno de los comandos ejecutados, se mostrarán en las siguientes secciones de este manual.

3.1. ¿Qué aprenderás?

En esta segunda parte del tutorial, aprenderás a incluir componentes de tipo GEO en tus aplicaciones generadas utilizando la herramienta de desarrollo de gvNIX.

Las principales características de gvNIX que veremos en este tutorial son las siguientes:

  • Configurar persistencia con BBDD que aceptan campos de tipo GEO.

  • Incluir soporte espacial utilizando Hibernate Spatial.

  • Añadir campos de tipo GEO en entidades generadas.

  • Generar buscadores sobre campos de tipo GEO.

  • Añadir mapas en las vistas de creación, actualización y visualización.

  • Generar geoportales para representar y gestionar los datos de la aplicación.

  • Añadir entidades al geoportal generado

  • Añadir capas base WMS y TileLayers al geoportal generado.

  • Añadir herramientas al geoportal generado.

  • Filtrar datos representados en el geoportal utilizando el componente Datatables

  • Seleccionar datos representados en el geoportal utilizando el componente Datatables

  • Agrupar elementos dependiendo del nivel de zoom.

3.2. Paso 1: Configurar persistencia GEO

Lo primero que debemos saber es que no todas las bases de datos tienen soporte para tipos de datos geográficos, consultas geoespaciales, etc.

Por este motivo, antes de incluir componentes geográficos en nuestra aplicación, es necesario configurar una base de datos válida.

gvNIX nos ayudará en esta tarea y nos propone sólo bases de datos compatibles con campos de tipo GEO. Actualmente gvNIX soporta las siguientes bases de datos con soporte geo:

En nuestro caso, utilizaremos una base de datos de tipo POSTGRES. Para ello, es necesario que configures una BBDD de tipo POSTGRES en tu equipo y añadas soporte geográfico incluyendo POSTGIS.

Para realizar la configuración anterior puedes seguir los siguientes pasos:

  • Instala PostgreSql y Postgis.

  • De manera opcional, puedes instalar pgadmin para gestionar tus bases de datos Postgres de forma visual.

  • Crea una nueva base de datos.

  • Añade la extensión postgis y postgis_topology en la base de datos generada, tal y como se muestra en la siguiente imágen:

Extensiones Postgis

Para más información sobre como configurar Postgis consulta su guía de referencia aquí.

Ahora que disponemos de una base de datos válida configurada en nuestro equipo, actualizaremos nuestro proyecto generado para utilizar una base de datos de tipo POSTGRES ejecutando el siguiente comando:

jpa setup --provider HIBERNATE --database POSTGRES --userName USERNAME --databaseName DATABASENAME --password PASSWORD --hostName HOSTNAME

3.3. Paso 2: Añadir soporte GEO al proyecto

En este momento, tu base de datos está configurada para soportar campos de tipo GEO y dispone de una serie de funcionalidades para gestionar información geográfica. Sin embargo, tu proyecto no acepta estos componentes de momento.

Para añadir soporte espacial en el proyecto generado necesitamos actualizar el mismo para que utilice Hibernate Spatial.

Ejecutando el siguiente comando, nuestro proyecto dispondrá de soporte espacial:

jpa geo setup --provider HIBERNATE_SPATIAL

En caso de ejecutar el comando anterior sobre una base de datos no válida aparecerá el siguiente mensaje indicándonos qué tipos de base de datos aceptan información geográfica:

There's not any valid database to apply GEO persistence support. GEO is only supported for POSTGRES, ORACLE, MYSQL and MSSQL databases.
You must change it following the next instructions:

Replace your current dialect with the correct one:
org.hibernate.dialect.H2Dialect ==> org.hibernate.spatial.dialect.h2geodb.GeoDBDialect
org.hibernate.dialect.PostgreSQLDialect ==> org.hibernate.spatial.dialect.postgis.PostgisDialect
org.hibernate.dialect.MySQLDialect ==> org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect
org.hibernate.dialect.MySQL5Dialect ==> org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect
org.hibernate.dialect.MySQLInnoDBDialect ==> org.hibernate.spatial.dialect.mysql.MySQLSpatialInnoDBDialect
org.hibernate.dialect.MySQL5InnoDBDialect ==> org.hibernate.spatial.dialect.mysql.MySQLSpatialInnoDBDialect
org.hibernate.dialect.MySQL5DBDialect ==> org.hibernate.spatial.dialect.mysql.MySQLSpatial56Dialect
org.hibernate.dialect.MySQLSpatial56Dialect ==> org.hibernate.spatial.dialect.mysql.MySQLSpatial5InnoDBDialect
org.hibernate.dialect.Oracle10gDialect ==> org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
org.hibernate.dialect.OracleDialect ==> org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
org.hibernate.dialect.SQLServerDialect ==> org.hibernate.spatial.dialect.SQLServer2008Dialect

3.4. Paso 3: Añadir campos GEO a entidades

Ahora que ya disponemos de soporte espacial en nuestra aplicación, procedemos a añadir campos de tipo GEO en las entidades generadas en la primera parte de este tutorial.

Es funcionalidad permite añadir varios tipos de campos GEO como los siguientes:

  • POLYGON

  • POINT

  • LINESTRING

  • MULTILINESTRING

  • GEOMETRY

En este caso añadiremos los campos localización, distancia y area sobre la entidad Owner. Para ello, ejecutamos los siguientes comandos:

field geo --fieldName location --type POINT --class ~.domain.Owner
field geo --fieldName distance --type LINESTRING --class ~.domain.Owner
field geo --fieldName area --type POLYGON --class ~.domain.Owner

Los comandos para añadir campos de tipo GEO solo estarán disponibles una vez añadido el soporte espacial en nuestra apliación.

3.5. Paso 4: Generar buscadores GEO

Para ser capaces de posicionar los distintos registros de las entidades sobre una vista de mapa, necesitamos generar una serie de buscadores devuelvan la información geográfica de uno o varios registros.

Para añadir estos métodos de búsqueda a nuestra aplicación generada, utilizaremos el siguiente comando:

finder geo all

3.6. Paso 5: Generar mapas en CRU

En este punto del tutorial, deberías disponer de una Base de datos con soporte GEO, soporte espacial configurado en el proyecto, varios campos de tipo GEO añadidos en las entidades generadas y varios métodos de búsqueda de tipo GEO.

En caso afirmativo, continuaremos con la generación de campos de tipo mapa en las vistas de creación, actualización y visualización de nuestras entidades.

Gracias a estos campos visuales seremos capaces de gestionar de manera cómoda la información geográfica almacenada en la entidad.

Para añadir estos campos sobre una entidad, ejecutaremos los siguientes comandos:

web mvc geo field --controller ~.web.OwnerController --field location
web mvc geo field --controller ~.web.OwnerController --field distance
web mvc geo field --controller ~.web.OwnerController --field area

Después de ejecutar los comandos anteriores, las vistas de creación, actualización y visualización de tus entidades con campos GEO tendrán el siguiente aspecto:

Mapa vista CRU

Estos componentes visuales no son obligatorios para gestionar la información geográfica de una entidad. En caso de no añadirlos, se podrá gestionar la información geográfica mediante entrada de texto en formato WKT.

3.7. Paso 6: Generar Geoportal

En este momento puedes añadir todos los geoportales que quieras en tu proyecto. Para ello, ejecuta los siguientes comandos:

web mvc geo controller --class ~.web.MapViewerController --preferredMapping mapview --projection EPSG4326
web mvc geo controller --class ~.web.MapController --preferredMapping map

Los comandos anteriores generan distintos geoportales en nuestra aplicación y una entrada de menú distinta para cada uno de ellos. El primer Geoportal está configurado para utilizar la proyección EPSG4326. En el segundo caso no se ha especificado la proyección a utilizar, por lo que se utilizará la proyección por defecto EPSG3857.

Menu GEO
Geoportal

Si necesitas configurar opciones como nivel de Zoom inicial, punto central inicial, capas base, etc.. tendrás que editar de forma manual las opciones de la vista views/{mappath}/show.jspx.

3.8. Paso 7: Añadir entidades al Geoportal

En el punto anterior hemos generado varios geoportales vacios, es decir, sin ninguna información representada sobre los mismos.

En este punto, aprenderemos cómo añadir entidades a los geoportales generados para así representar la información geográfica almacenada en las mismas.

Ejecutamos el siguiente comando para añadir todas las entidades que dispongan de campos de tipo GEO en todos los geoportales generados:

web mvc geo entity all

Si no quieres que la entidad se añada a todos los geoportales generados, utiliza el parámetro --map en el comando anterior indicando en qué mapa quieres incluir la entidad.

Si has seguido los pasos anteriores, tu aplicación tendrá el siguiente aspecto:

Entidades en mapa
Entidad representada en el mapa
Todos los campos representados

3.9. Paso 8: Añadir capas base al Geoportal

La herramienta gvNIX también nos permite añadir una serie de capas base en nuestro geoportal generado.

Existe más de un tipo de capas base. En este momento, gvNIX permite añadir dos tipos de capas base:

A continuación añadiremos una capa de tipo Tile en nuestros geoportales generados, en concreto, añadiremos una capa base de satélite del proveedor de mapas OVI. Para ello, ejecutamos el siguiente comando:

web mvc geo tilelayer --name satellit --url "http://maptile.maps.svc.ovi.com/maptiler/maptile/newest/satellite.day/{z}/{x}/{y}/256/png8" --index 1 --opacity 0.5

Además, también añadiremos una capa base de tipo WMS en nuestros geoportales generados, en concreto, añadiremos una capa base con información geológica de la provincia de Valencia (España) servida por el IGME. Para ello, ejecutamos el siguiente comando:

web mvc geo wmslayer --name "geological map of valencia" --url "http://mapas.igme.es/gis/services/Cartografia_Geologica/IGME_GeologicoCValenciana_400/MapServer/WMSServer" --format "image/png" --transparent true --version "1.1.1" --crs EPSG4326 --layers "0,1,2,3"

Al añadir una capa de tipo WMS, es necesario tener en cuenta la proyección en la que se encuentra y en la que está configurada el mapa, ya que en caso de no coincidir, podría verse desplazada en el mapa o representada de forma incorrecta.

Los comandos anteriores añaden las capas base sobre todos los geoportales generados. Para especificar sobre qué geoportal añadir las capas base es necesario incluir el parámetro --map.

3.10. Paso 9: Añadir herramientas al Geoportal

Por defecto, al generar un geoportal utilizando la herramienta de desarrollo gvNIX, podrás ver que aparece una barra de herramientas en la esquina inferior derecha. En esta barra de herramientas solo aparece una herramienta de tipo "desplazar", representada con el icono de una mano.

Gracias a esta herramienta, podemos desplazarnos por el mapa generado. Sin embargo, existen varias herramientas más que gvNIX permite añadir en los geoportales generados:

3.10.1. Herramienta de medición

Esta herramienta permite medir distancias entre varios puntos dentro del mapa.

Para añadir esta herramienta en todas las vistas del mapa, ejecutaremos el siguiente comando:

web mvc geo tool measure --name measure

3.10.2. Herramienta personalizable

Debido a la gran variedad de herramientas que podían existir en un componente mapa, gvNIX provee una herramienta personalizable, en la que el desarrollador implementa su funcionalidad, así como el icono que mostrará.

Para incluir esta herramienta personalizable en el geoportal generado, ejecutaremos el siguiete comando:

web mvc geo tool custom --name latlng --icon fa-location-arrow --activateFunction activateLatLngTool --deactivateFunction deactivateLatLngTool --iconLibrary fa

Al añadir esta herramienta utilizando el comando anterior, indicamos las funciones javascript que utilizará al activar y desactivar la herramienta.

Así, el desarrollador deberá personalizar estas funciones javascript para añadir la funcionalidad deseada a la herramienta, tal y como se muestra a continuación:

function activateLatLngTool(element, instance, map){
 map.on("click", function(e){
 alert(e.latlng);
 });
}
function deactivateLatLngTool(element, instance, map){
 map.off("click");
}

Al finalizar los pasos anteriores, aparecerán los siguientes elementos en nuestra barra de herramientas del geoportal:

Toolbar

Los comandos anteriores añaden las herramientas sobre todos los geoportales generados. Para especificar sobre qué geoportal añadir las herramientas es necesario incluir el parámetro --map.

3.11. Paso 10: Funcionalidades avanzadas

En este momento, ya dispones de una aplicación completa con componentes GEO generada utilizando la herramienta de desarrollo gvNIX! Pero.. ¿Qué me ofrece esta aplicación GEO?

En este capitulo te dejamos una serie de funcionalidades avanzadas que pueden interesarte.

3.11.1. Filtrar Datos utilizando Datatables

Por defecto, todas las entidades que añades a los geoportales generados pueden ser filtradas. Sabemos que una capa de entidad se puede filtrar si aparece el siguiente icono en el panel de capas (TOC)

Icono de filtro

Para realizar el filtrado de datos se utiliza el componente Datatables, el cual actualiza la vista de mapa aplicando los mismos filtros que al listado, tal y como se ve en el siguiente ejemplo:

En este geoportal, visualizamos todos los registros de la entidad Owner:

Filtrado de capas

A continuación, filtramos el Datatable para que solo aparezca un propietario en el listado. Como vemos en la imágen, el filtro se aplica al Datatable y el mapa se refresca de forma automática:

Aplicado el filtro

Para modificar el tipo de filtrado de una entidad representada en los geoportales, modifica el atributo filterType de la vista src/main/webapp/WEB-INF/views/{mappath}/show.jspx. Si especificas el valor auto en dicha propiedad, al filtrar los datos utilizando el componente Datatable, el mapa se actualizará de forma automática. Si por el contrario, estableces la propiedad a manual habrá que actualizar los datos refrescando la página de forma manual. Si estableces la propiedad a none, desactivarás la funcionalidad de filtrado para dicha capa de entidad.

3.11.2. Selección de Datos utilizando Datatables

Otra funcionalidad interesante es la selección de registros utilizando el componente Datatables. Al igual que en el filtrado, se seleccionarán aquellos registros que estén seleccionados en el listado Datatables, tal y como se muestra en la siguiente imágen:

Seleccion en mapa

Esta funcionalidad es compatible con el filtrado, por lo que se puede filtrar el componente Datatables y seleccionar un registro al mismo tiempo.

Por defecto, el elemento seleccionado se mostrará en color azul. Puedes modificar el estilo de la selección editando el atributo selection de la capa de entidad.

3.11.3. Agrupación de elementos en Geoportal

Otra funcionalidad que ofrecen los geoportales generados utilizando la herramienta de desarrollo gvNIX, es la agrupación de componentes dependiendo del nivel de zoom.

Si se representan varios elementos en un espacio muy reducido, cuando el usuario haga zoom para alejar la vista, estos elementos se agruparán evitando asi problemas de rendimiento tal y como se ve en la siguiente imágen:

Agrupación

Si hacemos click sobre uno de los grupos, el mapa se desplazará hasta el nivel mínimo de Zoom en el que se pueden representar los elementos.

II. gvNIX Add-Ons

1. Add-on Web Menu

Sistema de gestión del menú web

1.1. Descripción

Este Add-on instala un nuevo sistema de gestión del menú web de la aplicación sobre la que se está trabajando para facilitar la organización de su estructura de páginas y grupos.

Las principales características de este sistema son:

Modelo de datos del menú separado de su formato de visualización.

El modelo de datos del menú no está ubicado en la misma página que lo visualiza como ocurre en el modelo de menú que se proporciona por defecto. El modelo del menú estará definido en un archivo XML independiente.

Múltiples niveles en el menú

Soporte para crear elementos jerarquizados con múltiples niveles. Permite añadir, mover y anidar en varios niveles los elementos del menú.

Gestión de elementos desde consola

Permite añadir, quitar, mover, actualizar, definir permisos, ocultar, definir enlaces, etc. para cada uno de los elementos del menú desde la consola del framework.

Integración con Spring Security

Si está instalado el sistema de seguridad, se puede establecer que ciertos elementos del menú no sean visibles si el usuario no está entre los roles permitidos para ello.

Gestiona las peticiones de Roo

Aunque el sistema de gestión del menú es distinto al que se proporciona por defecto, este nuevo sistema también gestiona las peticiones de generación de elementos del menú realizadas por el resto de comandos. Es decir, si se encuentra instalada la nueva gestión del menú y cualquier otro comando solicita crear o actualizar un elemento del menú, la solicitud se realizará correctamente utilizando el nuevo sistema de gestión.

1.2. Definiciones

Antes de continuar explicando las funcionalidades del add-on es interesante tener clara las siguientes definiciones de los elementos que conforman un menú.

Página

Representación de una URL. El destino puede ser interno o externo. Los destinos internos apuntan dentro de la propia aplicación mediante una ruta relativa, por ejemplo /entity1s/entity1?id=1. Los enlaces externos apuntan a cualquier dirección web mediante una ruta absoluta, por ejemplo https://www.cit.gva.es.

Grupo

Contenedor de páginas. El contenido de un grupo puede ser también otros grupos. También puede tener asociado una URL pero con las mismas restricciones que la página.

Menú

Estructura en árbol de páginas y grupos.

Ítem del menú

Un elemento del menú que puede ser una página o un grupo.

1.3. Instalación de la gestión del menú

El uso del sistema de gestión del menú aportado por esta herramienta es opcional. Por ello, para instalarlo y activarlo es necesario ejecutar en primer lugar el comando menu setup.

roo>
Component org.springframework.roo.addon.web.mvc.jsp.menu.MenuOperationsImpl disabled

Created SRC_MAIN_WEBAPP/WEB-INF/views/menu.xml
Updated SRC_MAIN_WEBAPP/WEB-INF/views/menu.xml
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu/MenuItem.java
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu/Menu.java
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu/MenuLoader.java
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu/ContextMenuStrategy.java
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu/BaseURLContextMenuStrategy.java
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu/URLBrothersContextMenuStrategy.java
Created SRC_MAIN_JAVA/org/gvnix/test/web/menu/URLChildrenContextMenuStrategy.java
Created SRC_MAIN_WEBAPP/WEB-INF/tags/menu/gvnixmenu.tagx
Created SRC_MAIN_WEBAPP/WEB-INF/tags/menu/gvnixitem.tagx
Updated SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx
Updated ROOT/pom.xml [added property 'gvnix.version' = 'X.Y.Z']

Este comando añadirá los siguientes elementos:

  1. Clases que representan el modelo de datos del menú. Cada una de estas clases estarán anotadas con @GvNIXMenu para poder ser identificadas. Estas clases se crearán en el subpaquete web.menu.

  2. Una Clase para la carga del menú y hacerlo disponible para su pintado en la vista. Esta clase se creará en el subpaquete web.menu.

  3. Archivo XML para almacenar el modelo de datos del menú, rellenado previamente con la información del menú de Roo que existiese en ese momento. Por defecto se creará en WEB-INF/views/menu.xml.

  4. Tagx necesarios para el pintado del menú, almacenados en WEB-INF/tags/menu.

  5. Una nueva página jspx de la gestión del menú en la que se utilizan los tagx de pintado del menú, creada en WEB-INF/views/menu.jspx.

  6. Clases para el uso de los menús contextuales. Estas clases se crearán en el subpaquete web.menu.

Para más información sobre el comando ver menu setup en el apéndice de comandos de este add-on.

El nombre del fichero XML que contiene el modelo de datos del menú se toma de la constante MENU_CONFIG_FILE de la clase anotada como @GvNIXMenuLoader.

1.4. Modificación del menú.

Para hacer cambios en el menú se deben utilizar los comandos disponibles en la consola, que serán accesibles después de haber instalado la nueva gestión del menú.

Para mas información sobre los comandos ver el apéndice de comandos de este add-on.

1.5. Futuras versiones

Mejoras a incluir en futuras versiones del add-on.

  • El modelo de datos del menú actualmente se define en un archivo XML y en un futuro podrá estar almacenada en la base de datos.

2. Add-on JPA

Add-on de utilidades enfocadas a la persistencia y consulta de las entidades.

Este add-on incluye las siguientes funcionalidades:

  • Servicios de persistencia de entidades en bloque.

  • Registro de información adicional para búsquedas por relaciones.

  • Auditoría y registro de histórico de cambios de las endidades.

  • Persistencia de entidades con campos de tipo geográfico.

Para poder utilizar estas funcionalidades hay que ejecutar previamente el comando 'jpa gvnix setup'.

2.1. Servicios persistencia en bloque

Esta funcionalidad permite generar servicios que permiten realizar operaciones de creación, actualización y eliminación de múltiples instancias de una entidad en una sola petición y de forma transaccional.

Estos servicios se generan como un bean de Spring, de forma que, para utilizarlos, solo es necesario declararlos como propiedad en la clase que los requiera y serán inyectados en el momento de la construcción de la instancia por Spring.

Un ejemplo de este servicio generado sería este:

package com.springsource.petclinic.domain;
import org.gvnix.addon.jpa.batch.GvNIXJpaBatch;
import org.springframework.stereotype.Service;

@Service
@GvNIXJpaBatch(entity = Owner.class)
public class OwnerBatchService {
}

En el correspondiente fichero OwnerBatchService_Roo_GvNIXJpaBatch.aj se generarán los siguientes métodos:

deleteAll()

Elimina todos los registro de la entidad.

deleteIn(List<Long> ids)

Elimina los registro de la entidad cuyos indentificadores se encuentren en la lista ids.

deleteNotIn(List<Long> ids)

Elimina los registro de la entidad cuyos indentificadores no se encuentren en la lista ids.

create(List<Owner> owners)

Persiste como nuevos todos los elementos de la lista owners.

update(List<Owner> owners)

Persiste todos los elementos de la lista owners.

Si algún elemento de la lista no tiene establecido su campo de clave primaria o su campo de control de concurrencia (este último sólo si está definido) el registro se guardará como registro nuevo.

findByValues(Map<String,Object> propertyValues)

Devuelve una lista de elemento cuyas propiedades coincidan (se usa el operador igual a) con todos valores recibidos en propertyValues.

deleteByValues(Map<String,Object> propertyValues)

Elimina todos elementos cuyas propiedades coincidan (se usa el operador igual a) con todos valores recibidos en propertyValues.

Para poder usar este servicio en cualquier clase solo es necesario declarar una propiedad con la anotación @Autowire. Spring se encarga de inyectar una instancia del servicio en la propiedad. Este sería un ejemplo de la declaración para usarlo:

class MyClass {

    @Autowire
    private OwnerBatchService ownerBatch;

Todas las operaciones generadas (excepto findByValues) son transaccionales. Por lo que, si se produce un error en cualquier elemento afectado, la operación entera será abortada (no se guardarán los cambios)

Esta funcionalidad es requerida por otros add-ons como Web Mvc datatables para poder realizar operaciones sobre múltiples registros a la vez.

Para generar estos servicios se pueden utilizar los siguientes comandos:

'jpa batch add'

Genera el servicio para una entidad.

'jpa batch all'

Genera el servicio para todas las entidades de la aplicación.

2.2. Información adicional para búsquedas por relaciones

Esta funcionalidad permite definir información adicional sobre las propiedades de la entidad que declaran una relación que permiten realizar búsquedas y ordenaciones sobre ella.

Esta información se utiliza actualmente para permitir realizar búsquedas de texto dentro de entidades relacionadas y su ordenación cuando se usa el add-on web mvc datatables.

No tiene implementado ningún comando. Funciona añadiendo la anotación GvNIXJpaQuery a la propiedad. Por ejemplo, para permitir que, desde el listado de Pet, sea posible buscar por el nombre y apellido de su Owner y cuando se ordene por su columna se utilicen los mismos campos, deberíamos añadir la siguiente anotación:

....
public class Pet {
    ....
    ....

    @GvNIXJpaQuery(filterBy={"lastName","firstName"}, orderBy={"lastName","firstName"})
    @ManyToOne
    private Owner owner;

2.3. Auditoría y resgistro de cambios de entidades

Esta funcionalidad añade soporte para hacer auditoría (registrar quíen y cuándo se crea o modifica un resigtro) de entidades y, opcionalmente, registrar cada uno de los cambios de las modificaciones sufridas por los registros de la entidad.

2.3.1. Configurar detalles de usuario

Es posible configurar la clase que proveerá el nombre de usuario que realiza un cambio. Para ello se ejecuta el siguiente comando:

'jpa audit setup'

Configura la auditoría de historico creando la clase que proveerá del nombre de usuario que realiza el cambio. Sólo se puede ejecutar una vez.

2.3.2. Auditoría básica de entidades

Para añadir la auditoría a las entidades se pueden utilizar los siguientes comandos:

'jpa audit add'

Añade auditoría para una entidad.

'jpa audit all'

Añade auditoría para todas las entidades de la aplicación.

Al instalar la auditoría en un proyecto gvNIX se creará una clase (con el nombre facilitado en el parámetro --service) anotada con @GvNIXJpaAuditUserService, se incluirá el siguiente método (en su correspondiente fichero .aj) para obtener los datos del Usuario:

getUser()

Devolverá el tipo facilitado en el parámetro --userType. En caso de no definir ninguno, devolverá un tipo String

Al activar al auditoría sobre una entidad, que serán marcadas con la anotación GvNIXJpaAudit, se le incluirán las siguientes propiedades (en su correspondiente fichero .aj) para almacenar los datos de auditoría:

auditCreation

Fecha de creación del elemento.

auditCreatedBy

Usuario que creó el elemento.

auditLastUpdate

Fecha de la última modificación del elemento.

auditLastUpdatedBy

Último usuario que modificó el elemento.

Hay que tener en cuenta que este add-on no provee lógica de pintado, pero estas propiedades serán añadidas de forma automática a las correspondientes vistas si se han generado, o se generan, utilizando las funcionalidades de generación automática.

En las vistas generadas de forma automática para la creación y actualización de elementos puede ser interesante realizar cambios de forma manual para que estos campos no sean rellenados o modificado por el usuario.

Para evitar la pérdida de los datos de creación, en las vistas generadas de forma automática para la actualización incluir los datos de auditoría como campos ocultos en el formulario . Si no se incluyen estos campos en las peticiones puede perderse sus valores en el proceso de binding de los objetos recibidos

Es muy importante no utilizar actualizaciones/eliminaciones del estilo em.createQuery("UPDATE Country SET population = 0, area = 0"); ya que los cambios aplicados no serán registrados por la auditoría.

Para mantener esta información acutalizada se genera un clase, anotada con GvNIXJpaAuditListener, que será registrada como EntityListener de la librería JPA. Una instancia de esta clase será llamada cada vez que un elemento de la entidad sea creado/modificado.

Esta clase tendrá implementados los siguientes métodos:

onCreate

Método llamado antes de la creación de un registro. Rellena todos los campos de auditoría de la entidad (creación y actualización).

onUpdate

Método antes de la actualización de un registro. Rellena los campos de auditoría correspondientes a la última actualización.

Este método sólo será llamado después de un merge si el registro a sufrido modificaciones en sus datos.

Las clases EntityListener requeridas por esta funcionalidad se registran de forma automática en el fichero src/main/resources/orm.xml del proyecto.

2.3.3. Auditoría y registro de cambios de entidades

Esta funcionalidad almacena todos los cambios sufridos por las entidades auditadas de forma que sea posible identificar qué, quién y cuándo se produjeron. Esto incluye las eliminaciones de los registros. Esta funcionalidad sólo se aplica a aquellas entidades marcadas con la anotación GvNIXJpaAudit (ver Auditoría básica de entidades)

En caso de actualizar o eliminar registros mediante el uso de executeQuery no se almacenarán los cambios sufridos por las entidades auditadas. Esto se debe a que no se dispararán los listeners necesarios para llevar a cabo este proceso.

Ya que esta funcionalidad puede implementarse de distinta forma, incluso dependiendo de la implementación de JPA que se esté utilizando en el proyecto, para empezar a utilizarla es necesario seleccionar un proveedor. Esto proveedores deben de estar instalados como add-on en el framework.

Para seleccionar el proveedor de registro de cambios se debe utilizar el siguiente comando:

'jpa audit revisionLog'

Selecciona el proveedor de registro de cambios a usar.

Al activar el proveedor, se instalarán las librerías requeridas y se creará una clase que representará el registro índice de cambios en la aplicación. Esta clase será anotada con GvNIXJpaAuditRevisionEntity sus métodos y propiedades serán generados por el proveedor.

Para aquellas entidades anotadas con GvNIXJpaAudit y cuyo valor storeRevisionLog sea el adecuado (YES o PROVIDER_DEFAULT/null y la opción por defecto del proveedor sea activar el registro) se generarán en el .aj los siguientes métodos:

findAll_Entidad

Devuelve la lista de todos elementos de la entidad, al estado en el que estuviesen en una fecha en concreto o en un número revisión.

find_Entidad

Devuelve una entidad por código en el estado que estuviese en un fecha en concreto o en un número de revisión

get_Entidad_Revisions

Devuelve una lista de elementos de revisión de la entidad entre fechas o números de revisión para un elemento en concreto, pudiendo especificar números de registros a devolver.

getRevisionNumberForDate

Devuelve el identificador de revisión activo a una fecha.

find_Entidad_RevisionsByDates

Devuelve una lista de elementos de revisión de la entidad entre fechas, pudiendo especificar filtros, ordenación y números de registros a devolver.

find_Entidad_Revisions

Devuelve una lista de elementos de revisión de la entidad entre números de revisión, pudiendo especificar filtros, ordenación y números de registros a devolver.

Varios de los métodos arriba descritos devuelven elementos de revisión. Este elemento es una clase declarada para añadir información adicional a la entidad sobre los cambios producidos en una revisión del elemento de la entidad. Esta clase se generará en el fichero .aj de la entidad y tendrá los siguientes métodos:

getItem

Devuelve el objeto en el estado (valores de sus datos) en una revisión.

Para el registro de cambios de eliminación, el estado devuelto por este método será el estado anterior a la eliminación (los valores antes que tenía el elemento cuando fue eliminado).

getRevisionNumber

Devuelve el identificador de la revisión.

getRevisionUserName

Devuelve el nombre del usuario que realizó los cambios registrados.

getRevisionDate

Devuelve la fecha en el que se registraron los cambios.

isCreate

Informa si tipo de cambio registrado en este elemento es una creación.

isUpdate

Informa si tipo de cambio registrado en este elemento es una actualización.

isDelete

Informa si tipo de cambio registrado en este elemento es una eliminación.

Para estos casos, el estado devuelto por el método getItem() será el estado anterior a la eliminación (los valores antes que tenía el elemento cuando fue eliminado).

getType

Devuelve una cadena que representa el tipo de cambio del registro: CREATE, UPDATE o DELETE.

Además de lo métodos aquí descritos, cada proveedor puede incluir métodos necesario para dar soporte a su funcionalidad.

2.3.4. Proveedor de registro de cambios Hibernate Envers

Esta implementación de provee la funcionalidad de gestión de revisiones basada en el el módulo de la implementación de JPA Hibernate denominado Envers.

Para seleccionar este proveedor hay que ejecutar el comando: jpa audit revisionLog --provider H-ENVERS

Lógicamente, al ser un módulo de Hibernate, este proveedor de gestión de revisiones sólo estará disponible en aquellos proyectos cuyo proveedor de persistencia sea Hibernate.

Las características de este proveedor son:

  • Mantiene el estado de relaciones (siempre que ambas entidades estén gestionadas).

  • Los estados se mantienen en tablas adjuntas a las auditadas.

  • Soporta búsquedas en el histórico utilizando su propio API. Esto tiene la limitación de únicamente poder filtrar sobre los datos de la entidad principal de la búsqueda (en la implementación actual, aunque en la documentación comentan que en un futuro habrá soporte para filtrar por las relaciones).

En los proyectos en los que Spring Security sea el proveedor de seguridad, el proveedor ya genera el código necesario, en la clase RevisionEntity para obtener el usuario que está realizando el cambio. Para el resto, será necesario realizar un push-in de la clase RevisionLogEntityListener y ajustar la implementación del método newRevision.

Para acceder a la API de lectura de Envers se genera un método estático en las entidad con el soporte establecido llamado auditReader. Para ver mas información sobre el uso de AuditEntityReader ver la documentación de el JavaDoc de la clase o la documentación del módulo Envers.

2.4. Persistencia de entidades con campos de tipo geográfico

Esta funcionalidad permite guardar entidades con campos de tipo geográfico.

2.4.1. Configuración del proyecto para soporte geográfico

Para poder guardar entidades con campos de tipo GEO es necesario configurar el proyecto generado. Para ello se ejecuta el siguiente comando:

'jpa geo setup'

Configura el proyecto para poder guardar entidades con campos de tipo geográfico. Este comando solo funcionará si se ha instalado persistencia en el proyecto con proveedor HIBERNATE y se ha seleccionado una de las siguientes bases de datos:

  • POSTGRES

  • MYSQL

  • ORACLE

  • MSSQL

2.4.2. Añadir campos de tipo geográfico a entidades

Una vez configurado el proyecto para poder guardar entidades con campos de tipo geográfico, ya es posible añadir campos de tipo geográfico a las entidades. Para poder añadir estos nuevos tipos de campo, es necesario ejecutar este comando:

'field geo'

Añade un nuevo campo de tipo GEO a la entidad seleccionada. Los nuevos campos añadidos pueden ser de los siguientes tipos:

  • POINT (Se guarda un único punto en la base de datos)

  • LINESTRING (Se guardan una serie de puntos que forman una linea continua)

  • MULTILINESTRING (Se guardan una serie de puntos que forman varias lineas continuas)

  • POLYGON (Se guardan una serie de puntos que forman un polígono. Siempre empieza y acaba en el mismo punto.)

  • GEOMETRY (Se guarda una serie de puntos que forman una geometría. Acepta cualquiera de las geometrías anteriores.)

2.4.3. Implementación de buscadores para campos GEO

Para poder realizar búsquedas sobre campos de tipo GEO es necesario generar una serie de métodos. Para ello se ejecutan los siguientes comandos:

'finder geo all'

Genera los buscadores de todos los campos de tipo GEO de todas las entidades registradas en el proyecto.

'finder geo add'

Genera los buscadores de todos los campos de tipo GEO para la entidad seleccionada.

3. Add-on Monitoring

Uso del componente Java Melody como sistema de monitorización para aplicaciones web.

3.1. Descripción

Este Add-on genera una nueva página desde donde podemos ver lo que consume la generación y ejecución de vistas, consultas, scripts y demás elementos que se generan y componen nuestra aplicación web.

3.2. Instalación de la monitorización

Para instalarlo, hay que utilizar el comando monitoring setup, el cual instalará todo lo necesario para el funcionamiento básico de la monitorización de nuestra aplicación. Se encargará de las dependencias y de modificar los ficheros de configuración necesarios para el funcionamiento de la monitorizacion de JSP, SQL, consultas, etc.

3.3. Monitorizando a través de Spring

Para monitorizar a través de las llamadas de Spring, tendremos que configurar que métodos deseamos monitorizar, para ello utilizaremos alguno de los siguientes comandos, siempre después de haber instalado el add-on: monitoring all, monitoring add class, monitoring add method o monitoring add package. Al ejecutar estos comandos se añadiran anotaciones que nos permitirán acceder a las llamadas que se ejecuten a los metodos monitorizados y ver sus interacciones.

3.4. Accediendo a la monitorización

Una vez todo configurado y con nuestra aplicación en marcha, bastará pulsar en la entrada de menú que se ha generado para su acceso, en caso de haberla desactivado, bastará con acceder a la dirección principal de nuestra aplicación, seguida de "/monitoring".

4. Add-on Web MVC

Add-on de utilidades para la capa Web de tipo Spring MVC.

Este add-on incluye dos funcionalidades:

  • Interfaz Web para operaciones de persistencia de entidades en bloque.

  • Visualización de vistas usando jQuery como librería de JavaScript.

4.1. Interfaz para operaciones de persistencia en bloque

Esta funcionalidad añade el interfaz web a un controlador para poder recibir peticiones de creación, actualización y eliminación de registros de una entidad en bloque.

Actualmente se utiliza para dar soporte a las operaciones de modificación múltiple que el add-on web mvc datatables.

Los método añadidos por esta funcionalidad se apoyan en las operaciones de persistencia en bloque generadas por el 'add-on jpa' proporciona. Por ello, sólo se podrá añadir sobre controladores cuya entidad relacionada tenga generado este servicio.

Para generar estos métodos se pueden utilizar los siguientes comandos:

'web mvc batch setup'

Instala las dependencias y ajusta la configuración.

'web mvc batch add'

Genera los métodos en un controlador.

'web mvc batch all'

Genera los métodos para todos los controladores.

4.1.1. Métodos de creación y actualización

Los métodos de actualización y creación reciben una Array de elementos en formato JSON.

Como resultado generan un objeto JsonResponse (también en formato JSON) con el resultado de la operación.

El JsonResponse se compone de las siguientes propiedades:

status

Resultado de la operación: SUCCESS o ERROR

exceptionMessage

Mensaje de error (si lo hay) encontrado al ejecutar la operación.

bindingResult

Errores encontrados en la carga y/o validación de los datos recibidos.

El formato de este objeto en JSON es como el siguiente:

 {
    OBJECT_INDEX : { FIELD1_NAME : FIELD_ERROR_MSG, FIELD2_NAME : FIELD_ERROR_MSG, ...},
    OBJECT_INDEX2 : { FIELD1_NAME : FIELD_ERROR_MSG,
      FIELD_OBJECT_NAME : { SUBOBJECT_FIELD: FIELD_ERROR_MSG, ... }
      FIELD_LIST_NAME: {
         OBJECT_FIELD_ITEM_INDEX : {ITEM_LIST_FIELD: FIELD_ERROR_MSG, ... },
         OBJECT_FIELD_ITEM_INDEX2 : {ITEM_LIST_FIELD: FIELD_ERROR_MSG, ... },
      },
      ...
    },
    ...
 }
value

Objetos persistidos o recibidos.

4.1.2. Método de eliminación

El método de eliminación recibe los siguientes parámetros:

{entidad}

Valores de las propiedades usado como filtro base de la operación de borrado completo.

all

Si recibe un true elimina todos los elementos que cumplan el filtro base. Si no se ha recibido filtro base borrará todos los elementos. Los parámetros relativos a borrado por identificadores serán ignorados.

idList[]

Lista de identificadores de elementos a tener en cuenta para el borrado.

deleteIn

Si recibe un true cuyo identificador se encuentra en idList[]. De lo contrario elimina los elementos cuyo identificado no se encuentra en idList[].

Como resultado, el método devuelve: el número de elementos eliminados

Si se produce un error en la eliminación el método devuelve un estado INTERNAL_SERVER_ERROR(500) y el mensaje de error.

4.1.3. Carga de datos en formato JSON

Debido a que las operaciones de creación y actualización reciben los datos en formato JSON y Spring no tiene soporte todavía para cargar objetos en este formato usando el conversionService (ver tarea en el JIRA de Spring). Mientras tanto, esta funcionalidad incluye una librería propia que añade un MappingHandlerAdapter que es capaz de hacerlo. Además, este objeto realizar la validación y rellenar un BindingResult con los resultados de la carga.

El Jackson2RequestMappingHandlerAdapter se configura en el fichero webmvc-config.xml y se encarga de gestionar todas las peticiones cuyo @RequestMapping esté configurado con

consumes = "application/json"

4.2. Visualización con jQuery

Esta funcionalidad permite modificar la visualización de las vista para que utilice la librería jQuery en vez de la estándar jQuery.

Las opciones de este add-on no son compatibles con el add-on Web Screen Patterns.

Para poder utilizar el list generado por el add-on web mvc datatables es necesario que la vista esté convertida a jQuery (ya que el componente dataTables que se utiliza está creado en base a esta librería).

Los artefactos que se instalan son:

  • Ficheros .js de la librería jQuery y jQueryUI además de otros plugins, como jQuery.validate, necesarios para reemplazar todas las funcionalidades disponibles de base en las vistas.

  • Ficheros .tagx con la nueva implementación de pintado de los componentes.

  • Ficheros de estilos e imágenes.

Para utilizar esta funcionalidad dispone de los siguientes comandos:

'web mvc jquery setup'

Instala los artefactos necesarios.

'web mvc jquery add'

Convierte las vista de un controlador a jQuery.

'web mvc jquery all'

Convierte todas las vistas a jQuery.

'web mvc jquery update tags'

Actualiza los artefactos requeridos por jQuery. Util para actualizar un proyecto a una nueva versión de gvNIX.

4.2.1. Conversión de las vistas a jQuery

En el proceso de conversión consta de la correspondiente anotación en el controlador @GvNIXWebJQuery y la actualización de las rutas a los .tagx en sus ficheros .jspx.

Los .tagx se han creado para que sean compatibles con los originales, por lo que, en principio, no será necesario modificar las páginas .jspx generadas de forma estándar por los comandos de ROO.

Si se han añadido nuevos .tagx personalizados al proyecto basados en DOJO, es posible que tengan que ser replicados usando la nueva librería.

5. Add-on Bootstrap

Implementación de Bootstrap 3 en el proyecto gvNIX.

5.1. Descripción

Este add-on permite configurar el proyecto gvNIX con la estructura HTML necesaria para implementar Bootstrap 3. Además, incluye todos los recursos necesarios para modificar la apariencia de la aplicación por una por defecto basada en Bootstrap 3.

5.2. Instalación de Bootstrap 3

Para instalarlo, hay que utilizar el comando web mvc bootstrap setup, el cual solo estará disponible después de instalar el add-on JQuery en nuestro proyecto. Este comando detectará de forma automática, aquellos addons que ya hayan sido instalados y modificará sus componentes para una correcta visualización utilizando Bootstrap. Además, los addons que se instalen después de instalar Bootstrap tendrán apariencia Bootstrap por defecto.

5.3. Actualización de componentes

Para actualizar los componentes instalados de Bootstrap basta con ejecutar web mvc bootstrap update, el cual solo estará disponible después de haber instalado Bootstrap.

5.4. Apendice de comandos

Para ver con mas detalle el comando que proporciona el add-on consultar la sección de comandos del add-on Bootstrap.

6. Add-on Web MVC Datatables

Uso del componente dataTables en las vistas list de los controladores.

6.1. Descripción

Este Add-on reemplaza el widget de lista de las vistas de las entidades para usar el plugin de jQuery dataTables. Para ello, se usa una adaptación de la librería de tag JSP Dandelion-DataTables que se integra y adapta a la generación de vistas de Spring Roo.

Las opciones de este add-on no son compatibles con el add-on Web Screen Patterns.

Las principales características de este widget son:

Ordenación de datos por uno o más campos.

La tabla permite al usuario final ordenar los datos, por una o más columnas, y en el sentido que el desee. Las columnas disponibles para la ordenación y su sentido son configurables en la página.

Filtrados por columnas y búsquedas globales

Soporta filtrar los datos mostrados por columna, además de hacer búsquedas de texto sobre los resultados de los filtros. La configuración de que filtros están disponibles para el usuario se pueden configurar en la página. Además, estos filtros por columna disponen de un asistente para realizar búsquedas dependiendo del tipo de dato representado en cada una de ellas.

Paginación de datos ajustable

Los datos, filtrados o sin filtrar, se paginan sin necesidad de refrescar la página. El tamaño de la página puede ser seleccionado por el usuario final.

Acceso a los datos en la misma página o por petición por AJAX

Los datos que alimentan la tabla pueden estar integrados en la página o usar peticiones AJAX para ir solicitándolos a medida que el usuario los requiera.

Soporta múltiples plugins y es extensible

Soporta múltiples plugins como ColReorder (permite al usuario reordenar las columnas), FixedHeader (que mantiene las cabeceras de las columnas visibles cuando se desciende por páginas largas), etc.

Registro de Callbacks en distintos eventos

Soporta registrar funciones JavaScript a ejecutar por el widget cuando: termina la inicialización, al crear una línea, al pintar el píe de tabla, etc…​

Visualización en modo Registro

Permite realizar la visualización en modo Registro, es decir, mostrando un registro por página con sus valores completos.

Visualización de Detalles

Se puede añadir la visualización de un o varios detalles (listado de entidades relacionadas), con varios niveles, al marcar o visualizar (dependiendo del modo de visualización) un elemento de la tabla.

Actualización en línea

Modo que permite actualizar los elementos de la tabla desde la misma línea que los está visualizando. Es posible modificar multiples registro a la vez.

6.2. Instalación del soporte para Datatables

Esta funcionalidad depende de las librerías de jQuery por lo que, el primer paso, será instalar las librerías usando el comando 'web mvc jquery setup' si no estuviese ya instalado.

Para instalar esta funcionalidad hay que ejecutar el comando 'web mvc datatables setup'.

Este comando añadirá los siguientes elementos:

  1. Imágenes y hojas de estilo utilizadas por el widget. Estos ficheros se instalan en webapp/images/datatables y webapp/styles/datatables respectivamente.

  2. Los archivos javaScript de jQuery.datatables ( tanto en su versión optimizada como estándar) y algunos plugins para dataTables, creados por el equipo de gvNIX, para utilizados en las funcionalidades disponibles (como selección, edición, etc…​), en el directorio webapp/scripts/datatables. Para obtener información de las versiones de estos ficheros, consultar el fichero README.txt que se instala en el directorio.

  3. Tagx necesarios utilizados en las páginas para el pintado del widget, almacenados en WEB-INF/tags/datatables.

  4. Unos fichero de propiedades para diversos aspectos de configuración en src/main/resources/datatables*.properties y las cadenas de internacionalización.

  5. Actualiza el fichero WEB-INF/tags/util/load-scripts.tagx para que las páginas puedan localizar los recursos de hojas de estilo y javaScript requeridos.

  6. Algunos ajustes en el fichero WEB-INF/web.xml y WEB-INF/spring/webmvc-config.xml requeridos para el correcto funcionamiento de widget.

  7. La dependencia a este add-on, librerías de utilidades utilizadas para la gestión de peticiones de datos y a la librería de tag adaptada. Esta última tiene como dependencias las dependencias a las librerías de Dandelion-DataTables.

Para más información sobre el comando ver 'web mvc datatables setup' en el apéndice de comandos de este add-on.

6.3. Usar datatables en la vista "list" de un controlador

Para poder utilizar el widget de datatables en el listado es necesario que esté usando los componentes jQuery. Para ello usar el comando 'web mvc jquery add' o 'web mvc jquery all' antes de utilizar este add-on con un controlador.

Para utilizar el widget de datatables en el listado de un controlador de entidad es necesario ejecutar el comando 'web mvc datatables add'.

Este comando añade la anotación @GvNIXDatatables al controller para generar los métodos necesario para gestionar las peticiones que realiza el widget.

Además, actualiza la página list.jspx para cambiar las rutas a los tagx utilizados para pintar la tabla a los instalados por el add-on en el directorio WEB-INF/tags/datatables.

Este add-on incluye, además, el comando 'web mvc datatables all' que aplica los cambios a todos los controllers de la aplicación.

Para mas información sobre los comandos ver el apéndice de comandos de este add-on.

6.4. Ajustar la configuración del datatables de una vista

Los tags creados para este add-on, que se pueden encontrar en WEB-INF/tags/datatables, son compatibles con los tags estándar que se incluyen por defecto, incorporando además las opciones que ofrece la librería de Dandelion-DataTables.

Las opciones disponibles para los tags se pueden consultar en la declaración de los propios ficheros de tags, o en la página de referencia de Dandelion-DataTables. Algunos de los atributos no están disponibles debido a la integración con Spring Roo o los algunas opciones necesarias para la integración de los distintos modos de visualización preparados.

Para personalizar los ajustes de alguna vista, modificar el fichero list.jspx correspondiente tal y como se realiza con los tags estándar.

6.5. Cambiar el modo de datos de Datatables

Para proveer de datos al widget, se dispone de dos métodos.

  1. DOM o la carga de datos incrustados en la misma página. Una vez cargados los datos, el widget se encarga de paginarlos, ordenarlos y filtrarlos a través de javaScript en la propia página.

  2. AJAX el widget hace peticiones AJAX al servidor para obtener los datos en base a la paginación, orden y filtro. Luego los muestra repintando la tabla a través de javaScript en la propia página.

La opción por defecto que instala el add-on es la de AJAX, ya que es más escalable para volúmenes de datos grandes.

El modo de datos del controlador se establece con la opción --ajax al ejecutar el comando 'web mvc datatables add' o modificar el atributo 'ajax' de la anotación GvNIXDatatables. gvNIX actualizará el controlador para que el modo sea accesible tanto en el mismo (para los métodos de peticiones) como en la página.

6.6. El control de búsqueda y filtros por columnas

Por defecto, la tabla muestra un control de búsqueda que permite filtrar el contenido visualizado en la tabla. Esta búsqueda se realiza en formato texto. Es decir, compara el texto de cada valor sea cual sea su tipo.

Dependiendo del modo de acceso a datos y del tipo de dato el resultado de la búsqueda puede ser distinto: Para tablas en modo DOM, la búsqueda ser realiza sobre el texto que se visualiza en cada celda, mientras que, en modo AJAX se ejecuta una consulta contra la base de datos.

Para las búsquedas en las tablas en modo AJAX hay que tener en cuenta lo siguiente:

  • Para los campos de tipo entidad hay que anotar la propiedad de la relación con la anotación @GvNIXJpaQuery del add-on jpa para que se pueda construir la consulta con dichos campos.

  • Es posible buscar por los campos de tipo fecha, pero hay que tener en cuenta que, la transformación a texto la realiza la base de datos con su formato predeterminado no por el formato en el que se visualiza.

Los filtros por columna funcionan de la misma forma que la búsqueda, aplicando las misma reglas explicadas anteriormente, pero sólo con los datos de dicha columna. Ambas opciones se acumulan para mostrar el resultado en la tabla.

Para activar el filtrado en una columna hay que añadir el parámetro filterable="true" en la etiqueta table:column correspondiente a la columna en el fichero list.jspx. Al añadir este filtrado por columna se añadirán de forma automática un asistente de búsqueda al lado de cada filtro que permitirá realizar búsquedas avanzadas dependiendo del tipo de dato representado en cada columna.

6.7. Filtros Simples

Los filtros por columna llevan predefinidas unas operaciones dependiendo del tipo de campo de la columna. Los nombres de estas operaciones son multidioma y pueden ser configuradas por el desarrollador. Estas operaciones pueden ser introducidas manualmente o utilizando el asistente de búsqueda comentado anteriormente. Por defecto se pueden utilizar las siguientes operaciones:

Campos de Tipo Texto

  • cadena: Buscará la cadena de texto introducida

  • =cadena: Buscará la cadena de texto introducida después del simbolo igual

  • CONTIENE(cadena): Buscará todos los registros que para esa columna contengan la cadena de texto introducida

  • EMPIEZA(cadena): Buscará todos los registros que para esa columna empiecen por la cadena de texto introducida

  • TERMINA(cadena): Buscará todos los registros que para esa columna terminen por la cadena de texto introducida

  • ESVACIO: Buscará todos los registros que para esa columna estén vacios o sean nulos

  • NOESVACIO: Buscará todos los registros que para esa columna no estén vacios y no sean nulos

  • ESNULO: Buscará todos los registros que para esa columna sean nulos

  • NONULO: Buscará todos los registros que para esa columna no sean nulos

Campos de Tipo Numérico

  • número: Buscará el valor numérico exacto en la columna actual

  • =número: Buscará el valor numérico exacto en la columna actual

  • >número: Buscará todos los registros cuyo valor sea mayor que el indicado

  • >=número: Buscará todos los registros cuyo valor sea mayor o igual que el indicado

  • <número: Buscará todos los registros cuyo valor sea menor que el indicado

  • ⇐número: Buscará todos los registros cuyo valor sea menor o igual que el indicado

  • <>número: Buscará todos los registros cuyo valor sea distinto que el indicado

  • !=número: Buscará todos los registros cuyo valor sea distinto que el indicado

  • ENTRENUMERO(n1;n2): Buscará todos los registros cuyo valor se encuentre entre el primer número indicado y el segundo

  • ESNULO: Buscará todos los registros que para esa columna sean nulos

  • NONULO: Buscará todos los registros que para esa columna no sean nulos

Campos de Tipo Fecha

  • FECHA(fecha): Buscará todos los registros con la fecha introducida para la columna del filtro

  • ESANYO(año): Buscará todos los registros que contengan el año en la fecha de la columna del filtro

  • ESMES(mes): Buscará todos los registros que contengan el mes en la fecha de la columna del filtro

  • ESDIA(dia): Buscará todos los registros que contengan el día en la fecha de la columna del filtro

  • ENTREFECHA(fecha1;fecha2): Buscará todos los registros cuyas fechas se encuentren entre la primera fecha y la segunda

  • ESNULO: Buscará todos los registros que para esa columna sean nulos

  • NONULO: Buscará todos los registros que para esa columna no sean nulos

Campos de Tipo Boolean

  • VERDADERO: Buscará todos los registros cuyo valor para la columna sea true

  • FALSO: Buscará todos los registros cuyo valor para la columna sea false

  • ESNULO: Buscará todos los registros que para esa columna sean nulos

  • NONULO: Buscará todos los registros que para esa columna no sean nulos

6.8. Modo visualización de registro

Este modo de visualización muestra un registro por cada página para mostrar mas información sobre cada uno.

Para ello, se pinta la vista show del propio registro y se incrusta dentro de la celda de la tabla.

Este modo de visualización sólo permite el modo de acceso a datos 'AJAX' y no están soportadas la herramientas de búsqueda, ordenación, filtros y edición.

Para establece este modo de visualización hay que usar el parámetro --mode show al ejecutar el comando 'web mvc datatables add'.

Para vistas que ya transformadas, se pude establecer este modo modificando los valores de la anotación @GvNIXDatatables y añadirle el atributo mode = "show". Comprobar que también esta establecido el valor ajax = true.

6.9. Visualización de detalles

Este opción permite la visualización de datos relacionados con un registro al pie de la página. Los datos mostrados se obtendrán a parir de una propiedad de relación 1:N de la entidad actual. La propiedad debe tener configurada el valor mappedBy en la anotación @OneToMany

Para mostrar los datos del detalle se utilizará la vista list de la entidad hija, la cual debe de utilizar también una vista dataTable, usando exactamente la misma configuración de visualización y modo de datos (pero con sus datos filtrados para mostrar los datos relacionados con el padre). En la vista de detalle estarán disponibles todas las opciones disponibles originalmente, incluido si tiene activado la visualización de detalles.

Los registros mostrados en el detalle dependerá del registro actual. Este dependiendo del modo de visualización se selecciona:

modo tabular (estándar)

Haciendo doble click sobre la linea deseada. La linea actual se marcará de un color distinto (por defecto verde) y en caso de disponer detalles asociados, se desplazará hasta la posición de los mismos para facilitar su localización.

modo registro

El detalle muestra los datos para el registro actual (sólo se ve un registro por página)

Para añadir las visualización del detalle en una vista hay que usar comando 'web mvc datatables details add'.

6.10. Eliminación múltiple

Las listas soportan eliminación múltiple de líneas. Esta operación se activa de forma automática cuando el controlador tiene activado las operaciones de actualización en bloque.

Cuando esta opción está disponible, en la tabla aparecerá una columna de controles de marcado para permitir la selección de los elemento sobre los que se quiere actuar. En la cabecera de esta columna se mostrará un icono que permite la selección de todos los elementos o limpiar la selección.

La opción de seleccionar todo selecciona todos los registros del listado incluidos los que no se están visualizando en la página actual. La selección se mantiene con las operaciones de búsqueda, filtrado y paginación.

En la linea de estado se informa del total de registros seleccionados y cuantos de ellos están en la página actual.

Al pulsar sobre el botón elimina de la cabecera de la tabla, se pedirá confirmación, mostrando el total de registros a eliminar. El botón de eliminación de la línea sigue funcionando de la forma habitual.

6.11. Edición en línea

Las listas soportan la edición sobre la misma de líneas de los datos de la entidad sin necesidad de cambiar de página o recargarla.

Esta opción requiere que el controlador tenga activado las operaciones de actualización en bloque y no está soportado para el modo de visualización registro.

Entrar en modo edición hay que pulsar sobre el botón de editar de dicho registro o seleccionar los registros deseados en el control de marcado y pulsar el botón de edición de la cabecera de la tabla.

Al activar la edición de un registro, el control solicita al servidor el contenido de la vista update de la entidad y cambia el contenido de las columnas de dicha fila por los controles de entrada del formulario original. Por tanto los ajuste de los controles de actualización se realizan en un único lugar.

Después de entrar en modo edición aparecerán dos botones en la cabecera de la tabla para guardar los cambios o cancelar la edición. Estas acciones afectan a todos los registros en edición, se estén visualizando o no.

Durante la edición, las funciones de paginación, filtrado, búsqueda y ordenación estarán disponibles de la forma habitual, manteniendo los cambios realizados en los campos de las filas en edición.

Para que la actualización funcione correctamente la tabla debe contener todas las columnas requeridas para la edición del elemento. De no ser así la actualización de los registros fallará.

Al pulsar sobre el botón de guardar, el control recogerá los datos de las filas en edición y realizará una petición de actualización en bloque, de forma que si hay algún problema con algún registro ningún cambio se persistirá.

Si se encuentra algún problema de validación en algún registro, el control mantendrá el estado de edición de las lineas, marcando las lineas afectadas por errores de un color rojizo. Además, mostrará el mensaje de error generado en el servidor debajo de cada campo afectado.

Para activar esta opción hay que usar el parámetro --inline true al ejecutar el comando 'web mvc datatables add'.

Para vistas que ya transformadas, se pude activar la opción modificando los valores de la anotación @GvNIXDatatables y añadirle el atributo inlineEditing = true.

6.12. Registro creado en primera posición

Al crear un nuevo registro, se colocará automáticamente en la primera posición del listado sin tener en cuenta los filtros u ordenación del Datatable.

Gracias a esto tendremos siempre visible el registro que se ha editado.

Al recargar la página, se ordenará el registro de forma correcta siguiendo la ordenación y los filtros establecidos en el Datatable.

Esta funcionalidad se aplica tanto a Datatables maestros como para detalles asociados

6.13. Registro editado en primera posición

Al actualizar un registro, se colocará automáticamente en la primera posición sin tener en cuenta los filtros u ordenación del Datatable.

Gracias a esto tendremos siempre visible el registro que se ha editado.

Al recargar la página, se ordenará el registro de forma correcta siguiendo la ordenación y los filtros establecidos en el Datatable.

Esta funcionalidad se aplica tanto a Datatables maestros como para detalles asociados.

6.14. Registro seleccionado siempre visible

Al acceder a una página del listado Datatable que contenga un registro seleccionado por el usuario, se navegará de forma automática hasta este registro.

Gracias a esto tendremos siempre posicionado en pantalla el registro que se ha seleccionado.

7. Add-on Web MVC GEO

Uso del componente Mapa para representar y posicionar entidades que dispongan de campos de tipo GEO.

7.1. Descripción

Este Add-on permite representar en vistas de tipo Mapa, aquellas entidades que dispongan de campos de tipo GEO.

Las principales características de este widget son:

Representar entidades en Mapa

Permite representar aquellas entidades que dispongan de campos de tipo GEO en vistas de tipo Mapa. Se podrán mostrar/ocultar aquellos campos GEO que se deseen.

Filtrado de entidades

Soporta filtrar los registros de una entidad representados en el mapa utilizando el componente 'Datatable'.

Selección de entidades

Permite seleccionar uno o varios datos representados en la vista de Mapa utilizando el componente 'Datatable'.

Representar Capas Base en Mapa

Además de representar entidades en la vista de Mapa, también es posible representar capas obtenidas desde un servidor de mapas. Es posible representar capas de tipo "tile" y capas de tipo "WMS".

Barra de Herramientas

Este componente dispone de una serie de herramientas que pueden ser añadidas a la vista de mapa. También se pueden añadir herramientas estándar que el desarrollador puede personalizar para que realicen las acciones que él desee.

Personalización de componentes (Markers, Colores, etc…​)

Por defecto, la apariencia de las entidades que se representan en el mapa se generan de forma aleatoria. El desarrollador puede personalizar el icono, el color del icono, el color del marker o linea, etc…​ Si la entidad tiene la opción de ser seleccionada desde el componente 'Datatable' podrá configurar también, la apariencia con la que se representará esta entidad al ser seleccionada. De este mismo modo, se podrá configurar la apariencia de las herramientas genéricas.

7.2. Instalación del soporte para vista de Mapa

Esta funcionalidad depende de las librerías de jQuery por lo que, el primer paso, será instalar las librerías usando el comando 'web mvc jquery setup' si no estuviese ya instalado.

Para instalar esta funcionalidad hay que ejecutar el comando 'web mvc geo setup'.

Este comando añadirá los siguientes elementos:

  1. Imágenes y hojas de estilo utilizadas por el widget. Estos ficheros se instalan en webapp/images y webapp/styles/leaflet respectivamente.

  2. Los archivos javaScript de leaflet ( tanto en su versión optimizada como estándar) y algunos plugins para leaflet, creados por el equipo de gvNIX, para utilizados en las funcionalidades disponibles (como selección, edición, etc…​), en el directorio webapp/scripts/leaflet.

  3. Tagx necesarios utilizados en las páginas para el pintado del widged, almacenados en WEB-INF/tags/geo.

  4. Actualiza el fichero WEB-INF/tags/util/load-scripts.tagx para que las páginas puedan localizar los recursos de hojas de estilo y javaScript requeridos.

  5. La dependencia a este add-on y librerías de utilidades utilizadas para la gestión de peticiones de datos.

Para más información sobre el comando ver 'web mvc geo setup' en el apéndice de comandos de este add-on.

7.3. Generar vista de Mapa

Para poder visualizar una vista de Mapa en nuestro proyecto, es necesario ejecutar el comando 'web mvc geo controller'.

Este comando genera un controlador anotado con @GvNIXMapViewer que será el encargado de mostrar la vista del mapa que acabamos de crear. Además se podrá configurar la proyección en la que trabaja el mapa generado.

Además, genera la página show.jspx que será la encargada de representar el mapa y todos sus componentes.

Para mas información sobre los comandos ver el apéndice de comandos de este add-on.

7.4. Generar campos de mapa en vistas CRU

Por defecto, a la hora de guardar campos de tipo geográfico se utilizará formato WKT que tendrá que ser introducido de forma manual por el usuario.

Sin embargo, este add-on permite transformar estos campos de texto a componentes de tipo Mapa, gracias a los cuales se facilita la introducción de datos de tipo GEO en una entidad. Para utilizar estos tipos de campo, se ejecutará el siguiente comando 'web mvc geo field'.

Este comando modifica las vistas de create.jspx, update.jspx y show.jspx de la entidad sobre la que se aplica cambiando los inputs de los campos seleccionados por componentes de tipo mapa.

Para mas información sobre los comandos ver el apéndice de comandos de este add-on.

7.5. Añadir entidades a la vista de Mapa

Al generar la vista de mapa se generará una vista vacía con una capa base por defecto.

Para añadir nuevas entidades a la vista de mapa y que sean representadas sus campos de tipo geográfico, es posible ejecutar los siguientes comandos:

'web mvc geo entity all'

Añade todas las entidades con campos de tipo GEO a la vista de mapa

'web mvc geo entity add'

Añade la entidad seleccionada a la vista de mapa.

Este comando modifica los controladores de las entidades sobre los que se aplica el comando añadiendo la anotación @GvNIXWebEntityMapLayer.

Al añadirse esta anotación, se añade en la vista show.jspx del mapa la nueva entidad a representar.

Para mas información sobre los comandos ver el apéndice de comandos de este add-on.

7.6. Añadir Capas Base la vista de Mapa

Al generar la vista de mapa se generará una vista vacía con una capa base por defecto.

Para añadir nuevas capas base, es posible ejecutar los siguientes comandos dependiendo del tipo de Capa Base que queramos crear:

'web mvc geo tilelayer'

Añade una capa base de tipo Tile a la vista del mapa

'web mvc geo wmslayer'

Añade una capa base de tipo WMS a la vista del mapa

Estos comandos añaden en la vista show.jspx del mapa la nueva capa base.

Para mas información sobre los comandos ver el apéndice de comandos de este add-on.

7.7. Generar nuevas herramientas en la vista del Mapa

Por defecto, la vista de Mapa se genera con una única herramienta que permite desplazarnos por el mapa.

Sin embargo, este add-on permite añadir nuevas herramientas a la vista de mapa ejecutando los siguientes comandos:

'web mvc geo tool measure'

Añade una herramienta de medición a la vista del mapa

'web mvc geo tool custom'

Añade una herramienta personalizada a la vista del mapa

Este comando añade en la vista show.jspx del mapa la nueva herramienta a utilizar.

Para mas información sobre los comandos ver el apéndice de comandos de este add-on.

8. Add-on Campos Lupa

Implementación de campos lupa en el proyecto gvNIX.

8.1. Descripción

Este add-on permite utilizar componentes de tipo lupa en aplicaciones gvNIX. Gracias a estos componentes, podemos buscar registros de forma sencilla de campos relacionados sin tener que visualizar todos los datos en un desplegable.

8.2. Instalación del componente lupa

Para instalarlo, hay que utilizar el comando web mvc loupe setup, el cual solo estará disponible después de instalar el add-on JQuery en nuestro proyecto.

8.3. Permitiendo a una entidad utilizar el campo lupa

Una vez instalados todos los componentes, es necesario generar una serie de métodos para realizar las búsquedas y la visualización de los resultados. Para que el controlador disponga de estos métodos, utilizaremos el comando web mvc loupe set sobre el controlador seleccionado.

8.4. Utilizando componentes lupa

Ahora que el Controlador ya dispone de los métodos necesarios, ejecutaremos el comando web mvc loupe field sobre el field de la entidad a la que pertenece el controlador con los métodos generados. Una vez ejecutado este comando, transformaremos el campo indicado a un campo de tipo lupa en la capa web de nuestra aplicación.

8.5. Actualizando componentes lupa

Para mantener actualizados los componentes importados mediante el comando de instalación, podemos ejecutar el comando web mvc loupe update.

8.6. Apendice de comandos

Para ver con mas detalle el comando que proporciona el add-on consultar la sección de comandos del add-on Lupa.

9. Add-on OCC (Optimistic Concurrency Control)

Add-on de utilidades enfocadas a la persistencia de las entidades.

Este add-on proporciona un sistema que facilita la detección de modificaciones concurrentes en la persistencia de entidades del modelo de datos.

El sistema consiste en un control de concurrencia optimista basada en un checkSum o suma de control de los valores de una entidad dada.

9.1. Introducción

Esta utilidad añade a las entidades un sistema de control de concurrencia basado en una operación de checksum o suma de control sobre todos los campos persistentes que contiene la entidad.

El control de concurrencia optimista ya es ofrecido por defecto por el núcleo de Spring Roo. Sin embargo, el sistema que proporciona se basa en la existencia de un campo en cada una de las tabla de base de datos que se desea controlar. Este campo se suele definir como version (numérico que identifica la versión del objeto) o lastupdate (fecha de la última actualización). Esto es un problema para aquellas bases de datos ya existentes y en las que no se puede o no se quiere alterar su estructura.

Esta funcionalidad nace de la necesidad de controlar la concurrencia sobre modelos de datos heredados en los que no es posible alterar el modelo relacional de base de datos para añadir los campos de control en los que se basa el mecanismo de control de concurrencia del núcleo de Spring Roo que sigue la especificación JPA.

El checksum consiste en una operación matemática de los distintos valores que contiene un registro (instancia) de una entidad. El cálculo tiene en cuenta todas las propiedad de tipo simple de la entidad, es decir, no se incluye en el cálculo propiedad que represente una relación con otro u otros objetos. El cálculo se realiza en el momento de la carga del registro de la entidad desde la base de datos y es almacenado en una propiedad no persistente de la misma entidad.

En el momento de actualizar o eliminar un registro de dicha entidad se carga el elemento que está persistido en la base de datos y se compara el valor de checksum actual con el que se calculó en el momento de la carga del elemento a actualizar o eliminar. Si no coincide se lanza una Excepción(javax.persistence.OptimisticLockException) y la operación no se realizará.

Esta operación supone un coste adicional en las tareas de persistencia, pero no es apreciable en condiciones del uso cuotidiano de la aplicación excepto en procesos de actualizaciones masivas de registros.

Para mostrar un mensaje amigable al usuario se puede utilizar el Add-on Web Dialog que, en el conjunto de excepciones gestionadas por defecto se incluye esta. Una vez inicializada la gestión de excepciones es posible personalizar el mensaje usando el comando web mvc dialog exception set language.

9.2. Añadir el control en las entidades

Para activar esta característica sobre una entidad se pueden utilizar los siguientes comandos:

'occ checksum set'

Aplica el control de concurrencia a una entidad.

'occ checksum all'

Aplica el control de concurrencia a todas las entidades de la aplicación.

Estos comandos añaden a uno o a todos los ficheros .java de las entidades una anotación @GvNIXEntityOCCChecksum y un campo no persistente para almacenar el checksum. En base a esta anotación se generará un aspecto java (fichero *_gvNIX_occChecksum.aj) con toda la lógica necesaria para calcular el checksum en base a las propiedades de un registro de la entidad y para controlar antes de una actualización o borrado si el registro ha cambiado desde que se cargo inicialmente. Toda esta lógica sera manejada automáticamente por el add-on.

Si se aplica el control de concurrencia sobre una entidad que extiende de otra y en la clase padre existe un campo anotado como campo de control de persistencia con @javax.persistence.Version, el add-on detectará esta circunstancia y aplicará el control de concurrencia sobre la clase padre.

Para ver todos los comandos y sus opciones ver el apéndice de comandos.

Se ha detectado que al aplicar este control de concurrencia sobre entidades que tienen generados, o sobre los que se van a generar, tests de integración (mediante el comando test integration o mediante la opción --testAutomatically del comando entity jpa) los tests de integración presentarán un error de compilación. Se debe a que el add-on que genera los tests de integración no considera el caso en el que el campo que hace de control de concurrencia sea del tipo cadena. Hay varias opciones para evitar estos errores de compilación:

  1. No es recomendable, pero se pueden desactivar los tests de los métodos flush() y merge() (métodos testFlush() y testMerge()). Para ello hay que editar los archivos src/test/java/**/*IntegrationTest.java y añadir a la anotación @RooIntegrationTest los atributos flush = false y merge = false, de esta manera estos dos tests no se generan en sus aspecto Java correspondiente quedando la batería de pruebas incompleta pero compilando correctamente:

    @RooIntegrationTest(entity = MiClase.class, )
  2. La más recomendable es corregir los dos test mencionados en el punto anterior. Para ello se debe realizar un pushin de estos dos métodos que se encuentran declarados en src/test/java/**/*IntegrationTest_Roo_IntegrationTest.aj y también el campo <nombre_entidad>DataOnDemand dod, anotado con @Autowired, llevandolos a la clase Java del test de integración. Una vez los test están en la clase Java, se pueden corregir los errores de compilación reemplazando el operador ">" por el método equals. A continuación se muestra un ejemplo extraido del proyecto de ejemplo petclinic que se distribuye junto a gvNIX/Roo en el que se han corregido las líneas marcadas en negrita para los métodos testFlush() y testMerge().

    package com.springsource.petclinic.domain;
    
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.roo.addon.test.RooIntegrationTest;
    
    @RooIntegrationTest(entity = Owner.class)
    public class OwnerIntegrationTest {
        @Autowired
        private OwnerDataOnDemand dod;
    
        @Test
        public void testMarkerMethod() {
    
        }
    
        @Test
        public void testFlush() {
            com.springsource.petclinic.domain.Owner obj = dod.getRandomOwner();
            org.junit.Assert.assertNotNull(
                    "Data on demand for 'Owner' failed to initialize correctly", obj);
            java.lang.Long id = obj.getId();
            org.junit.Assert.assertNotNull(
                    "Data on demand for 'Owner' failed to provide an identifier", id);
            obj = com.springsource.petclinic.domain.Owner.findOwner(id);
            org.junit.Assert.assertNotNull(
                    "Find method for 'Owner' illegally returned null for id '"
                    + id + "'", obj);
            boolean modified =  dod.modifyOwner(obj);
            java.lang.String currentVersion = obj.getOccChekcsum();
            obj.flush();
            org.junit.Assert.assertTrue(
                    "OccCheckSum for 'Owner' failed to modify on flush directive",
                    (currentVersion != null &&
                    ) ||
                    !modified);
        }
    
        @Test
        public void testMerge() {
            com.springsource.petclinic.domain.Owner obj = dod.getRandomOwner();
            org.junit.Assert.assertNotNull(
                    "Data on demand for 'Owner' failed to initialize correctly", obj);
            java.lang.Long id = obj.getId();
            org.junit.Assert.assertNotNull(
                    "Data on demand for 'Owner' failed to provide an identifier", id);
            obj = com.springsource.petclinic.domain.Owner.findOwner(id);
            boolean modified =  dod.modifyOwner(obj);
            java.lang.String currentVersion = obj.getOccChekcsum();
            com.springsource.petclinic.domain.Owner merged = (
                    com.springsource.petclinic.domain.Owner) obj.merge();
            obj.flush();
            org.junit.Assert.assertEquals(
                    "Identifier of merged object not the same as identifier of " +
                            "original object",
                    merged.getId(), id);
            org.junit.Assert.assertTrue(
                    "OccCheckSum for 'Owner' failed to modify on merge and flush " +
                            "directive",
                    (currentVersion != null &&
                    )
                    || !modified);
        }
    }

10. Add-on Web Dialog

Add-on para la gestión de excepciones no controladas y de mensajes de usuario.

10.1. Descripción

Este add-on permite gestionar las excepciones no controladas en el código de la aplicación y así mostrar mensajes inteligibles al usuario en una ventana modal (pop-up) y en el idioma actual de la aplicación sin necesidad de realizar ningún desarrollo en la capa web.

El add-on, al aplicarse sobre un proyecto, por defecto configura ciertas excepciones que serán visualizadas de forma amigable al usuario en el caso de no ser gestionadas directamente desde la aplicación. Así mismo, se pueden incluir nuevas excepciones y modificar los textos amigables que se mostrarán en lugar de la excepción para cada idioma disponible en la aplicación.

Durante su aplicación se instalan algunas cadenas, tanto en ingles como en castellano, para mostrar mensajes para los errores de conversión de datos numéricos y fechas.

El add-on también permite mostrar mensajes de usuario sin realizar ninguna implementación en la capa web mediante la invocación de métodos desde el controlador que son los encargados de mostrar dichos mensajes en la pantalla del usuario.

Los mensajes de excepción y de usuario se muestran en un diálogo o ventana modal. Se permite además la modificación de las ventanas modales de excepción y de mensaje de usuario para que puedan ser personalizadas de acuerdo a los requerimientos que sean necesarios.

10.2. Instalación

Para aplicar esta funcionalidad sobre un proyecto se debe ejecutar en primer lugar el comando web mvc dialog setup. Al hacerlo se incluye el soporte para diálogos modales en la aplicación.

El componente visual message-box.tagx que instala el add-on es el encargado de mostrar en pantalla un diálogo modal al usuario.

Al mismo tiempo, la ejecución de este comando configura una serie de excepciones que serán mapeadas con sus respectivos diálogos modales y mensajes amigables en múltiples idiomas. En las siguiente secciones se verá más detalladamente las excepciones controladas y el uso de los diálogos modales.

10.3. Excepciones controladas por gvNIX

Conjunto de excepciones inicialmente definidas y controladas por gvNIX al ejecutar el comando web mvc dialog setup.

  • java.sql.SQLException.

    Se ha producido un error en el acceso a la base de datos.

  • java.io.IOException.

    Existen problemas para enviar o recibir datos.

  • org.springframework.transaction.TransactionException.

    Se ha producido un error en la transacción. No se han guardado los datos correctamente.

  • java.lang.UnsupportedOperationException.

    Se ha producido un error no controlado.

  • javax.persistence.OptimisticLockException.

    No se puede actualizar el registro debido a que ha sido actualizado previamente.

Las excepciones se muestran mediante un dialogo modal. Para ello, se modifica la definición, en el archivo webmvc-config.xml, del bean SimpleMappingExceptionResolver reemplazando la clase que se define por una propia. La clase propia se encontrará instalada en el proyecto en la clase MessageMappingExceptionResolver.java del subpaquete web.servlet.handler. En el subpaquete web.dialog se instala también la clase Dialog.java, la cual es un bean que representa la información necesaria para visualizar una excepción en la ventana modal renderizada por el componente message-box.tagx.

10.3.1. Añadir nuevas excepciones a la gestión

Pasos a seguir para incluir en la gestión automática de excepciones de la aplicación una nueva excepción.

El Add-on proporciona ciertos comandos que permiten realizar de forma automática las siguientes operaciones para la gestión de excepciones:

  1. Añadir el control de una excepción a la aplicación:

    • Define la excepción a capturar en el bean messageMappingExceptionResolverBean del archivo webmvc-config.xml.

    • Asocia una dirección a la excepcion en un nuevo bean <mvc:view-controller> en el archivo webmvc-config.xml.

    • Crea la nueva jspx asociada a la excepción.

    • Instancia la jspx creada en el archivo views.xml en el directorio WEB-INF la aplicación.

    • Crear las etiquetas multi idioma en los ficheros de propiedades de todos los idiomas que estén instalados en la aplicación.

  2. Mostrar las excepciones gestionadas por la aplicación:

    • Muestra la lista de excepciones definidas en el bean messageMappingExceptionResolver del archivo webmvc-config.xml.

  3. Eliminar excepciones controladas por la aplicación:

    • Elimina del fichero webmvc-config.xml las referencias a la excepción y por lo tanto la quita de las excepciones gestionadas por la aplicación.

    • Elimina la página jspx asociada.

    • Elimina las referencias a la excepción en el archivo views.xml.

Para obtener más información sobre estos comandos de gestión de excepciones consultar el apendice Comandos del Add-on Web Dialog.

10.4. Nuevos diálogos modales

Estos diálogos son útiles para mostrar mensajes al usuario informando de cualquier circunstancía tras una operación determinada.

Para aplicar esta funcionalidad sobre el proyecto primero se debe haber ejecutado el comando web mvc dialog setup.

El comando web mvc dialog add añade la anotación 'GvNIXModalDialogs' en la clase controladora que se le indica.

roo>

La anotación generará dos métodos asociados con el controlador. Un método con el nombre modalDialog y otro que tomará como nombre el valor del parámetro name del comando y una página jspx en WEB-INF/dialogs con también el mismo nombre.

El método modalDialog permite al desarrollador mostrar diálogos modales genéricos en la parte visual directamente desde el código Java del controlador. Para ello, el desarrollador proporcionará un título, una descripción y un tipo de mensaje que será mostrado en la página al usuario. La signatura del método es:

modalDialog(DialogType dialogType, String title, String description,
            HttpServletRequest httpServletRequest)

El segundo método servirá para mostrar un mensaje específico. La diferencia principal es que este nuevo método tiene su propia página jspx asociada y además permite proporcionar parámetros adicionales a dicha página, cosa que no permite el método modalDialog.

petsdialog(DialogType dialogType, String title, String description,
            HashMap<String, Object> params, HttpServletRequest httpServletRequest)

Asociado a este método también se habrá creado en WEB-INF/dialogs una página jspx con el nombre petsdialog.jspx que podrá personalizarse según las necesidades. El Map params será proporcionado a la página y por lo tanto el desarrollador puede insertar valores desde el controlador para utilizarlos en el diálogo.

Los parámetros de cada uno de los dos métodos anteriores definen la siguiente información:

dialogType

es un tipo enumerado que puede tomar como valores: Error, Info, Alert, Suggest. Cada uno define un nivel de severidad en el diálogo y producirá en el aspecto visual del diálogo que aparezca con distinto color e icono.

title

es el código del recurso i18n que se usará como título del diálogo modal.

description

es el código del recurso i18n que se usará como descripción del diálogo modal.

params

es un Map que se puede utilizar para proporcionar tantos parámetros como sea necesario al componente visual del diálogo modal para confeccionarlo y mostrar en él cualquier información necesaria.

httpServletRequest

este parámetro se usa internamente en el método para obtener la sesión del usuario y establecer un atributo que será leido por el componente message-box.tagx para mostrar el diálogo. Si al invocar el método no se dispone de este parámetro, se puede obtener añadiendo el parámetro HttpServletRequest httpServletRequest a los parámetros del método que contiene la invocación (esta es una característica especial de los métodos que gestionan las URLs en Spring MVC y que permite declarar distintos parámetros de entre algunos dados).

10.4.1. Ejemplos de dialogos personalizados

Con este nuevo soporte para crear diálogos modales gvNIX ofrece una gran libertad para maquetar multitud de mensajes de usuario o diálogos de la aplicación (avisos, errores, mensajes de confirmación, formularios, etc.).

A continuación se muestra una pequeña demostración de implementación de algunos de estos mensajes personalizados.

Mensaje de aviso de aplicación

En ocasiones puede ser necesario que tras una acción (una petición al servidor) se muestre en la respuesta algún mensaje acerca del resultado de la operación solicitada o, en el caso de pantallas de búsqueda, indicar que no se han encontrado resultados.

Con el soporte de este add-on se puede incluir la siguiente línea de código en cualquier punto de un método de un controlador para definir un mensaje informativo.

modalDialog(DialogType.Info, "message_info_title", "message_description_key",
                httpServletRequest);
Mensaje de confirmación

Puede ser necesario que tras una acción, la aplicación deba preguntar si se desea ir a una página en concreto. A continuación se verán los pasos y cambios en el código de un controlador para definir este mensaje de confirmación.

En el ejemplo, se va a añadir a la aplicación de ejemplo petclinic un mensaje de confirmación que consultará al usuario si quiere ir al formulario de mascotas (Pets) tras actualizar la información de un propietario (Owner).

  1. Añadir un diálogo modal a la aplicación mediante "web mvc dialog message add"

    web mvc dialog add --class ~.web.OwnerController --name confirmgopets

    Esto generará un método confirmgopets disponible en OwnerController y una jspx base llamada confirmgopets en WEB-INF/dialogs que será personalizada.

  2. Modificar el método update de OwnerController para añadir la llamada al método confirmgopets justo antes de la línea de return. Para ello se debe llevar el método update desde OwnerController_Roo_Controller.aj hasta OwnerController.java, podemos usar la opción push-in que ofrece Eclipse. Una vez movido el método, será modificado quedando como sigue:

    @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
    public String update(@Valid Owner owner, BindingResult bindingResult, Model uiModel,
            HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors()) {
            populateEditForm(uiModel, owner);
            return "owners/update";
        }
        uiModel.asMap().clear();
        owner.merge();
    
    
    
        return "redirect:/owners/" + encodeUrlPathSegment(owner.getId().toString(),
                httpServletRequest);
    }

    Se ha resaltado en negrita la parte específica que ha de modificarse para mostrar el diálogo modal.

    El HashMap dialogParams permite proporcionar al componente message-box.tagx información adicional para mostrarla o utilizarla como sea necesario. En este caso, es necesario indicar a qué página dirigir al usuario en caso de que responda afirmativamente a la pregunta de confirmación, pero se podría definir cualquier tipo de parámetro, desde un String hasta objetos del Modelo de la aplicación o listas de objetos.

  3. Modificar la jspx que ha creado el add-on (confirmgopets.jspx) para adecuarla a las necesidades del proyecto:

    <div xmlns:c="http://java.sun.com/jsp/jstl/core"
                        xmlns:util="urn:jsptagdir:/WEB-INF/tags/util"
                        xmlns:fn="http://java.sun.com/jsp/jstl/functions"
                        xmlns:spring="http://www.springframework.org/tags"
                        xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
      <jsp:directive.page contentType="text/html;charset=UTF-8" />
      <jsp:output omit-xml-declaration="yes" />
      <spring:message var="title" code="${titleCode}" text="Message title"
            htmlEscape="false" />
      <util:panel id="title" title="${title}">
        <h2>${fn:escapeXml(title)}</h2>
        <p>
         <spring:message code="${descriptionCode}"
                text="This is the dialog description ..." htmlEscape="false"/>
        </p>
        <div class="closeMessage">
         <spring:message var="closeButtonValue" code="button_close"/>
         <button class="boton" dojoType="dijit.form.Button" type="button"
           onClick="dijit.byId('${dialogId}').hide();">${closeButtonValue}</button>
          <spring:url value="" var="locationUrl"/>
          <spring:message var="confirmButtonValue" code="confirmButtonValue"/>
          <button class="boton" dojoType="dijit.form.Button" type="button"
            onClick="location.href = '${locationUrl}';">${confirmButtonValue}</button>
        </div>
      </util:panel>
    </div>

    En este caso se ha resaltado el accesso al HashMap de parámetros del diálogo (dialogParams) para demostrar el modo en que se debe extraer los datos que le llegan al diálogo desde el controlador.

Diálogo modal con formulario

En alguna ocasión puede ser necesario mostrar un formulario en un diálogo modal para solicitar información al usuario, siguiendo el ejemplo anterior, se debería modificar la jspx que crea el add-on para incluir un formulario. En este ejemplo, tras crear un nuevo Owner en la aplicación, se mostrará un formulario para que cree su primera mascota.

  1. Añadir un diálogo modal a la apliacaión mediante "web mvc dialog message add"

    web mvc dialog add --class ~.web.OwnerController --name createPetInModal

    Esto genera un método createPetInModal disponible en OwnerController y una jspx base llamada createPetInModal en WEB-INF/dialogs que será personalizada.

  2. Modifica el método create de OwnerController. Al igual que en el ejemplo anterior debemos hacer el Push-in del método. Lo modificamos para que quede como se muestra:

    @RequestMapping(method = RequestMethod.POST, produces = "text/html")
    public String create(@Valid Owner owner, BindingResult bindingResult, Model uiModel,
            HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors()) {
            uiModel.addAttribute("owner", owner);
            addDateTimeFormatPatterns(uiModel);
            return "owners/create";
        }
        uiModel.asMap().clear();
        owner.persist();
    
    
    
        return "redirect:/owners/" + encodeUrlPathSegment(owner.getId().toString(),
                httpServletRequest);
    }
  3. Modificar la jspx incluyendo el formulario de creación de mascotas (Pets):

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <div xmlns:c="http://java.sun.com/jsp/jstl/core"
            xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields"
            xmlns:form="urn:jsptagdir:/WEB-INF/tags/form"
            xmlns:jsp="http://java.sun.com/JSP/Page"
            xmlns:spring="http://www.springframework.org/tags"
            version="2.0">
        <jsp:directive.page contentType="text/html;charset=UTF-8"/>
        <jsp:output omit-xml-declaration="yes"/>
    
    
        <form:create id="fc_com_springsource_petclinic_domain_Pet" modelAttribute="pet"
                path="/pets" render="${empty dependencies}" z="lgvEyAlAYOudDmaPjwU0ABseTIk=">
            <field:checkbox field="sendReminders"
                    id="c_com_springsource_petclinic_domain_Pet_sendReminders"
                    z="uPpMX+IWb0KONpvd11fpG8x4/4Q="/>
            <field:input field="name" id="c_com_springsource_petclinic_domain_Pet_name"
                    min="1" required="true" z="ZY+k75JeSo9RmejYZRFNIvs2aBg="/>
            <field:input field="weight" id="c_com_springsource_petclinic_domain_Pet_weight"
                    min="0" required="true" validationMessageCode="field_invalid_number"
                    z="cOD5zE/z7gy+RZu5kVSPuxCa+/I="/>
            <input type="hidden" id="c_com_springsource_petclinic_domain_Pet_owner"
                    name="owner" value="${owner.id}" />
            <field:select field="owner" id="c_com_springsource_petclinic_domain_Pet_owner"
                    itemValue="id" items="${owners}" path="/owners" render="false"
                    z="fGzswAP4XXvhPhowJKsRVve929c="/>
            <field:select field="type" id="c_com_springsource_petclinic_domain_Pet_type"
                    items="${pettypes}" path="pettypes" required="true"
                    z="+hDCnUp+Y+A1RlT+AjH07sgipOo="/>
        </form:create>
        <form:dependency dependencies="${dependencies}"
                id="d_com_springsource_petclinic_domain_Pet" render="${not empty dependencies}"
                z="kThDNIW+69h9nI/69ynY1WyUieo="/>
    </div>

10.5. Futuras versiones

Mejoras a incluir en futuras versiones del add-on.

  • Obtención de las excepciones y los mensajes multi idioma de las excepciones no controladas que deben visualizarse de forma amigable desde una base de datos en la que se encuentra almacenada dicha información. Así podría definirse un repositorio central de excepciones para múltiples aplicaciones y sus mensajes amigables.

  • Envío de un informe por email al responsable de la aplicación con información detallada cuando se ha producido una excepción.

11. Add-on Web Report

El add-on añade soporte para la generación de informes con Jasper Reports y genera informes totalmente funcionales para una entidad que posteriormente pueden ser personalizados. Los informes son accesibles desde la interfaz web mediante un formulario que se crea para tal efecto.

En la sección de recetas se puede encontrar información adicional para realizar el diseño de informes con sub informes.

11.1. Descripción

El add-on añade por un lado el soporte necesario para trabajar con Jasper Reports y por otro es capaz de generar informes asociados con una entidad cualquiera de la aplicación.

Un informe de Jasper Reports se se define principalmente mediante un archivo de diseño de informe (jrxml). El diseño de informe al procesarse junto con una fuente de datos, genera un fichero de salida en un formato determinado incluyendo en él la información existente en la fuente de datos. La fuente de datos puede provenir de distintos orígenes, aunque en este caso siempre será una lista de entidades proporcionada directamente desde la aplicación.

El archivo de diseño es un documento XML con un formato determinado que se puede editar de manera sencilla y gráfica mediante una herramienta como iReport.

Editor de informes iReport

11.2. Instalación

Jasper Reports requiere varias librerías y configuraciones para funcionar, el add-on incluye en el proyecto las dependencias de la librería modificando el pom.xml del mismo e incluye varios ficheros de configuración que se verán a continuación con mas detalle.

El comando sólo estará disponible si el proyecto utiliza Spring MVC en la capa web. Esto es, el archivo de configuración webmvc-config.xml debe existir en /WEB-INF/spring.

Estas operaciones de configuración las realiza el comando del add-on web report setup:

    roo>
    Updated SRC_MAIN_WEBAPP/WEB-INF/spring/webmvc-config.xml
    Created SRC_MAIN_WEBAPP/WEB-INF/spring/jasper-views.xml
    Created SRC_MAIN_WEBAPP/WEB-INF/classes/jasperfonts
    Created SRC_MAIN_WEBAPP/WEB-INF/classes/jasperfonts/FreeSans.ttf
    Created SRC_MAIN_WEBAPP/WEB-INF/classes/jasperfonts/FreeSansBold.ttf
    Created SRC_MAIN_WEBAPP/WEB-INF/classes/jasperfonts/FreeSansBoldOblique.ttf
    Created SRC_MAIN_WEBAPP/WEB-INF/classes/jasperfonts/FreeSansOblique.ttf
    Created SRC_MAIN_WEBAPP/WEB-INF/classes/jasperfonts/gvnix_reportfonts.xml
    Updated ROOT/pom.xml [added dependency org.gvnix:org.gvnix.web.report.roo.addon:X.Y.Z;
            added property 'jasperreports.version' = '4.0.1';
            added property 'jasperreportsfonts.version' = '4.0.0';
            added property 'apachepoi.version' = '3.7';
            added dependencies net.sf.jasperreports:jasperreports:${jasperreports.version},
            org.apache.poi:poi:${apachepoi.version},
            net.sf.jasperreports:jasperreports-fonts:${jasperreportsfonts.version}]
    Created SRC_MAIN_WEBAPP/WEB-INF/classes/jasperreports_extension.properties

El comando configura los siguientes archivos:

  • pom.xml: añade la dependencia JasperReports, la dependencia Apache POI para informes en formato Excel y una dependencia con el propio add-on para así reconocer la anotación @GvNIXReports que se utilizará en el proyecto.

  • webmvc-config.xml: añade un bean para configurar el sitema de vistas de informes.

  • jasper-views.xml: añade una definición de vistas por informe.

  • jasperfonts: directorio que contiene fuentes True Type que usará JasperReports para confeccionar el informe.

  • jasperreports_extension.properties: define el lugar donde se encuentran las fuentes a utilizar.

Cada uno de los informes se comporta como una vista más de la aplicación y por tanto el add-on habrá incluido en el fichero de configuración de la capa web webmvc-config.xml un componente que para cada petición de este tipo devolverá el nuevo tipo de salida (un informe). Esto se logra añadiendo un nuevo bean:

<bean id="jasperReportsXmlViewResolver"
            class="org.springframework.web.servlet.view.XmlViewResolver"
            p:location="/WEB-INF/spring/" p:order="0" />

Este bean referencia al fichero jasper-views.xml como fichero de configuración de las nuevas vistas, por tanto el add-on habrá creado este archivo en src/main/webapp/WEB-INF/spring.

Los informes generados pueden contener textos que se deban visualizar con características especiales tales como negrita y cursiva. Para ello, Jasper Reports requiere que las fuentes utilizadas para generar el informe se encuentren en el classpath de la aplicación. Así pues, el add-on se ocupa de copiar en src/main/webapp/WEB-INF/classes/jasperfonts varios archivos de fuentes True Type y su definición para poder hacer uso de ellas en el archivo gvnix_reportfonts.xml. En el archivo src/main/webapp/WEB-INF/classes/jasperreports_extension.properties se indica a Jasper Reports que utilice estas fuentes a la hora de generar el informe.

Si se desean utilizar fuentes de letra adicionales a parte de las incluidas por defecto por el add-on, deberán ser instaladas de forma manual en el proyecto. Para ello se puede consultar la sección Instalar fuentes de letra para los informes de la sección de recetas.

11.3. Generación de un informe

El add-on realiza la generación automática de informes sobre cualquier entidad de la applicación en la que se está utilizando. Posteriormente, los informes podrán ser personalizados por parte del desarrollador de la aplicación para adecuarlos a los requerimientos modificando o bien lo lógica de negocio o bien el estilo visual como se desee.

La petición de un informe, al tratarse de una vista más de la aplicación, ha de ser atendida por un controlador. No obstante, los informes muestran información referente a una entidad del modelo de datos de la aplicación, por tanto el controlador debe atender peticiones referentes a una determinada entidad. Esto, como se comentó en CRUDS automático, se configura mediante la anotación '@RooWebScaffold' y su atributo 'formBackingObject'. Así pues, no se puede definir un informe sobre un controlador que no disponga de la anotación '@RooWebScaffold'.

La generación de un informe se realiza mediante el comando web report add o incluyendo la anotación @GvNIXReports en la clase del controlador. Los formatos de fichero en los que se puede generar el informe son:

  • PDF

    Portable Document Format.

  • XLS

    Excel.

  • CSV

    Comma Separated Values.

  • HTML

    Hyper Text Markup Language.

roo>
    Updated SRC_MAIN_JAVA/org/gvnix/test/web/EntityController.java
    Created SRC_MAIN_WEBAPP/WEB-INF/reports
    Created SRC_MAIN_WEBAPP/WEB-INF/reports/entity_informe.jrxml
    Created SRC_MAIN_JAVA/org/gvnix/test/web/servlet/view/jasperreports
    Created SRC_MAIN_JAVA/org/gvnix/test/web/servlet/view/jasperreports/
            CustomJasperReportsMultiFormatView.java
    Updated SRC_MAIN_WEBAPP/WEB-INF/spring/jasper-views.xml
    Updated SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
    Created SRC_MAIN_WEBAPP/WEB-INF/views/pets/informe.jspx
    Updated SRC_MAIN_WEBAPP/WEB-INF/views/pets/views.xml
    Updated SRC_MAIN_WEBAPP/WEB-INF/i18n/application.properties
    Created SRC_MAIN_JAVA/org/gvnix/test/web/EntityController_Roo_GvNIXReport.aj
    Updated SRC_MAIN_WEBAPP/WEB-INF/views/menu.jspx

El comando incluirá la anotación @GvNIXReports en la clase controladora e incluira como atributo un array de cadenas en la que cada elemento define un informe y los formatos en los que se podrá generar dicho informe. Así pues, la anotación:

@GvNIXReports({ "informe|pdf,xls,csv" })

Define un informe cuyo nombre es informe y estará disponible en los formatos pdf, xls y csv.

Al lanzar el comando web report add o anotar la clase del controlador con @GvNIXReports se realizan una serie de modificaciones en el proyecto que darán como resultado la posibilidad de generar un informe desde un formulario de la aplicación. Las modificaciones que realiza el comando sobre el proyecto son:

  • Crea la clase Java CustomJasperReportsMultiFormatView. La nueva clase se creará en el subpaquete servlet.view.jasperreports dentro del paquete donde se encuentre el controlador. Esta clase se instala solo una vez y en sucesivas ejecuciones se comprueba si existe. Esta clase tiene como principal cometido establecer, de manera dinámica, el nombre del archivo del informe que se genera para su descarga.

  • En el archivo jasper-views.xml añade la definición de una nueva vista que será el nuevo informe añadido a la aplicación. Se define para ello un bean cuyo id es <fromBackingObject><reportname> y CustomJasperReportsMultiFormatView como clase del bean. Si formBackingObject de @RooWebScaffold tiene como valor Entity y el nombre definido para el informe es informe:

    <bean id="entity_informe"
    class="org.gvnix.test.web.servlet.view.jasperreports.CustomJasperReportsMultiFormatView"
    p:url="/WEB-INF/reports/entity_informe.jrxml"
    p:subReportUrls-ref="subReportUrls"
    p:subReportDataKeys-ref="subReportDataKeys" />
  • Crea un archivo de diseño de informe (jrxml) con carios campos de la clase Entity (siguiendo el ejemplo anterior). El archivo se creará en src/main/webapp/WEB-INF/reports con el nombre entity_informe.jrxml. Este archivo se referenciará en el bean del fichero jasper-views.xml desde el atributo p:url.

  • Crea un formulario web bajo src/main/webapp/WEB-INF/views/<entity> con nombre informe.jspx siguiendo con el ejemplo anterior. Y define esta nueva vista en el fichero views.xml situado en el mismo directorio. Esta página permitirá solicitar la generación del informe y por defecto lo hará incluyendo los 10 primeros registros de la entidad.

  • Incluye las etiquetas multidioma que necesita visualizar la generación de informes en src/main/webapp/WEB-INF/i18n/application.properties y un nuevo enlace del menú en src/main/webapp/WEB-INF/views/menu.jspx para poder acceder a la página de generación del informe.

  • Crea el aspecto Java <controller>_Roo_GvNIXReport.aj con los métodos que atenderán las peticiones relacionadas con el informe añadido. Se añaden dos métodos por informe:

    • generate<Reportname>Form(..): devuelve la vista del formulario web que permite al usuario seleccionar el formato de salida del informe y solicitar su generación mediante un botón.

    • generate<Reportname>(..): atiende la petición de generación del informe recopilando los datos necesarios que se deben incluir en él. Para ello, por defecto invoca el método <formBackingObject>.find<formBackingObject>Entries(0, 10) por lo que se tomarán los 10 primeros registros de la entidad para rellenar el informe.

      @RequestMapping(value = "/reports/informe", params = "form",
              method = RequestMethod.GET)
      public String EntityController.generateInformeForm(Model uiModel) {
          String[] reportFormats =  {"pdf"};
          Collection<String> reportFormatsList = Arrays.asList(reportFormats);
          uiModel.addAttribute("report_formats", reportFormatsList);
          return "users/informe";
      }
      
      @RequestMapping(value = "/reports/informe", method = RequestMethod.GET)
      public String EntityController.generateInforme(
              @RequestParam(value = "format", required = true) String format, Model uiModel) {
          if ( null == format || format.length() <= 0 ) {
                  uiModel.addAttribute("error", "message_format_required");
                  return "users/informe";
          }
          final String REGEX = "(pdf)";
          Pattern pattern = Pattern.compile(REGEX, Pattern.CASE_INSENSITIVE);
          Matcher matcher = pattern.matcher(format);
          if ( !matcher.matches() ) {
                  uiModel.addAttribute("error", "message_format_invalid");
                  return "users/informe";
          }
          Collection<Entity> dataSource = Entity.findEntityEntries(0, 10);
          if (dataSource.isEmpty()) {
                  uiModel.addAttribute("error", "message_emptyresults_noreportgeneration");
                  return "users/informe";
          }
          uiModel.addAttribute("format", format);
          uiModel.addAttribute("title", "INFORME");
          uiModel.addAttribute("informeList", dataSource);
          return "entity_informe";
      }

El comando web report add puede ejecutarse tantas veces como se desee sobre el mismo controlador. Si el nombre del informe a añadir ya existe previamente, se añadirán los formatos especificados a los ya definidos. Si el nombre dado al nuevo informe definido no existía, se añadirá su definición en la anotación @GvNIXReports.

@GvNIXReports({ "informe|pdf,xls,csv", "otroinforme|pdf" })

Los valores de la anotación @GvNIXReports no son sensibles a mayúsculas por tanto si manualmente se establecen los valores de la anotación como:

@GvNIXReports({ "informe|pdf", "INFORME|xls,csv" })

es equivalente a:

@GvNIXReports({ "informe|pdf,xls,csv" })

11.4. Futuras versiones

  • Incrementar la funcionalidad del informe generado, incluyendo la visualización de las relaciones que pueda tener la entidad sobre la que se declara el informe. En la sección de recetas se muestra una forma de mostrar las relaciones de una entidad en el informe mediante el uso de subinformes.

12. Add-on Service

Permite crear servicios locales, servidores de servicios web y clientes de servicios web de forma automática.

12.1. Descripción

Permite crear de forma automática servicios locales, servidores de servicios web a partir de un método del código fuente, crear servidores de servicios web basándose en un archivo de descripción de servicios WSDL y crear clientes de servicios web a partir de un archivo de descripción de servicios WSDL.

La creación de servicios, del mismo modo que todas las funcionalidades que proporciona el framework, se realiza mediante anotaciones. Para simplificar esta tarea se puede hacer uso de los comandos que ofrece. A medida que se van ejecutando comandos del add-on, se van modificando anotaciones y métodos de la clase Java de forma que acabará conformando el servicio web que se desea publicar.

12.2. Creación de servicios locales

Un servicio local es una clase Java con una serie de métodos que se desea que estén disponibles de forma interna para toda la aplicación. La clase se puede crear con el comando remote service class.

roo>
Created SRC_MAIN_JAVA/org/gvnix/test/service/Service.java

La ejecución del comando creará una clase en la ruta especificada con la anotación @Service que le proporciona unas características especiales y facilita su uso como servicio local dentro de la aplicación.

...
@Service
public class Service {
}

De esta forma, el servicio puede ser utilizar desde cualquier otra clase Java definiendo una propiedad del tipo de la clase de servicio con la anotación @Autowired.

@Autowired
Service service;

Una vez creada la clase se pueden crear los métodos que se desea ofrecer en el servicio. Los métodos se pueden crear mediante el comando remote service operation que permite añadir métodos en una clase.

roo>  --name myMethod --service ~.service.Service
        --return java.lang.Long --paramNames param1,param2
        --paramTypes "java.lang.String,java.util.List"
Updated SRC_MAIN_JAVA/org/gvnix/test/service/Service.java

El comando anterior creará el método con las características solicitadas en la clase que se le indica como parámetro.

public Long myMethod(String param1, List param2) {
  return null;
}

Como se puede observar, la implementación del método está vacía y como es obvio deberá ser definida por el desarrollador.

12.3. Creación de servidores desde Java

Permite que los métodos de una clase Java puedan ser accedidos desde el exterior mediante operaciones de un servicio web.

En primer lugar se debe elegir una clase Java que contendrá los métodos que se desea ofrecer al exterior mediante el servicio web. La clase puede ser cualquiera existente previamente o se puede crear una nueva mediante el comando remote service class.

A continuación, se debe elegir los métodos a ofrecer a través del servicio web. Si todavía no existen, se pueden crear mediante el comando remote service operation.

De momento la clase no es accesible mediante un servicio web. Para ello se debe ejecutar el comando remote service define ws.

roo>
Updated ROOT/pom.xml [
        added repository http://repository.gvnix.org;
        added dependency org.gvnix:org.gvnix.service.roo.addon:X.Y.Z;
        added plugin org.apache.cxf:cxf-java2ws-plugin:${cxf.version}]
Created SRC_MAIN_WEBAPP/WEB-INF/cxf-appname.xml
Updated SRC_MAIN_WEBAPP/WEB-INF/web.xml
Creating a new class 'Service' to export web service.
Created SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Updated SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Updated ROOT/pom.xml [
        added dependency org.apache.cxf:cxf-rt-core:${cxf.version};
        added dependency org.apache.cxf:cxf-rt-bindings-soap:${cxf.version};
        added dependency org.apache.cxf:cxf-rt-databinding-jaxb:${cxf.version};
        added dependency org.apache.cxf:cxf-rt-frontend-jaxws:${cxf.version};
        added dependency org.apache.cxf:cxf-rt-transports-http:${cxf.version};
        added dependency javax.xml.bind:jaxb-api:2.1;
        added dependency javax.xml.ws:jaxws-api:2.1;
        added property 'cxf.version' = '2.4.2']
Updated SRC_MAIN_WEBAPP/WEB-INF/cxf-petclinic.xml
Updated ROOT/pom.xml
Created SRC_MAIN_JAVA/org/gvnix/test/service/Service_Roo_GvNix_WebService.aj
* New service defined without operations, use 'service export operation' command to add it
* New service can be shown adding '/services/' suffix to your base application URL

El comando incluirá la anotación @GvNIXWebService en la clase Java indicada. También generará los componentes necesarios para exponer la clase como un servicio web a partir de los atributos de la anotación.

...
@GvNIXWebService(name = "ServicePortType",
        targetNamespace = "http://service.test.gvnix.org/",
        serviceName = "Service", address = "Service",
        fullyQualifiedTypeName = "org.gvnix.test.service.Service", exported = false)
public class Service {
}

La clase Java será enlazada en la definición del servicio con un PortType lo que permitirá la comunicación con la clase desde el exterior mediante los protocolos y tecnologías de servicios web.

privileged aspect Service_Roo_GvNix_WebService {
declare @type: Service: @WebService(name = "ServicePortType",
        targetNamespace = "http://service.test.gvnix.org/",
        serviceName = "Service", portName = "ServicePortType");
declare @type: Service: @SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL,
        parameterStyle = ParameterStyle.WRAPPED);
}

En este momento el servicio web ya está publicado y es accesible, sin embargo no dispondrá de ninguna operación ya que por defecto todos los métodos de la clase publicada son configurados inicialmente como no accesibles por motivos de seguridad. Se podrá hacer accesible cada uno de los métodos de la clase por separado mediante el comando remote service export operation

roo>
Updated SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Updated SRC_MAIN_WEBAPP/WEB-INF/cxf-appname.xml
Updated ROOT/pom.xml
Deleted SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Created SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Created SRC_MAIN_JAVA/org/gvnix/test/service/Service_Roo_GvNix_WebService.aj
Updated SRC_MAIN_JAVA/org/gvnix/test/service/Service_Roo_GvNix_WebService.aj

El comando anterior añade la anotación @GvNIXWebMethod al método, de forma que que se generará el código necesario para que la operación esté disponible en el servicio web.

@GvNIXWebMethod(operationName = "method", requestWrapperName = "method",
            requestWrapperNamespace = "http://service.test.gvnix.org/",
            requestWrapperClassName = "org.gvnix.test.service.MethodRequestWrapper",
            resultName = "return", resultNamespace = "http://service.test.gvnix.org/",
            webResultType = Long.class, responseWrapperName = "methodResponse",
            responseWrapperNamespace = "http://service.test.gvnix.org/",
            responseWrapperClassName = "org.gvnix.test.service.MethodResponse")
public Long method(@GvNIXWebParam(name = "param1", type = String.class)
        @WebParam(name = "param1", partName = "parameters", mode = Mode.IN, header = false)
        String param1,
        @GvNIXWebParam(name = "param2", type = List.class)
        @WebParam(name = "param2", partName = "parameters", mode = Mode.IN, header = false)
        List param2) {
    return null;
}

Como es obvio, el método no dispone de ningún código en su cuerpo y será responsabilidad del desarrollador el implementar la lógica de negocio que sea necesaria.

12.4. Creación de servidores desde WSDL

Existe otro modo para crear servidores de servicios web. Consiste en ofrecer al exterior un servicio web partiendo de un archivo de contrato de servicio conocido como WSDL. Con el comando remote service export ws se proporciona la ruta a un archivo 'WSDL' y se generará una réplica del servicio en la que las operaciones son métodos vacios que posteriormente deberán ser personalizadas con la lógica de negocio adecuada.

roo>

La ruta al WSDL puede ser un archivo local mediante file://ruta, una dirección web mediante http://ruta o una dirección web segura mediante https://ruta.

Este modo es especialmente cómodo para realizar la migración de servicios que están implementados en otras aplicaciones o tecnologías o que se desean integrar en otra aplicación.

12.5. Creación de clientes

Es posible generar un cliente que permita realizar peticiones a un servicio web remoto existente utilizando para ello el comando remote service import ws. Facilitando la ruta a un 'WSDL', se generará una clase en la ruta que se especifique y que contendrá los métodos del cliente que darán acceso al servicio web remoto.

remote service import ws --class org.gvnix.test.service.Service
            --wsdl ruta
Created SRC_MAIN_JAVA/org/gvnix/test/service/
Created SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Updated SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Updated ROOT/pom.xml [
        added dependency org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final;
        removed dependency org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final;
        added plugin org.apache.cxf:cxf-codegen-plugin:${cxf.version}]
Updated ROOT/pom.xml

El comando dará lugar a la creación, si no existía, de la clase Java y a la inclusión de la anotación @GvNIXWebServiceProxy que define el servicio web al que da acceso la clase.

...
@Service
@GvNIXWebServiceProxy(wsdlLocation = "ruta")
public class Service {
}

La anotación desencadenará la creación en el aspecto Java correspondiente de tantos métodos como operaciones ofrece el servicio web y que enmascaran la comunicación con el sistema remoto.

privileged aspect Service_Roo_GvNix_WebServiceProxy {

    public String Service.method(String param1) {
            org.web.service.RemoteService s = new org.web.service.RemoteService();
        org.web.service.RemoteServiceSoap p = s.getRemoteServiceSoap12();
        return p.method(param1);
    }

}

Esta clase se podrá utilizar como si de un servicio local se tratase. Para usar esta clase simplemente habrá que crear una propiedad en la clase donde se desea hacer uso de ella y añadirle la anotación @Autowired.

public class MyClass {
  ...
  @Autowired
  private Service service;
  ...
  public void myMethod() {
    ...
    service.method(..);
    ...
  }
}

La ruta al WSDL puede ser un archivo local mediante file://ruta, una dirección web mediante http://ruta o una dirección web segura mediante https://ruta.

12.6. Acceso a un WSDL en un servidor seguro

Cuando el WSDL se encuentra en un archivo local o en un servidor no seguro como HTTP, se puede acceder directamente sin ningún problema.

En el caso que un WSDL se encuentra en un servidor seguro al que se accede mediante HTTPS pueden darse dos posibles escenarios:

  1. El certificado del servidor ha sido creado por una Autoridad de certificación (CA) confiable por la JVM.

    En este caso, el procesado del WSDL funciona de la misma manera que en el caso de acceso por HTTP, transparente para el usuario.

  2. El certificado de servidor ha sido creado por un CA no confiable (caso de certificados autofirmados).

    Aquí, es responsabilidad del usuario el aceptar las credenciales del servidor para poder acceder al WSDL. Recordando como trabajan los navegadores web, cuando se intenta acceder a un recurso seguro, si el certificado del servidor no ha sido creado por un CA que se encuentre entre la lista de CAs conocida (Verisign, Thwate, Equfax, …​), el navegador muestra un mensaje de advertencia y pregunta si se desea confiar en la identidad del servidor. Cada usuario decide aceptar o no el certificado.

    Para simplificar el proceso de importación de servicios web, se intenta hacer esta tarea de manera transparente para el usuario.

    Para ello, se manipula el almacén de certificados de la máquina virtual Java siempre que sea posible. Esto es:

    1. Existe el archivo de keystore en el directorio donde está instalado Java, por ejemplo en sistemas linux $JAVA_HOME/jre/lib/security/cacerts y es modificable por el usuario del sistema que está ejecutando gvNIX.

    2. La contraseña del keystore es changeit (la contraseña por defecto del keystore).

      Si se puede modificar el keystore, se importarán los certificados implicados en la autenticación del servidor y entonces se podrá acceder al WSDL requerido para generar el cliente del WS.

      Al mismo tiempo, se crea en src/main/resources una copia del almacén de certificados en el archivo gvnix-cacerts y una copia local de los certificados importados con el nombre <servidor>-<indice_certificado>.cer. De esta forma, los certificados pueden ser distribuidos con el resto de archivos del proyecto para que puedan ser instalados en otros entornos.

      Si no puede modificar el keystore de la JVM, porque no se cumplen alguna de las 2 condiciones enumeradas anteriormente, de todas formas realizará la copia de los certificados necesarios para que sea el usuario quien instale los mismos en el almacén de certificados de su JVM. Para ello se puede hacer uso de la herramienta keytool (distribuida también con el JDK). La operación de importar los certificados equivale a la aceptación que se hace con el navegador.

12.6.1. Creación de clientes con firma

El add-on permite añadir una firma digital a las peticiones realizadas a un servicio web externo que se encuentra importado en la aplicación.

Actualmente esta opción sólo está disponible para los servicio web que utilicen la librería Axis (RPC/Encoded). En futuras versiones se añadirá esta misma opción para servicios que utilicen la librería CXF (Document/Literal) y otra operaciones relacionadas con la seguridad en servicios web.

Para ello se debe disponer de:

  1. Servicio web importado en la aplicación.

  2. Fichero pkc12 con el certificado a usar para firmar la petición.

  3. Contraseña del certificado.

  4. Alias a usar con el certificado

Disponiendo de esto elementos, se puede hacer uso del comando remote service security ws para añadir la firma en las peticiones del cliente.

roo>
Created ROOT/src/main/resources/org/gvnix/test/service
Created ROOT/src/main/resources/org/gvnix/test/service/certificate.p12
Updated SRC_MAIN_JAVA/org/gvnix/test/service/Service.java
Created ROOT/src/main/resources/client-config.wsdd
Created ROOT/src/main/resources/org/gvnix/test/service/ServiceSecurity.properties
Updated ROOT/pom.xml [added dependency org.apache.ws.security:wss4j:1.5.11]
Updated ROOT/src/main/resources/client-config.wsdd
Created SRC_MAIN_JAVA/org/gvnix/test/service/Service_Roo_GvNIX_WebSecurity.aj

Se crearán dos ficheros con distintos parámetros de configuración en src/main/resources/org/gvnix/test/service/ServiceSecurity.properties y src/main/resources/client-config.wsdd. El primero contiene los parámetros introducidos para la configuración de la seguridad y el segundo la configuración para axis.

También dará lugar a la inclusión de la anotación @GvNIXWebServiceSecurity.

...
@GvNIXWebServiceSecurity
public class Service {
}

La anotación anterior dará lugar a la generación del aspecto Java correspondiente que establece la clave de acceso al certificado que se encuentra en el fichero ServiceSecurity.properties.

privileged aspect Service_Roo_GvNIX_WebSecurity {

    declare parents: Service implements CallbackHandler;

    public Service.new() {
        super();
    }

    public void Service.handle(Callback[] callbacks)
            throws IOException, UnsupportedCallbackException {
        final String propPath = "org/gvnix/test/service/ServiceSecurity.properties";
        final String propKey = "org.apache.ws.security.crypto.merlin.keystore.password";
        try {
// Get class loader to get file from project
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            java.io.File file = new java.io.File(classLoader.getResource(propPath).toURI());
            if (file != null && file.exists()) {
// Load properties
                java.util.Properties properties = new java.util.Properties();
                java.io.FileInputStream ins = null;
                try {
                    ins = new java.io.FileInputStream(file);
                    properties.load(ins);
                } finally {
                    if (ins != null) {
                        ins.close();
                    }
                }
                String value = properties.getProperty(propKey);
                if (value != null) {
                    ((org.apache.ws.security.WSPasswordCallback) callbacks[0]).setPassword(value);
                } else {
                    throw new IOException("Property ".concat(propKey).concat(" not exists"));
                }
            } else {
                throw new IOException("File ".concat(propPath).concat(" not exists"));
            }
        } catch (java.net.URISyntaxException e) {
            throw new IOException("Problem getting ".concat(propPath).concat(" file"),e);
        }
    }
}

Para realizar cambios en los parámetros de firma del servicio es posible ejecutar de nuevo el comando remote service security ws con los nuevos datos sobre la misma clase (opción recomendada) o modificar los ficheros antes mencionados a mano.

12.7. Listar los servicios

El comando remote service list operation muestra los métodos existentes en una clase que están disponibles para ser ofrecidos al exterior siempre y cuando la clase esté definida como un servicio web.

roo>
Method list to export as web service operation in '~.service.Service':
    * myMethod2

El comando remote service ws list permite obtener un listado de los servicios ofrecidos al exterior o aquellos servicios externos que son utilizados en la aplicación.

El resultado es una salida como esta:

roo> remote service ws list
Services                         exported    imported
-------------------------------  ---------   ----------
org.gvnix.test.service.Service1      X
org.gvnix.test.service.Service2                 X
org.gvnix.test.service.Service3                 X

13. Add-on Web MVC i18n

Permite añadir soporte para nuevos idiomas en el proyecto.

13.1. Descripción

Este add-on permite añadir en el proyecto soporte para nuevas lenguas utilizando para ello una infraestructura común para la inclusión de nuevos idiomas. Al incluir un nuevo idioma, se añaden en la aplicación de forma automática los textos traducidos a dicho idioma.

Los idiomas soportados son: de (Alemán), en (Inglés), es (Español), it (Italiano), nl (Holandés), sv (Finlandés), ca (Valenciano/Catalán). Este último es añadido por gvNIX utilizando la base del add-on de idiomas de su núcleo Spring Roo.

13.2. Instalación de un idioma

Para instalar uno de los idiomas soportados hay que ejecutar el comando web mvc install language y proporcionar como parámetro code el código del idioma deseado.

roo>
    Created SRC_MAIN_WEBAPP/WEB-INF/i18n/messages_ca.properties
    Created SRC_MAIN_WEBAPP/images/ca.png
    Updated SRC_MAIN_WEBAPP/WEB-INF/views/footer.jspx

Este comando instala un fichero de propiedades en el proyecto con la traducción de las etiquetas necesarias para el idioma que se requiera. Por ejemplo, para el idioma valenciano/catalán se creará el fichero src/main/webapp/WEB-INF/i18n/messages_ca.properties.

#menu
    global_menu_new=Crear nou {0}
    global_menu_list=Llistar {0}
    global_menu_find=Cercar per {0}
    ...

También realiza las modificaciones necesarias para poder solicitar el cambio de idioma desde la interfaz visual, lo que implica la inclusión de una imagen con la bandera del idioma solicitado y la modificación del pie de página para mostrar el cambio a dicho idioma. Esto se realiza en el fichero src/main/webapp/WEB-INF/views/footer.jspx mediante el tag <util:language> que será el encargado de incluir la imagen y generar el enlace para el cambio de idioma.

<util:language label="Valencian_Catalan" locale="ca"/>

Para mas información sobre este comando ver el apéndice de comandos del add-on.

13.3. Futuras versiones

Mejoras a incluir en futuras versiones del add-on.

  • Incluir el soporte para el resto de lenguas cooficiales del estado español, es decir, Gallego y Euskera. Se deja abierta la posibilidad de añadir idiomas de otros estados que pudiesen ser de utilidad.

14. Add-on Dynamic Configuration

14.1. Descripción

Este add-on pretende simplificar la gestión de distintos valores de configuración por entorno. Cuando se utiliza Maven como gestor del ciclo de desarrollo del proyecto existe la posibilidad de utilizar perfiles para definir los distintos entornos de ejecución que tendrá la aplicación (desarrollo, pruebas, integración, preproducción, producción, …​).

A continuación se muestra un ejemplo de parte de la configuración necesaria para la definición de perfiles en el fichero pom.xml.

   <profiles>
     <profile>
       <id>nombre-entorno</id>
       <properties>
         <nombre.propiedad>valor</nombre.propiedad>
         ...
       </properties>
     </profile>
   </profiles>

Esta funcionalidad permite configurar el comportamiento de la aplicación de manera distinta según donde vaya a ser ejecutada. Por ejemplo, la configuracíón de la conexión con la base de datos de la aplicación posiblemente será una URL distinta según se esté trabajando en un entorno de desarrollo o un entorno de producción.

Para esto, en la sección <properties> de cada sección <profile> se pueden declarar tantas propiedades como se desee de forma que al empaquetar la aplicación (habitualmente en formato WAR), se reemplace el valor de estas propiedades en los ficheros adecuados. Esto implica que en distintos archivos del proyecto, como puede ser persistence.xml, empiecen a aparecer definidas variables con el formato $\{nombre.propiedad}. Esta circunstancia, a la larga, puede complicar la comprensión de la configuración del proyecto o dificultar su gestión. Por ejemplo, podría aparecer la siguiente modificación en el fichero src/main/resources/META-INF/persistence.xml:

<property name="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl.auto}"/>

Esta circunstancia, a la larga, puede complicar la comprensión de la configuración del proyecto o dificultar su gestión.

14.2. Funcionalidad

Vista la problemática descrita en el punto anterior, el add-on dynamic configuration pretende simplificar esta gestión. Permite definir distintas configuraciones de manera rápida y simple. Además, es independiente del sistema de gestión del ciclo de vida del proyecto, ya que aunque actualmente las configuraciones solo se pueden exportar a perfiles Maven, el add-on es lo suficientemente general como para poder exportar a formatos Ant, etc.

A medida que se van ejecutando comandos del add-on se irá modificando el archivo src/main/resources/dynamic-configuration.xml que almacena la información sobre las distintas configuraciones definidas hasta el momento.

La creación de una nueva configuración se realiza con el comando configuration create que tiene un único parámetro obligatorio ('name') que define el nombre para la nueva configuración.

roo>
...
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Configuration created with currently available properties
First created configuration set as default
(use 'configuration property add' to make a property available for all configurations)
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Configuration created with currently available properties
(use 'configuration property add' to make a property available for all configurations)

Resaltar que la creación de las configuraciones no es obligatorio realizarlas al inicio y podrán realizarse en cualquier momento.

A partir de este momento es posible añadir nuevas propiedades para que estén disponibles para su gestión desde todas las configuraciones con configuration property add. Las propiedades inicialmente tomarán el valor que tengan definido en el proyecto.

roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property available for all configurations
(use 'configuration property value' to set property new values)
(use 'configuration property undefined' to set property with no values)
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property available for all configurations
(use 'configuration property value' to set property new values)
(use 'configuration property undefined' to set property with no values)
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property available for all configurations
(use 'configuration property value' to set property new values)
(use 'configuration property undefined' to set property with no values)
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property available for all configurations
(use 'configuration property value' to set property new values)
(use 'configuration property undefined' to set property with no values)

A continuación, se podrán modificar los valores de cada propiedad con configuration property value.

roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property value seted
(use 'configuration list' to show configurations and their properties)
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property value seted
(use 'configuration list' to show configurations and their properties)
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property value seted
(use 'configuration list' to show configurations and their properties)
roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property value seted
(use 'configuration list' to show configurations and their properties)

En algunos casos, por seguridad, puede ser necesario que el valor de una propiedad no esté almacenado en el proyecto, para ello puede utilizarse el comando configuration property undefined de forma que el valor se tendrá que proporcionar al empaquetar la aplicación con Maven como un parámetro mediante el modificador '-D nombre=valor'.

roo>
Updated SRC_MAIN_RESOURCES/dynamic-configuration.xml
Property value undefined
(use '-D propname=propvalue' on maven commands to set the property value)
(use 'configuration list' to show configurations and their properties)

Si se desea ver las distintas configuraciones que creadas, sus propiedades y los valores definidos para cada una de ellas utilizar el comando configuration list.

roo>
      (Active)      dev
----------------------------------------
 * Database Connection Properties
   - database.url = "jdbc:hsqldb:mem:mydevdb"
   - database.password = ""
 * Persistence Property Attributes XML
   - hibernate.hbm2ddl.auto = "create"
 * Logging Service Properties
   - log4j.rootLogger = "INFO, stdout"
                    pro
----------------------------------------
 * Database Connection Properties
   - database.url = "jdbc:hsqldb:file:myprodb"
   - database.password = (UNDEFINED)
 * Persistence Property Attributes XML
   - hibernate.hbm2ddl.auto = "update"
 * Logging Service Properties
   - log4j.rootLogger = "ERROR, stdout"
(use 'configuration export' to write configurations into the project)

Para escribir las configuraciones actuales en el proyecto se debe utilizar el comando configuration export. Es muy importante destacar que hasta que no se haya ejecutado este comando, las configuraciones no serán escritas en los ficheros destino y por lo tanto hasta ese momento no se podrán utilizar las configuraciones.

roo>
Updated ROOT/pom.xml
Updated ROOT/pom.xml
Updated SRC_MAIN_RESOURCES/META-INF/spring/database.properties
Updated SRC_MAIN_RESOURCES/log4j.properties
Updated SRC_MAIN_RESOURCES/META-INF/persistence.xml
Updated SRC_MAIN_RESOURCES/META-INF/spring/database.properties
Updated SRC_MAIN_RESOURCES/log4j.properties
Updated SRC_MAIN_RESOURCES/META-INF/persistence.xml
Configurations exported into project
(use '-P name' on maven commands to use a configuration)
(use 'configuration create' to define a new configuration)

Una vez exportadas las configuraciones, pueden utilizarse como perfiles desde Maven mediante el modificador -P nombre utilizando como nombre el valor que se definió para la configuración con el comando configuration create. Por ejemplo, al empaquetar la aplicación para desplegarla en uno u otro entorno, debe especificarse el nombre de la configuración y opcionalmente el valor de los parámetros que se crearon como indefinidos en la configuración.

shell>
... (Empaquetando la aplicación con la configuración llamada dev) ...
shell>
... (Empaquetando la aplicación con la configuración llamada pro) ...
... (Se utilizará como clave de acceso a la base de datos "mypassword") ...

También es posible elegir la configuración (perfil) a utilizar desde Eclipse/STS desde las propiedades del proyecto accediendo a la opción Maven del menú.

Selección del perfil Maven desde Eclipse

14.3. Mejoras de rendimiento

Se pueden definir algunos valores óptimos de rendimiento definidos en la sección Patrones de conversión óptimos en el log.

14.4. Futuras versiones

  • Incluir nuevas propiedades a la lista de propiedades disponibles para las configuraciones. O por contra, permitir cierta libertad para añadir cualquier propiedad del proyecto como configurable.

  • Posibilidad de incluir otro tipo de elementos en las configuraciones como, por ejemplo, distintas dependencias.

  • Definir plantillas de configuración de modo que establezcan unos valores estándar que se consideren adecuados para una determinada configuración. Por ejemplo, establecer el formato de los logs en producción para reducir el consumo de recursos.

15. Add-on Web MVC Binding

15.1. Descripción

El add-on permite registrar ciertos editores de propiedades en Spring MVC para uno o todos los controladores del proyecto.

Los editores son una pieza más de la arquitectura de Spring MVC. Se encargan de controlar el modo en que las cadenas enviadas por el navegador cliente, por ejemplo desde un formulario, se convierten en objetos al llegar al servidor.

Para obtener más información sobre los editores de propiedades ver la sección de conversión de beans de la documentación de Spring.

El comando web mvc binding stringTrimmer permite registrar un editor especialmente útil. Este editor elimina los espacios en blanco al principio y al final de las cadenas y además permite transformar las cadenas vacías en valores nulos.

Este editor es especialmente interesante al realizar mantenimientos de valores almacenados en bases de datos. Por defecto, cuando se deja vacío un valor de un formulario y está relacionado con una columna de base de datos del tipo cadena, al almacenar se escribe una cadena vacía. En estos casos puede suele ser más interesante almacenar un valor nulo.

roo>
Updated SRC_MAIN_JAVA/org/gvnix/test/web/EntityController.java
Updated ROOT/pom.xml added dependency org.gvnix:org.gvnix.web.mvc.binding.roo.addon:X.Y.Z
Created SRC_MAIN_JAVA/org/gvnix/test/web/EntityController_Roo_GvNIXStringTrimmerBinder.aj

Al ejecutar el comando, el add-on incluirá la anotación @GvNIXStringTrimmerBinder en la clase controladora especificada en el parámetro --class del comando o en todas las clases controladoras del proyecto si no se especificó dicho parámetro. El parámetro --emptyAsNull por defecto toma el valor true indicando que las cadenas vacías deben convertirse en valores nulos.

...
@GvNIXStringTrimmerBinder(emptyAsNull = true)
public class EntityController {
}

Esto generará en un aspecto Java propio todo el código necesario para registrar el editor, representado en Spring MVC mediante la clase StringTrimmerEditor.

privileged aspect EntityController_Roo_GvNIXStringTrimmerBinder {

    @InitBinder
    public void EntityController.initStringTrimmerBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }

}

Es interesante resaltar que este método puede ser reutilizado haciendo push-in para registrar cualquier editor asociado a un tipo de datos adecuado, como se hace en el ejemplo anterior asociando String con StringTrimmerEditor.

Para obtener mas detalles sobre el comando ver el apéndice de comandos de este add-on.

15.2. Futuras versiones

  • Para futuras versiones este add-on permitirá registrar más editores de entre los enumerados en la Tabla 5.2 de la documentación de Spring.

III. Apéndices

En este capitulo se recoge información adicional sobre todo lo comentado en las secciones anteriores así como un apéndice de todos los comandos disponibles en la herramienta de desarrollo gvNIX.

Appendix A: Apéndice de comandos

A.1. Comandos del add-on OCC

Para una descripción detallada de las características del add-on consultar la documentación del add-on OCC (Optimistic Concurrency Control).

Table 1. Comandos del add-on OCC
Comando Descripción

occ checksum set

Establece un control de concurrencia optimista mediante una suma de comprobación (checksum) para una determinada entidad del proyecto

occ checksum all

Establece un control de concurrencia optimista mediante una suma de comprobación (checksum) para todas las entidades del proyecto

A.1.1. occ checksum set

Establece un control de concurrencia optimista mediante una suma de comprobación (checksum) en una entidad del modelo. Si la entidad ya tiene configurado este sistema de control, el comando no permitirá sobreescribir su configuración y cualquier modificación deberá realizarse sobre la anotación relacionada @GvNIXEntityOCCChecksum que se habrá incluido en la clase Java de la entidad.

Sus parámetros son:

--entity

[Requerido si no está en el contexto] [Clase Java] [Autocompletado] + Entidad sobre la que establecer el sistema de control de concurrencia optimista mediante una suma de comprobación (checksum).

--fieldName

[Opcional] [Cadena] + Nombre del campo de la entidad en donde almacenar la suma de comprobación (checksum). Habitualmente este parámetro no necesita ser establecido. Si no se especifica, tomará por convención el nombre occChekcsum para dicha propiedad.

--digestMethod

[Opcional] [Cadena] + Método a utilizar en el cálculo de la suma de comprobación (checksum). Habitualmente este parámetro no necesita ser establecido. Los posibles valores vienen definidos por los algoritmos aceptados por MessageDigest.getInstance(String algorithm). Por defecto, se utilizará el algoritmo md5, pero pueden utilizarse otros como por ejemplo sha.

A.1.2. occ checksum all

Estable un control de concurrencia optimista mediante una suma de comprobación (checksum) en todas las entidades de la aplicación que no la tuviesen todavía establecida. Cualquier modificación una vez establecido el control deberá realizarse sobre la anotación relacionada @GvNIXEntityOCCChecksum que se habrá incluido en todas las clases Java de entidad.

Sus parámetros son:

--fieldName

[Opcional] [Cadena] + Nombre del campo en cada entidad en donde almacenar la suma de comprobación (checksum). Habitualmente este parámetro no necesita ser establecido. Si no se especifica, tomará por convención el nombre occChekcsum para dicha propiedad.

--digestMethod

[Opcional] [Cadena] + Método a utilizar en el cálculo de la suma de comprobación (checksum). Habitualmente este parámetro no necesita ser establecido. Los posibles valores vienen definidos por los algoritmos aceptados por MessageDigest.getInstance(String algorithm). Por defecto, se utilizará el algoritmo md5, pero pueden utilizarse otros como por ejemplo sha.

A.2. Comandos del add-on JPA

Para una descripción detallada de las características del add-on consultar la documentación del add-on JPA.

Table 2. Comandos de add-on jpa
Comando Descripción

jpa gvnix setup

Instala el soporte para la funcionalidad

jpa batch add

Genera el servicio de persistencia en bloque para una entidad.

jpa batch all

Genera el servicio de persistencia en bloque para todas las entidades.

jpa audit setup

Configura la auditoría de historico creando la clase que proveera del nombre de usuario que realiza el cambio. Sólo se puede ejecutar una vez.

jpa audit add

Añade el soporte de auditoría a una entidad.

jpa audit all

Añade el soporte de auditoría todas las entidades.

jpa audit revisionLog

Establece el proveedor de registro de cambios a usar.

jpa geo setup

Configura el proyecto para poder guardar entidades con campos de tipo geográficos.

field geo

Añade un nuevo campo de tipo geográfico a la entidad seleccionada.

finder geo all

Genera los buscadores de todos los campos de tipo GEO de todas las entidades registradas en el proyecto.

finder geo add

Genera los buscadores de todos los campos de tipo GEO para la entidad seleccionada.

A.2.1. jpa gvnix setup

Instala las dependencias necesarias para las funcionalidades del add-on.

A.2.2. jpa batch add

Crea el servicio de persistencia en bloque para una entidad.

Sus parámetros son:

--entity

[Requerido] [Clase entidad] [Autocompletado] + Entidad destino de las operaciones de persistencia.

--type

[Opcional] [Clase] [Autocompletado] + Clase de servicio a generar. Si se omite se generará una clase, con nombre basado en el nombre de la entidad, en el mismo paquete que la entidad.

A.2.3. jpa batch all

Crea el servicio de persistencia en bloque para todas las entidades de la aplicación.

Sus parámetros son:

--package

[Opcional] [Paquete] [Autocompletado] + Paquete donde se generarán las clases de servicio a generar. Si se omite se generarán en el mismo paquete que la entidad a la que afecta. El nombre de la clase del servicio se genera a partir del nombre de la entidad.

A.2.4. jpa audit setup

Configura la auditoría de historico creando la clase que proveera del nombre de usuario que realiza el cambio. Sólo se puede ejecutar una vez.

Sus parámetros son:

--service

[Requerido] [Clase] + Nombre de la clase a crear para hacer de proveedor del objeto usuario.

--userType

[Opcional] [Clase] [Autocompletado] + Clase a usar como usuario. Por defecto String.

Lanzará un warning informando que tiene que ajustar la implementación de la clase en dos circunstancias: Si no está configurado Spring Security:: Si la clase userType no es String y no implementa UserDetails.

A.2.5. jpa audit add

Añade el soporte de auditoría a una entidad.

Sus parámetros son:

--entity

[Requerido] [Clase entidad] [Autocompletado] + Entidad a la que añadir la auditoría.

--type

[Opcional] [Clase] [Autocompletado] + Clase a crear como EntityListener para establecer los datos de auditoría. Si no se establece se genera una clase, basada en el nombre de la entidad, en el mismo paquete que la entidad.

A.2.6. jpa audit all

Añade el soporte de auditoría a todas las entidades de la aplicación.

Sus parámetros son:

--package

[Opcional] [Paquete] [Autocompletado] + Paquete donde se generarán las clases EntityListener. Si se omite se generarán en el mismo paquete que la entidad a la que afecta. El nombre de la clase EntityListener se genera a partir del nombre de la entidad.

A.2.7. jpa audit revisionLog

Selecciona el proveedor de gestión de revisiones de entidades a usar.

Sus parámetros son:

--provider

[Requerido] [Identificador de proveedor] [Autocompletado] + Identificador del proveedor de revisiones a usar. Sólo estarán visibles aquellos proveedor que puedan utilizarse en el proyecto actual (esto se consulta al la propia instancia de proveedor). Los proveedores se registran como add-ons en el framework (al estilo de los proveedores de JDBC para la ingeniería inversa) y deben de implementar un interfaz definido.

A.2.8. jpa geo setup

Configura el proyecto para poder guardar entidades con campos de tipo geográficos.

Sus parámetros son:

--provider

[Requerido] [Identificador de proveedor] [Autocompletado] + Identificador del proveedor de persistencia GEO a usar. Sólo estarán visibles aquellos proveedor que puedan utilizarse en el proyecto actual (esto se consulta al la propia instancia de proveedor). Los proveedores se registran como add-ons en el framework (al estilo de los proveedores de JDBC para la ingeniería inversa) y deben de implementar un interfaz definido.

A.2.9. field geo

Añade un nuevo campo de tipo geográfico a la entidad seleccionada.

Sus parámetros son:

--class

[Requerido] [Autocompletado] + Entidad sobre la que se quiere añadir el nuevo campo de tipo GEO

--fieldName

[Requerido] + Nombre del nuevo campo que se quiere añadir

--type

[Requerido] [Autocompletado] + Selecciona el tipo de dato GEO que representará el nuevo campo añadido a la entidad. Puede tomar los siguientes valores:

  • POINT (Se guarda un único punto en la base de datos)

  • LINESTRING (Se guardan una serie de puntos que forman una linea continua)

  • MULTILINESTRING (Se guardan una serie de puntos que forman varias lineas continuas)

  • POLYGON (Se guardan una serie de puntos que forman un polígono. Siempre empieza y acaba en el mismo punto.)

  • GEOMETRY (Se guarda una serie de puntos que forman una geometría. Acepta cualquiera de las geometrías anteriores.)

A.2.10. finder geo all

Genera los buscadores de todos los campos de tipo GEO de todas las entidades registradas en el proyecto.

A.2.11. finder geo add

Genera los buscadores de todos los campos de tipo GEO para la entidad seleccionada.

Sus parámetros son:

--class

[Requerido] [Autocompletado] + Entidad sobre la que se quieren generar los métodos de búsqueda.

A.3. Comandos del add-on Web Dialog

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web Dialog.

Table 3. Comandos del add-on Web Dialog
Comando Descripción

web mvc dialog setup

Instala el soporte para diálogos modales y realiza la gestión de ciertas excepciones para que sean visualizadas de forma amigable y en múltiples idiomas

web mvc dialog exception list

Muestra por la consola la lista de excepciones que están siendo actualmente gestionadas

web mvc dialog exception add

Incluye una nueva excepción dentro de la gestión de excepciones y permite definir el mensaje amigable asociado a la excepción en un determinado idioma

web mvc dialog exception set language

Añade o actualiza un mensaje amigable asociado a una excepción en un determinado idioma para lo que la excepción debe haber sido incluida previamente en el sistema de gestión de excepciones con el comando anterior

web mvc dialog exception remove

Quita una excepción de la gestión y por lo tanto no se mostrará un mensaje amigable y en múltiples idiomas en el caso de producirse y no ser controlada desde el proyecto

web mvc dialog add

Añade dos métodos en el código fuente de un controlador que permiten abrir un diálogo modal en una página de la aplicación sin realizar ninguna implementación en la capa web

A.3.1. web mvc dialog setup

Instala en el proyecto el soporte para diálogos de error y de usuario en ventana modal (pop-up). A partir de ese momento los mensajes de error de la aplicación se mostrarán con ese formato. También configura un sistema para visualizar de forma amigable y con soporte multi idioma ciertas excepciones que se pueden producir en esta clase de aplicaciones. Ver Add-on Web Dialog para una información más detallada.

A.3.2. web mvc dialog exception list

Muestra por consola la lista de excepciones que actualmente están siendo gestionadas. Es decir, las excepciones que si no son controladas desde la aplicación y se producen, aparecerán al usuario en una ventana modal con un mensaje amigable y en multiples idiomas. El resultado mostrado por la consola será algo similar a lo siguiente:

Handled Exceptions:
.DataAccessException
.NoSuchRequestHandlingMethodException
.TypeMismatchException
.MissingServletRequestParameterException
java.sql.SQLException
java.io.IOException
org.springframework.transaction.TransactionException
java.lang.UnsupportedOperationException
javax.persistence.OptimisticLockException
org.hibernate.NonUniqueObjectException
org.hibernate.exception.ConstraintViolationException
org.hibernate.id.IdentifierGenerationException
A.3.3. web mvc dialog exception add

Incluye una nueva excepción a la gestión de excepciones. De esta forma, si se produce dicha excepción en la aplicación se visualizará de forma amigable mediante un mensaje modal y en múltiples idiomas. Este comando permite también definir el mensaje amigable asociado a la excepción en un determinado idioma. El mensaje amigable se compone de título y descripción.

Sus parámetros son:

--exception

[Requerido] [Cadena] + Nombre de la excepción a incluir en la gestión de excepciones. Si se desea que la definición sea única, se ha de especificar el paquete java completo del que proviene, por ejemplo java.lang.NullPointerException, ya que si se especifica únicamente el nombre, por ejemplo NullPointerException, aplicaría a todas las excepciones con dicho nombre sea cual sea el paquete en el que se encuentre.

--title

[Requerido] [Cadena] + Título de la ventana modal que se mostrará en pantalla cuando se produzca la excepción.

--description

[Requerido] [Cadena] + Texto con el contenido de la ventana modal que se mostrará en pantalla cuando se produzca la excepción.

--language

[Requerido] [Cadena] + Idioma del título y de la descripción en su formato ISO: es, de, it, nl, sv, en, etc.

A.3.4. web mvc dialog exception set language

Añade o actualiza el mensaje amigable asociado a una excepción en un determinado idioma. La excepción debe haber sido incluida anteriormente en el sistema de gestión de excepciones con el comando web mvc dialog exception add. El mensaje amigable se compone de título y descripción.

Sus parámetros son:

--exception

[Requerido] [Cadena] + Nombre de la excepción ya incluida en la gestión de excepciones para la que se desea añadir o modificar sus mensajes amigables en un idioma determinado. Se puede obtener el nombre exacto de la excepción mediante el comando web mvc dialog exception list.

--title

[Requerido] [Cadena] + Título de la ventana modal que se mostrará en pantalla cuando se produzca la excepción.

--description

[Requerido] [Cadena] + Texto con el contenido de la ventana modal que se mostrará en pantalla cuando se produzca la excepción.

--language

[Requerido] [Cadena] + Idioma del título y de la descripción en su formato ISO: es, de, it, nl, sv, en, etc.

A.3.5. web mvc dialog exception remove

Quita una excepción del sistema de gestión de excepciones y por lo tanto no se mostrará un mensaje amigable y en múltiples idiomas en el caso de producirse cuando no es controlada desde el código fuente de la aplicación.

Sus parámetros son:

--exception

[Requerido] [Cadena] + Nombre de la excepción ya incluida en la gestión de excepciones que se desea eliminar. Se puede obtener el nombre exacto de la excepción mediante el comando web mvc dialog exception list.

A.3.6. web mvc dialog add

Añade dos métodos en el código fuente de un controlador que permiten abrir un diálogo modal en una página de la aplicación sin realizar ninguna implementación en la capa web. Ver la sección de inclusión de nuevos diálogos modales para una información más detallada.

Sus parámetros son:

--class

[Requerido] [Clase Java] [Autocompletado] + Controlador para el cual generar los métodos de creación de un diálogo modal.

--name

[Requerido] [Cadena] + Nombre que se dará a uno de los métodos en el controlador. Este método y el método por defecto con nombre modalDialog permitirán mostrar un diálogo modal cada uno con distintas características.

A.4. Comandos del add-on Web Menu

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web Menu.

Table 4. Comandos del add-on Web Menu
Comando Descripción

menu setup

Instala el sistema de gestión del menú web que permite organizar de forma sencilla su estructura de páginas y permisos

menu entry add

Añade un elemento al menú, sea una página o un grupo

menu entry visibility

Define un elemento del menú como visible o oculto

menu entry roles

Establece una lista de perfiles de usuario para los que se mostrará una entrada del menú

menu entry move

Mueve un elemento del menú y todos los hijos que pueda tener

menu entry update

Actualiza un elemento del menú

menu entry info

Muestra por consola los valores establecidos en un elemento del menú y en todos los hijos que pueda tener

menu tree

Muestra por consola un árbol con un resumen de los elementos del menú.

Instala y activa en la aplicación el sistema de gestión del menú web para la organización de su estructura de páginas y la definición de permisos. A partir de este momento se podrán utilizar todos los comandos de gestión del menú para modificar su modelo de datos y definir permisos de visualización sobre las distintas opciones del menú en función del perfil de cada usuario. El modelo de datos se encuentra definido en el fichero src/main/webapp/WEB-INF/views/menu.xml.

Para una descripción detallada de las tareas que realiza este comando consultar la documentación de instalación de la gestión del menú.

A.4.2. menu entry add

Añade un elemento al menú, sea una página o un grupo. La diferencia entre ambos es que una página tiene asociada una URL y un grupo no. Este comando crea un elemento del menú, pero no crea una nueva vista en el proyecto. La creación de una vista puede realizarse con el comando web mvc view.

Sus parámetros son:

--category

[Opcional] [Elemento del menú] [Autocompletado] + Identificador del elemento del menú donde incluir la nueva entrada. El elemento del menú puede ser una página o un grupo. Si no se especifica este parámetro la nueva entrada se incluirá en el grupo Page que si no existe será creado al final del menú.

--url

[Opcional] [Cadena] + URL con la que enlazará el elemento del menú.

--label

[Requerido] [Cadena] + Título para el elemento del menú. Se creará una etiqueta con este título en el fichero src/main/webapp/WEB-INF/i18n/application.properties. Este título será ignorado si se define el parámetro messageCode.

--messageCode

[Opcional] [Cadena] + Etiqueta que representará la traducción en múltiples idiomas del título del elemento del menú. Si todavía no existe, se deberá crear dicha etiqueta en cada fichero de idioma que exista configurado en el proyecto en src/main/webapp/WEB-INF/i18n/messages_xx.properties.

--roles

[Opcional] [Cadena] + Lista de perfiles con permiso para ver el elemento del menú. Los distintos elementos de la lista de perfiles deben estar separados por comas. Si no se establece este parámetro, el elemento del menú aparecerá para todos los perfiles.

Al finalizar la ejecución de este comando se informará del identificador del nuevo elemento del menú añadido con un texto similar al siguiente.

New page 'i_page_xxxx_xxxx' added.
A.4.3. menu entry visibility

Cambia la visibilidad de un elemento del menú, es decir, permite definirlo como visible o oculto.

Sus parámetros son:

--id

[Requerido] [Elemento del menú] [Autocompletado] + Identificador del elemento del menú, sea página o grupo.

--hidden

[Requerido] [Booleano] [Autocompletado] + Indica si este elemento del menú debe ocultarse. Si se especifica este parámetro sin ningún valor, tomará el valor true y ocultará el elemento del menú. Si no se especifica este parámetro, tomará el valor false y mostrará el elemento del menú.

A.4.4. menu entry roles

Establece una lista de perfiles de usuario para los que se mostrará una entrada del menú. No se mostrará a los usuarios que no tengan algún perfil de la lista.

Sus parámetros son:

--id

[Requerido] [Elemento del menú] [Autocompletado] + Identificador del elemento del menú, sea página o grupo.

--roles

[Requerido] [Cadena] + Lista de perfiles con permiso para ver el elemento del menú. Los distintos elementos de la lista de perfiles deben estar separados por comas.

A.4.5. menu entry move

Mueve un elemento del menú y todos los hijos que pueda tener. Se puede cambiar su posición en el orden de elementos del menú o se puede mover dentro de otro elemento del menú.

Sus parámetros son:

--id

[Requerido] [Elemento del menú] [Autocompletado] + Identificador del elemento del menú, sea página o grupo.

--into

[Opcional] [Elemento del menú] [Autocompletado] + Identificador de un elemento del menú donde añadir como hijo el elemento del menú. El elemento se insertará en la última posición de la lista de hijos. Este parámetro no se puede especificar simultaneamente junto al parámetro before.

--before

[Opcional] [Elemento del menú] [Autocompletado] + Identificador de un elemento del menú antes del cual insertar el elemento del menú. Este parámetro no se puede especificar simultaneamente junto al parámetro into.

A.4.6. menu entry update

Actualiza un elemento del menú, sea una página o un grupo. Los valores no especificados en el comando se mantendrán con su valor original.

Sus parámetros son:

--id

[Requerido] [Elemento del menú] [Autocompletado] + Identificador del elemento del menú, sea página o grupo.

--nid

[Opcional] [Cadena] + Nuevo identificador para el elemento del menú. Por convención, se utiliza el prefijo _c para los grupos e _i para las páginas.

--label

[Opcional] [Cadena] + Título para el elemento del menú. Se actualizará con el nuevo título la etiqueta correspondiente en el fichero src/main/webapp/WEB-INF/i18n/application.properties. Este título será ignorado si se define o ya estaba definido el parámetro messageCode.

--messageCode

[Opcional] [Cadena] + Etiqueta que representará la traducción en múltiples idiomas del título del elemento del menú. Si todavía no existe, se deberá crear dicha etiqueta en cada fichero de idioma que exista configurado en el proyecto en src/main/webapp/WEB-INF/i18n/messages_xx.properties.

--url

[Opcional] [Cadena] + URL con la que enlazará el elemento del menú.

--roles

[Opcional] [Cadena] + Lista de perfiles con permiso para ver el elemento del menú. Los distintos elementos de la lista de perfiles deben estar separados por comas.

--hidden

[Requerido] [Booleano] [Autocompletado] + Indica si este elemento del menú debe ocultarse. Si se especifica este parámetro sin ningún valor, tomará el valor true y ocultará el elemento del menú. Si no se especifica este parámetro, tomará el valor false y mostrará el elemento del menú.

A.4.7. menu entry info

Muestra por consola los valores establecidos en un elemento del menú y en todos los hijos que pueda tener, formateados de forma amigable para su fácil lectura.

Sus parámetros son:

--id

[Requerido] [Elemento del menú] [Autocompletado] + Identificador del elemento del menú, sea página o grupo.

--lang

[Opcional] [Idioma] + Idioma en el que mostrar los valores de las distintas etiquetas definidas para cada elemento del menú.

El comando mostrará un resultado similar al siguiente:

[c_person]
URL          : No
Label Code   : menu_category_person_label
Label        : Person
Message Code :
Message      :
Roles        :
Hidden       : false
Children     :
               [i_person_new]
               URL          : /people?form
               Label Code   : menu_item_person_new_label
               Label        : Person
               Message Code : global_menu_new
               Message      : Create new {0}
               Roles        :
               Hidden       : false

               [i_person_list]
               URL          : /people?page=1&size=${empty param.size ? 10 : param.size}
               Label Code   : menu_item_person_list_label
               Label        : People
               Message Code : global_menu_list
               Message      : List all {0}
               Roles        :
               Hidden       : false

Muestra por consola un árbol con un resumen de los elementos del menú, opcionalmente a partir de un determinado elemento del menú.

Sus parámetros son:

--id

[Opcional] [Elemento del menú] [Autocompletado] + Identificador del elemento del menú, sea página o grupo, a partir del cual comenzar a mostrar el árbol resumen. Si no se especifica, se muestran todas las página del menú.

El comando mostrará un resultado similar al siguiente:

roo>
[c_pet, visible, no-URL]
          /pets?form  [i_pet_new, visible]
          /pets?page=1&size=${empty param.size ? 10 : param.size}  [i_pet_list, visible]
          /pets?find=ByNameAndWeight&form  [fi_pet_nameandweight, visible]
          /pets?find=ByOwner&form  [fi_pet_owner, visible]
          /pets?find=BySendRemindersAndWeightLessThan&form
                [fi_pet_sendremindersandweightlessthan, visible]
          /pets?find=ByTypeAndNameLike&form  [fi_pet_typeandnamelike, visible]

[c_owner, visible, no-URL]
          /owners?form  [i_owner_new, visible]
          /owners?page=1&size=${empty param.size ? 10 : param.size}
                [i_owner_list, visible]

[c_visit, visible, no-URL]
          /visits?form  [i_visit_new, visible]
          /visits?page=1&size=${empty param.size ? 10 : param.size}
                [i_visit_list, visible]
          /visits?find=ByDescriptionAndVisitDate&form
                [fi_visit_descriptionandvisitdate, visible]
          /visits?find=ByDescriptionLike&form  [fi_visit_descriptionlike, visible]
          /visits?find=ByVisitDateBetween&form  [fi_visit_visitdatebetween, visible]

[c_vet, visible, no-URL]
          /vets?form  [i_vet_new, visible]
          /vets?page=1&size=${empty param.size ? 10 : param.size}  [i_vet_list, visible]

[c_seleniumtests, visible, no-URL]
          /resources/selenium/test-suite.xhtml  [si_seleniumtests_test, visible]

A.5. Comandos del add-on Web Report

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web Report.

Table 5. Comandos del add-on Web Report
Comando Descripción

web report setup

Configura en el proyecto el soporte para la generación de informes en formato PDF, XLS, CSV y HTML

web report add

Crea un nuevo informe y permite su acceso desde el controlador de una entidad que se le proporciona como parámetro

A.5.1. web report setup

Configura en el proyecto el soporte para la generación de informes en formato PDF, XLS, CSV y HTML mediante Jasper Reports y su descarga desde la aplicación web.

El comando sólo estará disponible si el proyecto utiliza Spring MVC en la capa web y Tiles como motor de vistas web.

Este comando no tiene ningún parámetro obligatorio ni opcional.

Para una descripción detallada de las configuraciones que realiza este comando en el proyecto, consultar la sección de instalación del add-on Web Report.

A.5.2. web report add

Crea un nuevo informe y permite su acceso desde el controlador de una entidad que se le proporciona como parámetro al comando. El controlador debe obligatoriamente estar gestionando una entidad del proyecto. El informe, por defecto, mostrará los 10 primeros registros de la entidad.

Si el comando se ejecuta varias veces sobre el mismo controlador y con el mismo nombre de informe, se añadirán al informe existente los nuevos formatos de generación que se hayan podido especificar. Para mas información consultar la sección de generación de un informe del add-on Web Report.

El comando sólo estará disponible si el proyecto utiliza Spring MVC en la capa web y Tiles como motor de vistas web.

Sus parámetros son:

--controller

[Requerido] [Clase Java] [Autocompletado] + Clase controladora que gestiona una entidad en la que se desea añadir el informe. Este controlador ha de contener la anotación @RooWebScaffold y su atributo formBackingObject indicará la entidad para la que se generará el informe.

--reportName

[Requerido] [Cadena] + Nombre que se le quiere dar al informe y que servirá de identificador único. No admite espacios y el valor proporcionado será convertido a minúsculas.

--format

[Opcional] [Cadena] + Lista de formatos en los que se permitirá generar el informe. Los formatos de la lista deberán estar separados por comas y sin espacios. Los formatos soportados son: pdf, xls, csv y html. Si el nombre del informe ya existe en un controlador, los formatos nuevos que se hubiesen podido definir se añadirán al informe existente. Los formatos siempre serán convertidos a minúsculas. Si este parámetro no se especifica, tomará por defecto el valor pdf.

A.6. Comandos del add-on Service

Para una descripción detallada de las características del add-on consultar la documentación del add-on Service.

Table 6. Comandos del add-on Service
Comando Descripción

remote service class

Crea una clase Java que actuará como servicio local dentro de la aplicación

remote service operation

Añade un nuevo método en una clase Java

remote service define ws

Hace que una clase Java pueda ser accedida desde el exterior a través de un servicio web

remote service export operation

Hace que un método de una clase Java pueda ser accedido desde el exterior a través de una operación del servicio web

remote service list operation

Muestra el listado de métodos de una clase Java que podrían ser ofrecidos al exterior como operaciones del servicio web

remote service export ws

Crea en el proyecto la infraestructura necesaria definida por un WSDL para ofrecer ciertas operaciones mediante un servicio web

remote service import ws

Crea en el proyecto la infraestructura necesaria definida por un WSDL para acceder a ciertas operaciones situadas en un servicio web

remote service ws list

Lista los servicios web que se encuentran definidos en la aplicación

remote service security ws

Añade o actualiza la configuración necesaria para firmar las peticiones que se hacen a un servicio web remoto

A.6.1. remote service class

Crea una clase Java que actuará como servicio local dentro de la aplicación. El servicio se podrá utilizar desde cualquier otra clase Java definiendo una propiedad del tipo de la clase de servicio con la anotación @Autowired.

Sus parámetros son:

--class

[Requerido] [Clase Java] [Autocompletado] + Paquete y nombre donde crear la clase Java de servicio.

A.6.2. remote service operation

Añade un nuevo método en una clase Java. La clase Java puede ser una entidad, controlador, servicio o cualquier otro tipo.

Sus parámetros son:

--name

[Requerido] [Cadena] + Nombre del método a añadir en la clase Java.

--service

[Requerido] [Clase Java] [Autocompletado] + Paquete y nombre de la clase Java donde crear el nuevo método.

--return

[Opcional] [Tipo Java] [Autocompletado] + Tipo de dato Java que devolverá el método.

--paramNames

[Opcional] [Cadena] + Nombre de los parámetros de entrada del método, separados mediante comas y sin espacios.

--paramTypes

[Opcional] [Tipos Java] [Autocompletado] + Tipos Java de los parámetros de entrada del método, separados mediante comas y sin espacios.

--exceptions

[Opcional] [Cadena] + Tipos Java de las excepciones que puede lanzar el método, separados mediante comas y sin espacios.

A.6.3. remote service define ws

Hace que una clase Java pueda ser accedida desde el exterior a través de un servicio web. Para ello, creará toda la infraestructura necesaria para que sistemas externos puedan comunicarse con ella mediante los protocolos y tecnologías propias de los servicios web. Si la clase indicada como parámetro no existe, será creada automáticamente.

Se recomienda no especificar en este comando ningún parámetro opcional si no es estrictamente necesario y se conoce las implicaciones que tendrá desde el punto de vista de la interoperabilidad de servicios web. Si no se especifica, para cada parámetro se proporcionará un valor adecuado para facilitar la máxima interoperabilidad del servicio web con el exterior.

Tras publicar una clase Java a través de un servicio web, sus métodos todavía no serán accesibles como operaciones del servicio web hasta que no se le indique para cada método.

Sus parámetros son:

--class

[Requerido] [Clase Java] [Autocompletado] + Paquete y nombre de la clase Java a hacer accesible desde el exterior a través de un servicio web. Si la clase Java no existe, será creada y además se le aplicará las características propias de un servicio local. Por ejemplo, org.gvnix.test.service.Service.

--serviceName

[Opcional] [Cadena] + Nombre con el que se quiere publicar el servicio web. Por defecto, tomará el mismo nombre que la clase Java. Por ejemplo, Service.

--portTypeName

[Opcional] [Cadena] + Nombre para el tipo de puerto o PortType del servicio web. Por defecto, tomará el mismo nombre que la clase Java seguido del sufijo PortType. Por ejemplo, ServicePortType.

--addressName

[Opcional] [Cadena] + Dirección URL relativa a la raíz de la aplicación desde donde se podrá acceder al servicio web. Por defecto, tomará el mismo nombre que la clase Java. Por ejemplo, Service.

--targetNamespace

[Opcional] [Cadena] + Espacio de nombres o Namespace del servicio web. Debe tener formato de URL. Por defecto, tendrá el mismo valor que el paquete de la clase Java en sentido inverso y con formato de URL. Por ejemplo, http://service.test.gvnix.org/.

A.6.4. remote service export operation

Hace que un método de una clase Java pueda ser accedido desde el exterior a través de una operación del servicio web. Para ello, creará toda la infraestructura necesaria para que sistemas externos puedan comunicarse con ella mediante los protocolos y tecnologías propias de los servicios web. Si la clase indicada como parámetro no está configurada todavía para ser accedida a través de un servicio web, se le aplicará esta configuración automáticamente.

Se recomienda no especificar en este comando ningún parámetro opcional si no es estrictamente necesario y se conoce las implicaciones que tendrá desde el punto de vista de la interoperabilidad de servicios web. Si no se especifica, para cada parámetro se proporcionará un valor adecuado para facilitar la máxima interoperabilidad de la operación del servicio web con el exterior.

Sus parámetros son:

--class

[Requerido] [Clase Java] [Autocompletado] + Paquete y nombre de la clase Java que contiene el método que se desea hacer accesible a través de una operación del servicio web. Por ejemplo, org.gvnix.test.service.Service.

--method

[Requerido] [Cadena] + Nombre del método que se desea hacer accesible a través de una operación del servicio web. Por ejemplo, method.

--operationName

[Opcional] [Cadena] + Nombre que tendrá la operación del servicio web y que dará acceso al método de la clase Java. Por defecto, tomará el mismo nombre que el método. Por ejemplo, method.

--resultName

[Opcional] [Cadena] + Nombre que tendrá el resultado de la operación del servicio web y que será de un tipo de datos equivalente al resultado del método. Por defecto, tomará el nombre result.

--resultNamespace

[Opcional] [Cadena] + Espacio de nombres o Namespace del resultado de la operación del servicio web. Debe tener formato de URL. Por defecto, tendrá el mismo valor que el paquete de la clase Java en sentido inverso y con formato de URL. Por ejemplo, http://service.test.gvnix.org/.

--responseWrapperName

[Opcional] [Cadena] + Nombre que tendrá el objeto que contendrá la respuesta de la operación del servicio web. Por defecto, tomará el mismo nombre que el método seguido del sufijo Response. Por ejemplo, methodResponse.

--responseWrapperNamespace

[Opcional] [Cadena] + Espacio de nombres o Namespace del objeto que contendrá el resultado de la operación del servicio web. Debe tener formato de URL. Por defecto, tendrá el mismo valor que el paquete de la clase Java en sentido inverso y con formato de URL. Por ejemplo, http://service.test.gvnix.org/.

--requestWrapperName

[Opcional] [Cadena] + Nombre que deberá tener el objeto que contendrá la petición a la operación del servicio web. Por defecto, tomará el mismo nombre que el método. Por ejemplo, method.

--requestWrapperNamespace

[Opcional] [Cadena] + Espacio de nombres o Namespace del objeto que contendrá el la petición a la operación del servicio web. Debe tener formato de URL. Por defecto, tendrá el mismo valor que el paquete de la clase Java en sentido inverso y con formato de URL. Por ejemplo, http://service.test.gvnix.org/.

A.6.5. remote service list operation

Muestra el listado de métodos de una clase Java que podrían ser ofrecidos como operaciones del servicio web. La clase Java debe haber sido previamente definida como accesible a través de un servicio web.

Sus parámetros son:

--class

[Requerido] [Clase Java] [Autocompletado] + Paquete y nombre de la clase Java de la que obtener el listado de métodos que podrían ser ofrecidos como operaciones del servicio web. Por ejemplo, org.gvnix.test.service.Service.

A.6.6. remote service export ws

Crea en el proyecto toda la infraestructura necesaria para ofrecer ciertas operaciones mediante un servicio web. El servicio web y sus operaciones vendrán definidas mediante un contrato de servicio o WSDL.

El comando creará una clase Java que representará en el proyecto al servicio web y creará dentro tantos métodos como operaciones hubiesen definidas en el contrato de servicio. Con esto, el servicio web y sus operaciones ya son accesibles desde el exterior. Será responsabilidad del desarrollador el implementar la lógica de negocio de cada método.

Sus parámetros son:

--wsdl

[Requerido] [Cadena] + Ruta al archivo que define el contrato de servicio o WSDL cuya infraestructura Java se desea crear en el proyecto. La ruta puede ser a un archivo local mediante file://ruta, a una dirección web mediante http://ruta o a una dirección web segura mediante https://ruta.

A.6.7. remote service import ws

Crea en el proyecto toda la infraestructura necesaria para acceder a ciertas operaciones situadas en un servicio web. El servicio web y sus operaciones vendrán definidas mediante un contrato de servicio o WSDL.

El comando creará una clase Java que representará en el proyecto al servicio web y creará dentro tantos métodos como operaciones hubiesen definidas en el contrato de servicio. Invocando a alguno de estos métodos se estará accediendo a la operación correspondiente del sistema externo.

Sus parámetros son:

--wsld

[Requerido] [Cadena] + Ruta al archivo que define el contrato de servicio o WSDL cuya infraestructura Java se desea crear en el proyecto. La ruta puede ser a un archivo local mediante file://ruta, a una dirección web mediante http://ruta o a una dirección web segura mediante https://ruta.

--class

[Requerido] [Clase Java] [Autocompletado] + Paquete y nombre de la clase Java que permitirá acceder al servicio web externo creando un método por cada una de las operaciones del servicio web. Si la clase Java no existe, será creada y además se le aplicará las características propias de un servicio local. Por ejemplo, org.gvnix.test.service.Service.

A.6.8. remote service ws list

Lista los servicios web que se encuentran definidos en la aplicación, tanto los que ofrecen servicios web al exterior como los que acceden a servicios web externos.

Este comando no tiene ningún parámetro obligatorio ni opcional.

A.6.9. remote service security ws

Añade o actualiza la configuración necesaria para firmar las peticiones que se hacen a un servicio web remoto.

Sus parámetros son:

--class

[Requerido] [Clase Java] [Autocompletado] + Paquete y nombre de la clase Java que define realiza el acceso al servicio web externo. Por ejemplo, org.gvnix.test.service.Service.

--certificate

[Requerido] [Cadena] + Ruta y nombre del fichero donde se encuentra el certificado a utilizar para firmar la petición. El certificado debe de tener un formato pkcs12 y una extensión p12. El certificado será copiado al directorio de recursos del proyecto. Por ejemplo, /tmp/certificado.p12.

--password

[Requerido] [Cadena] + Contraseña para acceder al certificado de firma.

--alias

[Requerido] [Cadena] + Alias a utilizar para la firma.

A.7. Comandos del add-on Web MVC i18n

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web MVC i18n.

Table 7. Comandos de add-on Web MVC i18n
Comando Descripción

web mvc install language

Instala el soporte para un nuevo idioma en el proyecto

A.7.1. web mvc install language

Crea un fichero de propiedades con las traducciones de las etiquetas multi idioma del proyecto en el lenguage solicitado y configura en la capa web un acceso para cambiar a dicho idioma.

Sus parámetros son:

--code

[Requerido] [Idioma] [Autocompletado] + Código del idioma a instalar. Los idiomas disponibles son de, en, es, it, nl y sv.

A.8. Comandos del add-on Dynamic Configuration

Para una descripción detallada de las características del add-on consultar la documentación del add-on Dynamic Configuration.

Table 8. Comandos del add-on Dynamic Configuration
Comando Descripción

configuration create

Crea una nueva configuración con un determinado nombre

configuration property add

Añade una propiedad a la gestión de configuraciones

configuration property value

Cambia el valor que tiene una propiedad en una determinada configuración

configuration property undefined

Deja sin valor una propiedad en una determinada configuración

configuration list

Lista todas las configuraciones definidas

configuration export

Escribe en el proyecto los cambios definidos hasta el momento en las configuraciones

A.8.1. configuration create

Crea una nueva configuración con un determinado nombre.

La primera configuración creada quedará marcada como la configuración por defecto de modo que en el caso de empaquetar la aplicación sin elegir ninguna configuración, será esta la que se aplique.

Sus parámetros son:

--name

[Requerido] [Cadena] + Nombre para la nueva configuración que la referenciará de forma unívoca.

A.8.2. configuration property add

Añade una propiedad a la gestión de configuraciones de modo que dicha propiedad podrá tener distinto valor para cada configuración.

Al añadir una nueva propiedad, quedará almacenado internamente el valor que tubiese en dicho momento. En todas las configuraciones existentes en ese momento y en aquellas que se creen en un futuro la propiedad tendrá por defecto dicho valor.

Sus parámetros son:

--name

[Requerido] [Propiedad] [Autocompletado] + Nombre de la propiedad cuyo valor puede tomar distinto valor en cada configuración.

A.8.3. configuration property value

Cambia el valor que tiene una propiedad en una determinada configuración.

Sus parámetros son:

--configuration

[Requerido] [Configuración] [Autocompletado] + Nombre de la configuración cuyo valor para una propiedad se quiere modificar.

--property

[Requerido] [Propiedad] [Autocompletado] + Nombre de la propiedad cuyo valor se desea modificar.

--value

[Requerido] [Cadena] + Nuevo valor para la propiedad en la configuración.

A.8.4. configuration property undefined

Deja sin valor una propiedad en una determinada configuración.

Esto es útil para evitar que quede almacenado en el código fuente del proyecto algunos valores críticos como puede ser la clave de conexión con la base de datos de producción. El valor se tendrá que proporcionar al empaquetar la aplicación con Maven como un parámetro mediante el modificador -Dnombre.propiedad=valor.

Sus parámetros son:

--configuration

[Requerido] [Configuración] [Autocompletado] + Nombre de la configuración cuyo valor para una propiedad se desea dejar sin valor.

--property

[Requerido] [Propiedad] [Autocompletado] + Nombre de la propiedad cuyo valor se desea dejar sin valor.

A.8.5. configuration list

Lista todas las configuraciones definidas junto con las propiedades incluidas y los valores definidos para cada una de ellas.

Este comando no tiene ningún parámetro obligatorio ni opcional.

A.8.6. configuration export

Escribe en el proyecto los cambios definidos hasta el momento en las configuraciones mediante todos los comandos anteriores utilizando para ello el sistema de perfiles de Maven. Mientras no se ejecute este comando, las configuraciones no serán aplicadas en el proyecto y por lo tanto no podrán ser utilizadas.

Este comando no tiene ningún parámetro obligatorio ni opcional.

A.9. Comandos del add-on Web MVC Binding

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web MVC Binding.

Table 9. Comandos del add-on Web MVC Binding
Comando Descripción

web mvc binding stringTrimmer

Registra el StringTrimmerEditor.

A.9.1. web mvc binding stringTrimmer

Configura en un controlador concreto o en todos los controladores del proyecto un editor de propiedades para cadenas que elimina espacios al inicio y al fin y opcionalmente permite transformar cadenas vacías a valores nulos.

Sus parámetros son:

--class

[Opcional] [Clase Java] [Autocompletado] + Nombre de la clase Java controladora en la que registrar el editor. Si no se indica este parámetro, se registrará el editor en todos los controladores del proyecto.

--emptyAsNull

[Opcional] [Booleano] [Autocompletado] + Indica si las cadenas vacias deben convertirse en valores nulos.

A.10. Comandos del add-on Web MVC

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web MVC.

Table 10. Comandos de add-on Web MVC
Comando Descripción

web mvc batch setup

Instala el soporte para la funcionalidad Web Batch

web mvc batch add

Genera los métodos de de persistencia en bloque para un controlador.

web mvc batch all

Genera los métodos de de persistencia en bloque para todos los controladores.

web mvc jquery setup

Instala los artefacto necesario para usar vistas usando la librería JavaScript jQuery.

web mvc jquery update tags

Actualiza los artefactos, ya instalados en el add-on, por los actuales.

web mvc jquery add

Convierte las vistas de un controlador a jQuery.

web mvc jquery all

Convierte todas las vistas a jQuery.

A.10.1. web mvc batch setup

Instala las dependencias necesarias y configura el proyecto para dar soporte a las peticiones de persistencia en bloque.

A.10.2. web mvc batch add

Añade los métodos al controlador para peticiones de persistencia en bloque.

Sus parámetros son:

--controller

[Requerido] [Clase controlador] [Autocompletado] + Controlador destino.

--service

[Opcional] [Clase de servicios de persistencia] [Autocompletado] + Añade los métodos al todos los controladores para peticiones de persistencia en bloque.

A.10.3. web mvc batch all

Crea el servicio de persistencia en bloque para todas las entidades de la aplicación.

A.10.4. web mvc jquery setup

Instala los artefactos necesario para usar vistas que use la librería jQuery.

A.10.5. web mvc jquery update tags

Actualiza todos los artefactos necesario para que el add-on funcione. Este comando es útil cuando se actualiza la versión del add-on y se desea utilizar los cambios en los tagx u otros artefactos de la nueva versión.

Advertencia:_Al ejecutar este comando, _los artefactos del proyecto serán reescritos. Cualquier cambio sobre los originales se perderá. Por lo tanto, es conveniente disponer de una copia de seguridad o un sistema de control de versiones para revisar las diferencias entre los artefactos anteriores y la actualización.

A.10.6. web mvc jquery add

Convierte las vistas de un controlador a jQuery.

Sus parámetros son:

--type

[Requerido] [Clase controlador] [Autocompletado] + Controlador cuyas vistas se desea convertir a jQuery.

A.10.7. web mvc jquery all

Convierte las vistas de todos los controladores a jQuery.

A.11. Comandos del add-on WEB MVC Bootstrap

Para una descripción detallada de las características del add-on consultar la documentación del add-on Bootstrap.

Table 11. Comandos de Addo-on Bootstrap
Comando Descripción

web mvc bootstrap setup

Este comando importará e instalará todos los recursos necesarios para utilizar bootstrap. Además, modificará la estructura de algunos tagx existentes para que funcionen correctamente con Bootstrap y modificará todas las vistas de la aplicación para que utilicen los tags de JQuery.

web mvc bootstrap update

Este comando permite regenerar de forma correcta todos los componentes importados por Bootstrap. En caso de una modificación incorrecta de estos componentes, podremos regenerarlos para que vuelvan a su estado inicial.

A.11.1. web mvc bootstrap setup

Este comando importará e instalará todos los recursos necesarios para utilizar bootstrap. Además, modificará la estructura de algunos tagx existentes para que funcionen correctamente con Bootstrap y modificará todas las vistas de la aplicación para que utilicen los tags de JQuery.

A.11.2. web mvc bootstrap update

Este comando permite regenerar de forma correcta todos los componentes importados por Bootstrap. En caso de una modificación incorrecta de estos componentes, podremos regenerarlos para que vuelvan a su estado inicial.

A.12. Comandos del add-on Web MVC Datatables

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web MVC Datatables.

Table 12. Comandos del add-on Web MVC Datatables
Comando Descripción

web mvc datatables setup

Instala los artefactos y dependencias requeridas para el funcionamiento del add-on.

web mvc datatables update tags

Actualiza los artefactos, ya instalados en el add-on, por los actuales.

web mvc datatables add

Añade el uso de datatables al controlador especificado.

web mvc datatables all

Añade el uso de Datatables a todos los controladores de la aplicación.

web web mvc datatables details add

Añade un detalle a la vistas list de un controlador.

A.12.1. web mvc datatables setup

Instala todos los artefactos necesario para que el add-on funcione.

Los cambios en el proyecto son:

webapp/styles/datatables

Css usadas por el widget.

webapp/images/datatables/

Imágenes usadas por el widget.

webapp/scripts/datatables

JavaScript usado por el widget.

webapp/WEB-INF/tags/datatables

Tagx que adaptan los parámetros de los tags estándar a los de Dandelion-DataTables.

src/main/resources/datatables*.properties

Fichero con opciones de configuración de Dandelion-DataTables y cadenas de internacionalización.

webapp/WEB-INF/tags/util/load-scripts.tagx

Añade la carga de ficheros js y css a la páginas.

webapp/WEB-INF/web.xml

Registra configuración necesaria para el uso de Dandelion-DataTables.

webapp/WEB-INF/spring/webmvc-config.xml

Registra configuración necesaria para el uso de Dandelion-DataTables.

A.12.2. web mvc datatables update tags

Actualiza todos los artefactos necesario para que el add-on funcione. Este comando es útil cuando se actualiza la versión del add-on y se desea utilizar los cambios en los tagx u otros artefactos de la nueva versión.

Advertencia:_Al ejecutar este comando, _los artefactos del proyecto serán reescritos. Cualquier cambio sobre los originales se perderá. Por lo tanto, es conveniente disponer de una copia de seguridad o un sistema de control de versiones para revisar las diferencias entre los artefactos anteriores y la actualización.

A.12.3. web mvc datatables add

Añade el uso de Datatables al controlador especificado.

Sus parámetros son:

--type

[Requerido] [Clase Java] [Autocompletado] + Nombre de la clase Java controladora a la que se aplicará los cambios.

--ajax

[Opcional] [Booleano] [Autocompletado] + Establece el modo de datos a AJAX (por defecto) o a DOM (cuando es false).

--mode

[Opcional] [Cadena] + Muestra la vista de la entidad que elijamos. En caso de utilizar la vista de "show" se establece el modo de visualización a modo registro. Si se utiliza "--mode list" se estará mostrando la página list.jspx asociada a la entidad.

--inline

[Opcional] [Boolean] [Autocompletado] + Habilita la funcionalidad edición en línea.

A.12.4. web mvc datatables all

Añade el uso de Datatables a todos los controladores de la aplicación, usando los valores por defecto del comando web mvc jquery add.

A.12.5. web mvc datatables details add

Un detalle a la vista list para en base a una propiedad 1 a N de la entidad relacionada (ver descripción en Visualización de detalles).

Sus parámetros son:

--type

[Requerido] [Clase Java] [Autocompletado] + Nombre de la clase Java controladora a la que se aplicará los cambios. Este controlador ya debe estar usando la funcionalidad dataTables

--property

[Requerido] [Nombre de propiedad] + Nombre de la propiedad 1 a N de la entidad relación con el controlador a usar para el detalle.

A.13. Comandos del add-on Web MVC GEO

Para una descripción detallada de las características del add-on consultar la documentación del add-on Web MVC GEO.

Table 13. Comandos del add-on Web MVC GEO
Comando Descripción

web mvc geo setup

Instala los artefactos y dependencias requeridas para el funcionamiento del add-on.

web mvc geo controller

Genera una nueva vista de Mapa en nuestro proyecto

web mvc geo field

Transforma los campos de texto generados por defecto, a campos de tipo mapa para facilitar el guardado de campos geográficos.

web mvc geo entity all

Añade todas las entidades con campos de tipo GEO a la vista de mapa

web mvc geo entity add

Añade la entidad seleccionada a la vista de mapa.

web mvc geo tilelayer

Añade una capa base de tipo Tile a la vista del mapa

web mvc geo wmslayer

Añade una capa base de tipo WMS a la vista del mapa

web mvc geo tool measure

Añade una nueva herramienta de medición a la vista del mapa

web mvc geo tool custom

Añade una nueva herramienta personalizada a la vista del mapa

A.13.1. web mvc geo setup

Instala todos los artefactos necesario para que el add-on funcione.

A.13.2. web mvc geo controller

Genera una vista de mapa en nuestro proyecto. Es posible generar tantas vistas de mapa como se necesiten. Cada una de ellas será independiente y podrán personalizarse de manera individual

Sus parámetros son:

--class

[Requerido] [Clase Java] + Nombre de la clase Java controladora que se desea crear.

--preferredMapping

[Requerido] [String] + Path que se quiere utilizar en el controller

--projection

[Opcional] [CRS] [Autocompletado] + Proyección con la que trabajará el mapa generado

A.13.3. web mvc geo field

Por defecto, a la hora de guardar campos de tipo geográfico se utilizará formato #http://es.wikipedia.org/wiki/Well_Known_Text[WKT] que tendrá que ser introducido de forma manual por el usuario.

Sin embargo, este add-on permite transformar estos campos de texto a componentes de tipo Mapa, gracias a los cuales se facilita la introducción de datos de tipo GEO en una entidad.

Sus parámetros son:

--controller

[Requerido] [Clase Java] [Autocompletado] + Controlador Java asociado a la entidad sobre la cual queremos actualizar campo de tipo input a campo de tipo mapa.

--field

[Requerido] [String] + Campo que queremos modificar

--center

[Opcional] [String] + Configura el centro del mapa que se va a generar. Formato 'lat, lng'

--color

[Opcional] [String] + Color con el que se pintarán los datos en el mapa

--maxZoom

[Opcional] [String] + Nivel de Zoom máximo que se aplicará al mapa generado

--weight

[Opcional] [String] + Grosor de la linea que se utilizará para pintar sobre el mapa

--zoom

[Opcional] [String] + Nivel de Zoom inicial con el que aparecerá el mapa

A.13.4. web mvc geo entity all

Añade todas las entidades con campos de tipo GEO a la vista de mapa

A.13.5. web mvc geo entity add

Añade la entidad seleccionada a la vista de mapa.

Sus parámetros son:

--controller

[Requerido] [Clase Java] [Autocompletado] + Selecciona el controlador asociado a la entidad que quieres añadir a la vista de Mapa.

--map

[Opcional] [Map] + Indica el mapa en el cual quieres añadir la nueva entidad. Si no se selecciona ningún mapa, se añade a todas las vistas de mapa generadas.

A.13.6. web mvc geo tilelayer

Añade una capa base de tipo Tile a la vista del mapa

Sus parámetros son:

--name

[Requerido] [String] + Indica el nombre de la nueva Capa Base. Este nombre debe ser único para cada una de las capas añadidas.

--url

[Requerido] [String] + URL del servidor de mapas que devolverá la capa base

--map

[Opcional] [Mapa] + Indica sobre que mapa quieres añadir la nueva capa base. Si no selecciona ningún mapa se añadirá a todas las vistas de mapas existentes.

--index

[Opcional] [String] + Posición en la que aparecerá la capa base. Si no se introduce ningun indice, se generará uno automáticamente para evitar erorres en la visualización de capas.

--opacity

[Opcional] [Number] + Indica la opacidad que tendrá la capa. Podemos indicar valores entre el 0 y el 1. 1 significa que no es transparente y 0 que es totalmente transparente.

A.13.7. web mvc geo wmslayer

Añade una capa base de tipo WMS a la vista del mapa

Sus parámetros son:

--name

[Requerido] [String] + Indica el nombre de la nueva Capa Base. Este nombre debe ser único para cada una de las capas añadidas.

--url

[Requerido] [String] + URL del servidor de mapas que devolverá la capa base

--map

[Opcional] [Mapa] + Indica sobre que mapa quieres añadir la nueva capa base. Si no selecciona ningún mapa se añadirá a todas las vistas de mapas existentes.

--index

[Opcional] [String] + Posición en la que aparecerá la capa base. Si no se introduce ningun indice, se generará uno automáticamente para evitar erorres en la visualización de capas.

--opacity

[Opcional] [Number] + Indica la opacidad que tendrá la capa. Podemos indicar valores entre el 0 y el 1. 1 significa que no es transparente y 0 que es totalmente transparente.

--layers

[Opcional] [String] + Indica qué capas quieres obtener del servicio WMS

--format

[Opcional] [String] + Indica en qué formato se obtienen las imágenes del servicio WMS. Formato 'image/png'

--transparent

[Opcional] [Boolean] + Indica si la imágen que devuelve tiene transparencia o no

--styles

[Opcional] [String] + Indica qué estilos quieres obtener para cada una de las capas

--version

[Opcional] [String] + Versión del servicio WMS

--crs

[Opcional] [String] + Indica en qué proyección se obtiene la capa WMS. Por defecto EPSG3857

A.13.8. web mvc geo tool measure

Añade una nueva herramienta de medición a la vista del mapa

Sus parámetros son:

--name

[Requerido] [String] + Indica el nombre de la herramienta de medición. Este nombre es único y cada una de las herramientas deben tener el suyo propio.

--map

[Opcional] [Map] + Indica el mapa sobre el que se desea añadir la nueva herramienta. Si no se espeicifica ningún mapa, se añadirá a todas las vistas de mapa registradas en el proyecto.

--preventExitMessageCode

[Opcional] [String] + Código del mensaje multi-idioma que aparecerá al cambiar de herramienta para evitar que se pierdan los cambios aplicados sobre el mapa.

A.13.9. web mvc geo tool custom

Añade una nueva herramienta personalizada a la vista del mapa

Sus parámetros son:

--name

[Requerido] [String] + Indica el nombre de la herramienta de medición. Este nombre es único y cada una de las herramientas deben tener el suyo propio.

--icon

[Requerido] [String] + Indica el icono que mostrará la herramienta personalizada

--activateFunction

[Requerido] [String] + Nombre de la función Javascript que se ejecutará al seleccionar la herramienta personalizada.

--deactivateFunction

[Requerido] [String] + Nombre de la función Javascript que se ejecutará al cambiar de herramienta si esta se encuentra seleccionada.

--map

[Opcional] [Map] + Indica el mapa sobre el que se desea añadir la nueva herramienta. Si no se espeicifica ningún mapa, se añadirá a todas las vistas de mapa registradas en el proyecto.

--iconLibrary

[Opcional] [String] + Indica qué librería se utilizará para representar el icono.

--actionTool

[Opcional] [Boolean] + Indica si la herramienta es únicamente clicable o si puede mantenerse seleccionada

--cursorIcon

[Opcional] [String] + Indica el icono que tendrá el cursor sobre el mapa al activar esta herramienta.

--preventExitMessageCode

[Opcional] [String] + Código del mensaje multi-idioma que aparecerá al cambiar de herramienta para evitar que se pierdan los cambios aplicados sobre el mapa.

A.14. Comandos del add-on WEB MVC Lupa

Para una descripción detallada de las características del add-on consultar la documentación del add-on Lupa.

Table 14. Comandos de Addo-on Componentes Lupa
Comando Descripción

web mvc loupe setup

Este comando importará a nuestro proyecto todos los recursos necesarios para utilizar componentes lupa.

web mvc loupe set

Este comando nos permite generar los métodos necesarios para la búsqueda y visualización de registros del componente lupa en el controlador seleccionado.

web mvc loupe field

Este comando nos permite transformar a componente lupa cualquier campo válido de la entidad a la que está asociado el Controlador en el que se han generado los métodos de lupa.

web mvc loupe update

Este comando nos permite mantener actualizados todos los componentes importados mediante el comando de instalación.

A.14.1. web mvc loupe setup

Este comando importará a nuestro proyecto todos los recursos necesarios para utilizar componentes lupa.

A.14.2. web mvc loupe set

Este comando nos permite generar los métodos necesarios para la búsqueda y visualización de registros del componente lupa en el controlador seleccionado.

Sus parámetros son:

--controller

[Requerido] [Cadena] + Nombre y ruta del Controlador sobre el cual queremos generar los nuevo métodos de búsqueda para el componente lupa.

A.14.3. web mvc loupe field

Este comando nos permite transformar a componente lupa cualquier campo válido de la entidad a la que está asociado el Controlador en el que se han generado los métodos de lupa.

Sus parámetros son:

--controller

[Requerido] [Cadena] + Nombre y ruta del Controlador que ya dispone de los métodos generados.

--field

[Requerido] [Cadena] + Nombre del campo que queremos transformar a componente lupa en la vista de creación y actualización de la capa web.

--additionalFields

[Cadena] + Campos adicionales de la entidad sobre los que se realizará la búsqueda cuando el usuario escriba en el componente lupa. Si no se especifica ningún valor solo será posible buscar por id.

--baseFilter

[Cadena] + Filtro base que se aplica a todas las búsquedas realizadas en el componente lupa.

--caption

[Cadena] + Campo de la entidad relacionada que se mostrará en el desplegable del componente lupa cuando se encuentré un resultado.

--listPath

[Cadena] + Opcionalmente, añadiendo la ruta del fichero a este comando, se puede mostrar un listado distinto al generado por defecto para cada controlador.

--max

[Cadena] + Se especifica el número máximo de resultados que se quiere mostrar en el desplegable del componente lupa. Por defecto se muestran los 3 primeros resultados obtenidos.

A.14.4. web mvc loupe update

Este comando mantiene actualizados todos los componentes que se importan al proyecto gvNIX al realizar la instalación del add-on.

A.15. Comandos del add-on Monitoring

Para una descripción detallada de las características del add-on consultar la documentación del add-on Monitoring.

Table 15. Comandos del add-on Monitoring
Comando Descripción

monitoring setup

Instala las dependencias de JavaMelody además de configurar el proyecto con lo necesario para su funcionamiento.

monitoring all

Establece todas las clases del proyecto para ser monitorizadas a través de Spring.

monitoring add class

Añade la monitorización a una clase determinada.

monitoring add method

Añade la monitorización de un método de una clase. Es posible que si se trata de una clase controlador y el método que deseamos monitorizar está incluido en el .aj no funcione, para solucionarlo bastará con hacer push-in del método previo a ejecutar el comando.

monitoring add package

Añade la monitorización a un paquete determinado.

A.15.1. monitoring setup

Instala las dependencias de JavaMelody además de configurar el proyecto con lo necesario para su funcionamiento.

Sus parámetros son:

--path

[Cadena] + Ruta de la carpeta donde se guardaran los datos de la monitorización dentro del servidor.

A.15.2. monitoring all

Establece todas las clases del proyecto para ser monitorizadas a través de Spring.

A.15.3. monitoring add class

Añade la monitorización a una clase determinada.

Sus parámetros son:

--name

[Requerido] [Cadena] + Ruta de la clase sobre la que se va a establecer la monitorización.

A.15.4. monitoring add method

Añade la monitorización de un método de una clase. Es posible que si se trata de una clase controlador y el método que deseamos monitorizar está incluido en el .aj no funcione, para solucionarlo bastará con hacer push-in del método previo a ejecutar el comando.

Sus parámetros son:

--name

[Requerido] [Cadena] + Nombre del método de la clase que se va a establecer la monitorización.

--class

[Requerido] [Cadena] + Ruta de la clase sobre cuyo método se va a establecer la monitorización.

A.15.5. monitoring add package

Añade la monitorización a un paquete determinado.

Sus parámetros son:

--path

[Requerido] [Cadena] + Ruta del paquete sobre cuyas clases se va a establecer la monitorización.

Appendix B: Desarrollo con eclipse

B.1. Instalación

Spring ha desarrollado una extensión para Eclipse llamada SpringSource Tool Suite o STS, que ofrece soporte para trabajar en Eclipse con aplicaciones de Spring, entre ellas Spring Roo y por tanto gvNIX. Entre otras funcionalidades incorpora un intérprete de comandos de Roo que permite ejecutar órdenes sin necesidad de salir de Eclipse.

Hay dos formas de instalar STS, la primera es como una distribución propia y la segunda es como un plugin de un Eclipse ya existente. Se recomienda encarecidamente utilizar la primera de ellas por su facilidad de instalación y mejor rendimiento.

B.1.1. STS como distribución

Para instalar el IDE como una distribución propia realizar los siguientes pasos:

  • Descargar la última versión de Springsource Tool Suite desde http://spring.io/tools

  • Descomprimir el archivo descargado y moverlo a una carpeta, por ejemplo $HOME/software.

  • Ejecutar STS ($HOME/software/springsource-X.X.X/sts-X.X.X.RELEASE/STS). Tener en cuenta que STS es una aplicación Java por lo que requiere tener una máquina virtual Java instalada en el sistema.

B.1.2. STS como plugin

Para instalar el IDE en un Eclipse existente seguir los siguientes pasos:

  • Si no se dispone todavía de él, descargar Eclipse IDE for Java EE Developers de http://www.eclipse.org/downloads/

  • Crear la variable de classpath de Eclipse M2_REPO, para ello:

    1. Window > Preferences > Java > Build Path > Classpath Variables, botón `New…​`.

    2. Definir los siguientes valores:

      • `Name` = `M2_REPO`.

      • `Path` = directorio correspondiente al repositorio de Maven (normalmente en Unix: $HOME/.m2/repository)

    3. Ok para crear la variable, y Ok de nuevo para cerrar la ventana de preferencias y guardar cambios.

  • Instalar plugin M2Eclipse para Eclipse (http://m2eclipse.sonatype.org/installing-m2eclipse.html)

    En el menú Help > Install New Software, en el campo de texto "Work with:" indicar que se usará el site: http://m2eclipse.sonatype.org/sites/m2e. A continución eleccionar "Maven Integration for Eclipse". Pulsar en siguiente y tras aceptar la licencia del plugin instalar.

  • Activa la opción `Enable Window > Preferences > General > Workspace > Refresh Automatically`.

  • Opcionalmente, instalar el plugin Subeclipse para trabajar sobre el sistema de control de versiones Subversion (SVN).

    Para ello en Eclipse, en el menú Help > Install New Software. En la ventana que se abre hacer click sobre el botón Add que hay a la derecha de Work with. Se abre un diálogo en el que se indicará como nombre Subeclipse por ejemplo y en la URL indicar http://subclipse.tigris.org/update_1.6.x guardar con OK y la ventana anterior empezará la carga de los plugins que hay disponibles. Seleccionarlos y seguir haciendo click en Next. La URL indicada es de la versión actual, revisar el sitio oficial de Subeclipse para más información y futuras versiones.

  • Para instalar el plugin STS seguir las instrucciones del punto "UPDATE SITE INSTALLATION" del documento Spring Source Tool Suite Installation Instructions.

B.1.3. Integrar soporte ROO en STS

Spring Roo ya no está incluido en la distribución de STS a partir de su versión 3.6.0, por ello necesitaremos instalar este soporte para poder trabajar con gvNIX.

Para incluir este soporte, sigue los siguientes pasos:

  1. Abre tu STS

  2. Abre el dashboard del STS y busca Spring ROO

  3. Instala Spring Roo (current production release) y Spring IDE - Roo Extension

  4. Reinicia tu STS

Integrando soporte ROO en STS

B.2. Consola gvNIX / Roo integrada en Eclipse

El plugin o distribución de STS instalado ofrece la posibilidad de incluir la consola de ROO en el propio entorno de desarrollo. Para ello antes hay que indicarle a Eclipse donde está instalada la nueva versión de ROO.

En el menú Window > Preferences > Spring > Roo Support. Pulsar sobre el botón Add y buscar en el navegador de archivos el lugar donde está instalado ROO. Aparecerá una pantalla similar a la siguiente:

Configuración del soporte gvNIX en Eclipse

Presionando en OK sobre las dos pantallas que abiertas ya estará configurado el soporte para la linea de comandos de ROO. Para poder usarlo abrir la perspectiva de Spring con Window > Open Perspective > Other > Spring. En la parte inferior de la pantalla aparecerá una pestaña llamada Roo Shell. Si no apareciese la pestaña, puede abrirse seleccionando Window > Show View > Roo Shell.

Para abrir la consola pulsar en el botón que aparece en la parte superior derecha de la pestaña con el título Open Roo Shell. Entonces seleccionar el proyecto en el que se va a trabajar y ya se puede empezar a ejecutar comandos. Si no se dispone todavía de ningún proyecto, en el punto siguiente se verá como crear un nuevo proyecto.

La ejecución de comandos también se puede hacer de forma gráfica pulsando en el botón que aparece en la parte superior derecha de la pestaña con el título Open Roo Command Wizard.

Consola gvNIX en Eclipse

Hay que tener en cuenta una pequeña diferencia a la hora de usar la línea de comandos desde Eclipse con respecto a la linea de comandos de gvNIX en la consola del sistema. Mientras en una consola del sistema se utiliza la tecla TAB para completar los comandos, en el IDE se utilizará Ctrl+Space que es el atajo por defecto usado en Eclipse.

B.3. Utilizar Eclipse como IDE

B.3.1. Crear proyecto gvNIX en Eclipse IDE

Crear un proyecto gvNIX desde Eclipse a través del menú: File > New > Spring Roo Project:

Nuevo proyecto Spring Roo con soporte gvNIX

Esta primera pantalla habrá ejecutado de forma automática el comando de creación de un nuevo proyecto:

project setup --topLevelPackage com.gvnix.tenminutes

En este punto ya se dispone de un proyecto Maven preparado.

A continuación, añadir el soporte para el manejo de la persistencia de datos a través de JPA. El siguiente ejemplo muestra los comandos que se deben usar para configurar el soporte JPA. Recordar que se puede usar Ctrl+Space como ayuda a la escritura en los comandos:

roo> jpa setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY
Created ...
roo> entity jpa --class ~.domain.Timer --testAutomatically
Created ...
~.domain.Timer roo> field string --fieldName message --notNull
Managed ...

El comando jpa setup permite configurar la capa de acceso a datos de manera sencilla. El comando entitiy jpa sirve para crear una nueva entidad y field crea atributos en la entidad. Estos comandos se verán con más detalle en la sección Persistencia de objetos y Crear una entidad con el intérprete de comandos, también se verá como generar todas las entidades de una aplicación mediante el proceso de ingeniería inversa contra un esquema de BBDD existente.

~.domain.Timer roo> web mvc setup
~.domain.Timer roo> web mvc all --package ~.web
Created ...

Los comandos web mvc crean la capa capa web que gestionaran la interacción del usuario con la aplicación. Se verán con más detalle en Crear la capa web con el intérprete de comandos.

~.web roo> selenium test --controller ~.web.Time
B.3.2. Importar proyecto gvNIX en Eclipse

gvNIX/Roo permite crear proyectos desde la linea de comandos, aunque puede suceder que se necesite importar un proyecto ya existente en el IDE. Si se está ejecutando gvNIX en la línea de comandos, bastaría con ejecutar el comando perform eclipse para crear una estructura de proyecto Eclipse:

~.domain.PizzaOrder roo> perform eclipse

Este comando termina ejecutando el comando del sistema`mvn eclipse:eclipse` en el proyecto, por lo que es indiferente el uso de cualquiera de los dos métodos. Tener en cuenta que este último comando necesita tener configurado Maven.

Ahora se puede importar en el entorno de trabajo mediante File > Import > General > Existing Projects into workSpace. Si aparece el mensaje Turn Weaving Service on?, marcar la casilla Don’t ask again until next upgrade y clic en Yes (será necesario reiniciar Eclipse).

También es posible borrar la configuración de eclipse ejecutando el comando mvn eclipse:clean en una consola del sistema que tenga configurada Maven. Para regenerar la configuración de eclipse en un solo comando usar mvn eclipse:clean eclipse:eclipse.

Al importar un proyecto en Eclipse es importante comprobar que dicho proyecto tiene configuradas las características de proyecto Maven y proyecto de aspectos java. Esto aparece de forma visual en el proyecto mediante unas pequeñas letras M y AJ. Si no apareciesen se pueden añadir estas características seleccionando el proyecto y con el segundo botón del ratón eligiendo la opción Configure. Esto es muy importante ya que en el caso de no estar correctamente configurado nos aparecerán falsos errores en el proyecto.

B.4. Generación de pruebas de integración

El comando entity jpa dispone de la opción testAutomatically que al ser especificada generará los test de integración para dicha entidad usando JUnit.

Si los tests no fueron creados en el momento de la ejecución del comando entity, pueden ser generados con posterioridad mediante otro comando:

roo> test integration --entity ~.domain.Timer

B.5. Arrancar la aplicación con Eclipse

Es posible arrancar la aplicación desde el propio Eclipse y, además de permitir depurarla, permite hacer cambios en caliente sobre la aplicación.

Para ello, debemos tener la aplicación importada en un workspace de Eclipse y configurar el servidor dónde ejecutarlo. Eclipse es capaz de gestionar distinto tipos de servidores, generando sus propios directorio y ficheros de configuración.

Para prepara un servidor seguir los siguiente pasos:

B.5.1. Mostrar la Vista de Servidores en Eclipse

Eclipse tiene una vista que permite ver los distintos servidores configurados y gestionarlos desde ahí. Estos son los pasos para mostrar la vista

  1. Abra la opción del menú Window > Show view > Other....

  2. Busque la vista llamada Servers y pulse el botón Ok.

B.5.2. Crear un nuevo Servidor

Se pueden definir múltiples entornos de ejecución para los servidores. Esta configuración incluye el tipo de servidor (Tomcat, Jetty, JBoss, etc..), Máquina Virtual Java (JRE 1.5, JRE 1.6, etc…​) y la ruta a los binarios del servidor.

Cabe destacar que eclipse no usa la configuración que exista en la instalación del servidor en la mayoría de los casos. Solo usa los ejecutables para arrancarlo con ficheros de configuración que almacena en el propio workspace.

En este caso, vamos a preparar el entorno para Tomcat 6 siguiendo los pasos indicados a continuación:

  1. Dentro de la pestaña Servers, pinchar con el segundo botón del ratón y seleccionar New > Server.

  2. Seleccionar Apache Tomcat v6.0 Server de la lista de tipos y pulsar el botón Next.

    En el caso en que no aparezca ningún tipo de servidor o no aparezcan los de Apache Tomcat se ha de realizar lo siguiente:

    • Ir a Help > Install New Software…​.

    • Desmarcar la casilla "Hide items that are already installed."

    • En "Work With" seleccionar el sitio "Eclipse Web Tools Platform Repository - http://download.eclipse.org/webtools/updates/" (si no aparece, añadirlo usando el botón Add…​.)

    • En el listado de software desplegar Web Tools Platform Tests (WST Tests) (si hay más de un WST Tests seleccionar el de la última versión).

    • Instalar (seleccionándolos) WST Server tests y JST Server Tests (si ya están instalado aparecerá su icono en gris)

  3. Introducir un nombre para la configuración.

  4. Seleccionar el directorio donde se encuentra una instalación de Tomcat 6. Si no se dispone de ninguna instalación de Tomcat 6 crear un nuevo directorio, seleccionarlo y pulsar sobre el botón Download and Install …​ que pasados unos segundos terminará la descarga y permitirá continuar.

  5. Seleccionar la máquina virtual Java con la que ejecutar el servidor.

  6. Pulsar el botón Next.

  7. Añadir las aplicaciones a ejecutar en este servidor de entre las disponibles.

B.5.3. Ajustar la configuración del Servidor

Puede ser necesario ajustar algunas opciones de la configuración del servidor. Para poder acceder a dichas opciones hay que seleccionar el servidor desde la pestaña de servidores y, con el botón derecho del ratón sobre él pulsar Open.

Desde el panel abierto podremos gestionar:

  • Datos generales del servidor.

  • Opciones de publicación y seguridad.

  • TimeOuts (muy útil si se está depurando algún proceso de arranque).

  • Puertos

  • Configuración de tipos MIME.

  • Las aplicaciones/modulos a lanzar (admite módulos externos).

  • Configuración de arranque del servidor.

    El servidor Tomcat arranca con cierta cantidad de memoria que no soportar mas de 4 cambios en el proyecto antes de llenarse y dejar de funcionar. Para evitar esto, se puede incrementar la cantidad de memoria con la que arranca Tomcat.

Es muy interesante modificar los parámetros de memoría con los que trabaja el servidor. Para ello:

  • En la pantalla de opciones de la configuración del servidor acceder a Open launch configuration

  • En la nueva ventana, en la pestaña Arguments añadir al final del texo que aparece en el apartado VM Arguments lo siguiente: -Xms64m -Xmx256m -XX:MaxPermSize=128m -XX:PermSize=128m

B.5.4. Ejecución de la aplicación en el Servidor

Una vez configurado el servidor, se podrá añadir a este la aplicación que se desea ejecutar en él. Se puede ejecutar más de una a la vez. En la vista Servers, pulsar con el botón derecho sobre el servidor deseado y seleccionar la opción Add and Remove …​. En el diálogo que se abre seleccionar de la lista de la izquierda la aplicación y pulsar el botón Add. Por último, cerrar el diálogo con Finish.

Añadir / Eliminar aplicaciones al Servidor

Ya es posible arrancar el servidor y probar la aplicación.

Vista de servidores disponibles en el workspace de Eclipse

En la imagen anterior se observa un servidor Tomcat 6 con la aplicación tenminutes disponible para ejecutar. Con los botones disponibles se puede arrancar la aplicación en modo debug, arrancar la aplicación de manera normal (botón verde con triángulo blanco en el centro), arrancar en modo profile, pararlo o re-publicar los cambios del proyecto en el servidor.

Botones de la vista servidores de Eclipse

Una vez arrancado el servidor se podrá navegar por la aplicación bien desde un navegador externo (Firefox) o bien desde un navegador propio que incorpora Eclipse accediendo a la dirección http://localhost:8080/tenminutes. Observar que el final de la dirección se corresponde con el nombre de la aplicación proporcionado al crear el proyecto. Para abrir el navegador interno de Eclipse utilizar Window > Show view > Internal Web Browser.

Navegador interno de Eclipse

Ejecutar la apliación desde Eclipse puede ser muy útil a la hora de hacer cambios en el proyecto, modificaciones en las vistas, en los objetos de aplicación, bien desde el propio IDE o desde la línea de comandos de gvNIX, ya que automáticamente se verán reflejados los cambios en el navegador.

B.6. Trabajando con el código de la aplicación en Eclipse

Al generar un proyecto con gvNIX/Roo habrá que trabajar sobre el código de la aplicación para añadir más funcionalidades y/o modificar alguna de las que se han generado. A continuación se explicarán un par de detalles que simplificaran esta tarea usando Eclipse y el plugin STS instalado.

Vista de editor y Cross References en Eclipse

En la imagen anterior se observa el editor de Eclipse con el archivo Timer.java que se ha generado al ejecutar los comandos entity y field anteriores. En la parte derecha de la captura se ve una ventana que muestra información de la clase Timer. Se trata de la vista Cross Reference. Si no está disponible en la perspectiva de trabajo, se puede incorporar desde el menú Window > Show view > Cross References. Esta vista es similar a la vista Outline que muestra los campos y métodos declarados en una clase.

La particularidad de la vista Cross References es que muestra los campos y métodos asociados a la clase Java mediante aspectos java que se verán en el Cápitulo sobre el código que genera gvNIX/Roo.

Esta información también está disponible desde un menú contextual accesible haciendo click con el botón derecho sobre la flecha que hay a la izquierda de la declaración de la clase. El menú contextual es el siguiente.

Contextual Cross References

Haciendo click sobre una de las entradas que aparecen en la ventana Cross References o en el menú contextual, se abrirá el fichero .aj que tiene declarado ese campo o método. Por ejemplo, si se accede al método Timer.toString() se abrirá el editor con el archivo Timer_Roo_ToString.aj.

Cabe destacar que para que aparezca esta información sobre el código asociado a una clase Java mediante aspectos java, la clase debe estar libre de errores de compilación.

B.6.1. Modificación del código generado

Como se ha comentado, seguramente será necesario añadir nuevas funcionalidades o modificar algunas de las que se han generado automáticamente para adaptar el código a los requisitos de la aplicación. En estos casos hay que tener en cuenta que no se debe hacer ningún cambio sobre los aspectos java (ficheros aj) asociados a una clase Java. gvNIX/Roo ya nos lo avisa en la primera línea del archivo .aj. El motivo de esto es, que teniendo la consola gvNIX funcionando, o al arrancar, gvNIX/Roo volvería a generar el código automáticamente perdiendo las modificaciones que hubiésemos realizado.

Edición archivo Timer_Roo_ToString.aj

Para modificar el código de un método o la declaración de un campo que se encuentre en un aspecto java, se puede mover el método o el campo a la clase Java, del que depende el aspecto java. En el ejemplo, se movería a la clase Timer.java. Puede realizarse cortando y pegando, pero Eclipse con el plugin STS ofrece una opción mucho más adecuada para esto.

Seleccionando el nombre del método a mover y a través del menú contextual AspectJ Refactoring > Push In …​ Eclipse se ocupará de eliminar el código del .aj y moverlo al .java.

Menú contextual AspecJ Refactoring

Una vez en el .java, se podrá hacer cuantas modificaciones se necesiten sin peligro de que se pierdan por la acción de gvNIX/Roo.

Del mismo modo, si se necesita añadir nuevos métodos o campos a la clase Java, se debe hacer directamente en el .java.

Es interesante tener abierta la consola gvNIX para que los cambios realizados sobre los ficheros del proyecto disparen los cambios automáticos que realiza gvNIX/Roo.

Appendix C: Recetas

En este capítulo se verá como realizar algunas modificaciones sobre el código generado para adaptar la aplicación a distintos requerimientos habituales dada la experiencia de uso del framework.

C.1. Repositorios Maven

Cuando una funcionalidad generada por el framework requiere de librerías externas, el add-on correspondiente registrará el repositorio de artefactos Maven necesario en el fichero pom.xml, si todavía no lo estaba.

No es habitual, pero en el caso de ser necesario añadir algún repositorio adicional al proyecto puede realizarse mediante el comando de la consola maven repository add. El siguiente ejemplo define el repositorio Maven interno de la Conselleria de Infraestructuras, Transporte y Medio Ambiente. Este repositorio es accesible únicamente desde la red interna de la Conselleria.

roo> maven repository add --id citma-maven --name "CITMA Maven Repository"
        --url http://benigno.coput.gva.es:8081/nexus/content/groups/public
Updated ROOT/pom.xml [
        added repository http://benigno.coput.gva.es:8081/nexus/content/groups/public]

El comando modificará el fichero pom.xml y en la sección <repositories> añadirá la definición del repositorio indicado.

<repositories>
    ...
    <repository>
        <id>citma-maven</id>
        <url>http://benigno.coput.gva.es:8081/nexus/content/groups/public</url>
        <name>CITMA Maven Repository</name>
    </repository>
    ...
</repositories>

En el lado opuesto, también es posible eliminar repositorios Maven del proyecto mediante el comando maven repository remove.

C.2. Desarrollo de buscadores con gran cantidad de campos

El add-on de los buscadores (finder) tiene una limitación impuesta por el sistema operativo Windows en el tamaño máximo del nombre de archivos. La limitación del tamaño máximo del nombre de archivo limita al comando finder add a generar nombres de buscadores que generen paths a archivos jspx de tamaño menor de 244 caracteres.

Existe una forma para generar buscadores con un tamaño superior al de la limitación impuesta. Consiste en dividir el buscador necesario en varios más pequeños, parciales de unos pocos campos cada uno, y al final unir el código que se genera para cada uno de ellos en un unico método. Esto implica tener que modificar el código que se ha generado para el buscador en la entidad, el controlador y la jspx de la siguiente forma:

  • En el archivo Java de la entidad para la que se está generando el buscador crear un método con el nombre, por ejemplo, findByTodo y cuyos parámetros de entrada serán todos los parámetros que reciben los métodos de los buscadores parciales que se hayan generado. Del mismo modo, el cuerpo de este nuevo método es la unión de la implementación de todos los buscadores parciales. Es posible modificar el código, según se explica en el siguiente apartado, de forma que los parámetros sean opcionales.

  • De manera similar, en el fichero Java del controlador de la entidad crear dos métodos: uno findByTodoForm que devolverá la vista del formulario del buscador y otro findByTodo que responderá a las peticiones que lleguen desde el formulario del buscador. Este segundo método, al igual que en el método creado en la entidad, deberá tener como parámetros la unión de todos parámetros de los métodos de los buscadores parciales en el controlador. El cuerpo de este método deberá invocar al método findByTodo creado en la entidad. Para definir la anotación @RequestMapping de estos dos métodos se recomienda utilizar como guía los buscadores parciales ya existentes.

  • Finalmente, crear una página jspx (por ejemplo, con nombre findByTodo.jspx) en el directorio WEB-INF/views/<entidad> que contendrá el formulario del buscador. Esta página debe incluir todos los campos que hayan en el resto de páginas jspx de los buscadores parciales. Recordar, que esta vista se ha de definir también en el fichero views.xml que hay en la misma carpeta y que esta vista es la que devuelve el método findByTodoForm creada anteriormente en el controlador.

Con todo lo anterior se ha descrito un proceso manual que permite montar buscadores con cualquier cantidad de campos.

C.3. Campos opcionales en los buscadores

El comportamiento que implementa automáticamente la generación de buscadores es hacer todos los campos de busqueda obligatorios. Por lo tanto, si no se proporciona alguno de los parámetros se generará una excepción indicando la falta de un parámetro obligatorio. En ocasiones no es lo deseado, es decir, puede necesario que los parámetros no informados simplemente no se incluyan en la consulta si no se especifican. Para ello se debe modificar el código del método finderByXxxx declarado en el aspecto Java *_Roo_Finder.aj. A continuación se ejemplifica como hacer este cambio.

Hacer push-in del método tal y como se comenta en la sección sobre modificación del código generado y llevarlo al fichero Java de la entidad. Una vez allí modificarlo para que no requiera los campos y así construir la consulta considerando tan solo los parámetros que lleguen informados:

public static TypedQuery<Owner> findOwnersByLastNameLikeAndCityLike(
            String lastName, String city) {




    lastName = lastName.replace('*', '%');
    if (lastName.charAt(0) != '%') {
        lastName = "%" + lastName;
    }
    if (lastName.charAt(lastName.length() - 1) != '%') {
        lastName = lastName + "%";
    }

  }


    city = city.replace('*', '%');
    if (city.charAt(0) != '%') {
        city = "%" + city;
    }
    if (city.charAt(city.length() - 1) != '%') {
        city = city + "%";
    }

  }


  EntityManager em = Owner.entityManager();
  TypedQuery<Owner> q = em.createQuery(, Owner.class);

    q.setParameter("lastName", lastName);
  }

    q.setParameter("city", city);
  }
  return q;
}

Se han marcado en negrita las líneas de código modificadas. Como puede observarse, se construye la consulta de forma dinámica de forma que se añaden los distintos filtros al where de la consulta solo si el campo asociado al filtro tiene algún valor y se elimina la generación de excepciones al detectar alguno de dichos campos como vacío.

En este ejemplo se ha construido la consulta usando un StringBuilder en el que se genera la consulta deseada, pero se podría utilizar cualquier otra tecnología como por ejemplo Hibernate Criteria Builder.

Como ya se ha comentado, el código generado fuerza que todos los parámetros de búsqueda sean obligatorios, esto implica también al formulario situadao en la página jspx. Tal como se genera, si alguno de los campos no se rellena, no dejará enviar la petición. Se debe editar la jspx y modificar el atributo required de los campos field y establecer su valor a false, no olvidar cambiar el valor del atributo z a "user-managed" para indicar que este campo ha sido personalizado.

<field:input disableFormBinding="true" field="city"
            id="f_com_springsource_petclinic_domain_Owner_city" max="30" />

En los buscadores en los que uno de los parámetros sea una entidad del modelo, es decir una relación con otra entidad del modelo, será necesario realizar un cambio adicional. En estos casos se visualiza un selector desplegable, mediante el componente select.tagx. Sin embargo, este selector tiene el inconveniente de que no incluye una opción vacía entre las disponibles, con lo que obliga a elegir siempre algún valor. Un ejemplo de este caso se encuentra en el buscador findPetsByOwner generado para la entidad Pet en el ejemplo de clinic.roo .

La forma de tratar estas peticiones en Spring MVC es intentar cargar el registro asociado con el valor del selector que llega como parámetro. Por tanto si llega como parámetro un dato que no concuerda con ningún registro de la entidad parámetro, usará null como valor. Como se ha comentado, el componente select.tagx no ofrece una opción vacía.

C.4. Instalar fuentes de letra para los informes

Las fuentes instaladas automáticamente proporcionan soporte para la inclusión de texto en negrita y cursiva. El desarrollador debe instalar cualquier otro tipo de fuente que se utilice en los informes que diseñe. Para ello, basta con ampliar las definiciones fontFamily realizadas en el archivo gvnix_reportfonts.xml y copiar los archivos de fuente en la carpeta jasperfonts. La inclusión de nuevas fuentes se puede realizar utilizando una utilidad que ofrece iReport. Desde el menú Herramientas > Opciones > Pestaña Fonts se accederá a la siguiente pantalla:

Herramienta de gestión de fuentes de IReport

Desde esta pantalla, seleccionando una fuente de la lista de fuentes instaladas en iReports y con el botón "Export as extension" se creará un archivo JAR que al descomprimirlo contiene:

  • Directorio fonts

    • Archivos de fuentes en formato TTF.

    • Archivo fontsfamily<IdentificadorAleatorio>.xml

  • Archivo jasperreports_extension.properties

Para instalar esta fuente en la aplicación se deben copiar los ficheros con extensión TTF a /WEB-INF/classes/jasperfonts y del archivo fontsfamily<IdentificadorAleatorio>.xml adaptar el elemento <fontFamily/> para copiarlo en el archivo del proyecto gvnix_reportfonts.xml (modificando las rutas para que apunten a jasperfonts). El archivo jasperreports_extension.properties se puede ignorar porque ya se encuentra definido en el proyecto en /WEB-INF/classes.

C.5. Diseño de informes con sub informes

gvNIX mediante el Add-on Web Report facilita la creación de informes sobre una entidad. El add-on genera el diseño de un informe Jasper Reports básico el cual se puede modificar utilizando un diseñador gráfico como iReport.

Puede ser necesario mostrar en un informe una lista de entidades relacionadas con la entidad sobre la que se ha generado el informe. Por ejemplo, en la aplicación del script de ejemplo clinic.roo, se podría definir un informe sobre la entidad Owner y desear mostrar para cada Owner la lista de mascotas que le pertenecen, es decir, listar la relación definida por el campo Set<Pet> pets de la entidad Owner.

Para este ejemplo se utilizará la versión 4.0.1 de iReport.

Partiendo del informe definido por el siguiente comando de gvNIX:

roo> web report add --controller ~.web.OwnerController --reportName ownerpets

En src/main/webapp/WEB-INF/reports se creará el archivo con el diseño del informe owner_ownerpets.jrxml. Abriendo este archivo usando iReport (Archivo > Open) aparecerá una pantalla como la que se muestra a continuación.

iReport - Diseñador

En la parte izquierda, en la pestaña con título Report Inspector se pueden observar los elementos principales del diseño de informes.

iReport - Report Inspector

Lo primero que se debe hacer es declarar un nuevo parámetro con, por ejemplo, el nombre SubReportPetsLocation. Para ello hacer click con el botón derecho sobre el elemento Parameters y seleccionar la opción Agregar Parameter. Justo debajo del último parámetro aparecerá uno nuevo con nombre parameter1. Al seleccionarlo, en la parte derecha de la ventana de iReport se podrán ver sus propiedades. Modificar sus propiedades estableciendo en la propiedad_Name_ el valor SubReportPetsLocation y en la propiedad Parameter Class el valor net.sf.jasperreports.engine.JasperReport.

A continuación, añadir un elemento Subreport al diseño. Para que aparezca el Subreport para cada elemento de la lista de Owners, se debe añadir en la banda de detalle Detail1 del informe. Será necesario aumentar la altura de la banda Detail1. Para ello, seleccionarla y en sus propiedad Band height especificar el valor 55. De la paleta de elementos seleccionar el Subreport y arrastrarlo a la banda de detalle. Se abrirá un asistente, seleccionar la opción Just create the subreport element y cerrar con Terminar. Es posible modificar las dimensiones del elemento Subreport arrastrando las esquinas de la caja del elemento.

iReport - Subreport

Antes de seguir con el establecimiento de las propiedades del Subreport, es necesario declarar un campo del informe que permitirá acceder al campo pets de la Entidad Owner. En Report Inspector, seleccionar Fields y con el botón derecho Agregar Field. Modificar también este elemento estableciendo en la propiedad Name el valor pets y en la propiedad Field Class el valor java.util.Collection.

Se debe indicar cuales son las propiedades del Subreport. Para ello, en la ventana de propiedades de la derecha buscar las siguientes propiedades y establecer los valores que se especifican a continuación:

  1. Subreport Expression = $P{SubReportPetsLocation}

  2. Expression Class = net.sf.jasperreports.engine.JasperReport

  3. Connection type = Use a datasource expression

  4. Data Source Expression = new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{pets})

En el flujo de ejecución de un informe en Jasper Reports, los parámetros del mismo han de ser informados antes de su visualización o, de lo contrario, se tomarán los valores por defecto que se hubiesen definido o null en su defecto. Observar que se ha definido el parámetro SubReportPetsLocation y el valor que toma este parámetro en tiempo de ejecución ha de ser una ruta absoluta al sistema de archivos o al classpath de la aplicación.

En la sección del Add-on Web Report se explicó que al añadir un informe a la aplicación, utilizando el comando 'web report add', en el archivo 'src/main/webapp/WEB-INF/spring/jasper-views.xml' se declara un bean que establece la ruta hasta el fichero jrxml del informe añadido. Este bean tiene un atributo que indica el lugar donde se declaran los subreports que se usan en los distintos informes mediante el atributo 'p:subReportsUrls-ref'.

<bean id="owner_ownerpets"
class=
 "com.springsource.petclinic.web.servlet.view.jasperreports.CustomJasperReportsMultiFormatView"
p:reportDataKey="ownerpetsList" p:url="/WEB-INF/reports/owner_ownerpets.jrxml"
p:subReportDataKeys-ref="subReportDataKeys"  />

El elemento anterior marcado en negrita apunta al elemento <util:map/>, declarado también en el fichero jasper-views.xml. Aquí se ha de especificar el valor que debe tomar el parámetro SubReportPetsLocation. Modificar este elemento añadiendo una entrada, quedando como se muestra a continuación.

<util:map id="">
  <!-- This entry key must be declared exactly as declared in the master JRXML file -->
  <!-- Add one <entry /> node for each sub-report you need to define -->

</util:map>

En el elemento <util:map/> se pueden definir tantos elementos <entry/> como sea necesario para definir los parámetros que indican el lugar donde se localizan los archivos jrxml de los distintos subreports.

Ahora se debe diseñar el informe que mostrará el listado de mascotas (pets) que conformará el subreport.

Crear un nuevo diseño de informe (Archivo > Nuevo), y en el asistente seleccionar Blank A4 y Open This Template. Se solicitará un nombre para el diseño y el lugar donde guardarlo. Indicar, por ejemplo owner_ownerpets_sub_pets.jrxml y guardarlo en el mismo directorio donde se encuentre el report padre (owner_ownerpets.jrxml).

iReport - Nuevo diseño

Se debe validar que el nuevo informe se crea con el lenguage Java configurado para las expresiones. En Report Inspector, al seleccionar el primer elemento (el nombre del informe) y mirar en sus propiedades (parte derecha de la pantalla de iReport) se debe buscar la propiedad Language, si no tiene el valor Java, cambiarla usando el desplegable.

Este nuevo informe, que constituirá el subreport, es un informe a todos los efectos, por tanto se debe definir los campos (elemento Fields del diseño), parámetros (elemento Parameters), etc.

Al igual que se ha hecho anteriormente con el campo pets del informe padre, definir los campos que permiten acceder a los valores de la entidad Pet que se visualizarán en el subreport. Click con el botón derecho sobre Fields y Agregar Field:

  1. Crear field con nombre name y clase java.lang.String

  2. Crear field con nombre weight y clase java.lang.Float

  3. Crear field con nombre type y clase com.springsource.petclinic.reference.PetType (enumerado declarado en el proyecto clinic.roo)

El diseño del informe se compone de distitnas bandas, donde se colocan los elementos a mostrar (Title, Page Header, Column Header, Detail1, Column Footer, …​). Para un subreport como el de este ejemplo, algunas bandas son innecesarias y pueden ser eliminadas. Esto permitirá ajustar mejor el diseño completo del informe (informe padre ownerpets
subreport pets). Si se hace click con el botón derecho sobre Title y se selecciona Delete Band, es eliminada. Hacerlo con todas las bandas excepto con Column Header, Detail1 y Summary.

iReport - Bandas subreport

Column Header es una banda que se dibujará solo al inicio de la columna del informe (en este caso solo existirá una). Añadir textos estáticos que harán las veces de cabecera de tabla. Para ello, de la paleta de componentes, seleccionar Static Text y arrastrarlo hasta la banda Column Header.

iReport - Paleta

En el primer Static Text establecer el valor Nombre y repetir la misma operación para definir un texto para el campo Peso y para el campo Tipo. Es posible distribuir las etiquetas para que quede tal y como se muestra en la captura anterior.

A continuación, hacer lo mismo pero usando el elemento Text Field. Este elemento sirve para mostrar el valor de un campo de la entidad Pet y se ha de corresponder con los field definidos anteriormente (name, weight, type). Estos elementos Text Field se definirán en la banda Detail1, puesto que se repetirán para cada uno de los elementos de la fuente de datos del subreport. Recordar que la fuente de datos de este subreport se había definido anteriormente como JRBeanCollectionDataSource usando la colección de Pets que pertenecen a un Owner.

En los Text Field, es importante establecer correctamente la propiedad Expression Class, esta se ha de corresponder con el tipo Java del field definido y que se va a usar para mostrarlo. Por ejemplo, el Text Field que mostará el peso de la mascota tendría las propiedades como sigue:

  • Text Field Expression = $F{weight}

  • Expression Class = java.lang.Float

Para establecer el Text Field Expression se puede utilizar el diálogo que se muestra a continuación Este diálogo permite seleccionar elementos de los campos definidos en el informe, de los parámetros e incluso acceder a alguna de las operaciones que proporcionan estos objetos.

iReport - Diálogo Text Field Expression

Obviamente, en un Text Field es posible establecer expresiones más elaboradas, como añadir a la cadena las unidades de peso. Se debe tener en cuenta que la propiedad Expression Class deberá establecerse al tipo Java resultante de la expresión (por ejemplo, $F{weight} + "kg" da como resultado un java.lang.String). Establecer en el Text Field asociado con el tipo de mascota la expresión $F{type}.toString() y la clase java.lang.String.

Ya está diseñada la banda de detalle y para terminar el subreport, opcionalmente, se puede definir un Text Field que indique cuantos registros de Pet se han impreso cada vez que se ejecuta el subreport. Esto ya se encuentra incluido en el informe padre (owners) y se consigue utilizando la variable del report REPORT_COUNT, ya difinida por defecto. Incluirla en la banda Summary con un Text Field en la que el Expression tome el valor $V{REPORT_COUNT} y el Class sea java.lang.Integer.

Solo queda arrancar de nuevo la aplicación, desde el Tomcat de Eclipse o desde la línea de comandos y probar la generación del informe de Owners.

Informe Owners con subreport Pets

JasperReports permite gran cantidad de opciones al trabajar con subreports (paso de parámetros desde el informe padre a los subinformes, devolución de parámetros desde los subinformes al informe padre, actualización de variables, …​). Para conocerlas con profundidad consultar la documentación de referencia de Jasper Reports e iReport.

C.6. Operaciones durante el inicio de la aplicación

Se pueden crear clases que se invoquen durante la inicialización de una aplicación.

En alguna aplicación puede ser necesario realizar alguna acción durante el inicio de una aplicación, como por ejemplo. Existen diversas formas para hacer esto en Spring.

Sino se va a interaccionar con datos, se puede usar la anotación @PostConstruct en un método de una clase anotada con @Component. Hay que tener en cuenta que la inicialización del soporte de datos y transacciones puede no estar todavía listo en este punto.

Crear un listener del contexto de Spring de la siguiente forma:

@Component
  public class DataSeeder implements ApplicationListener<ContextRefreshedEvent> {

    @Override
        @Transactional
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (Model.countModels() == 0) {
            // Create initial Model values
        }
    }

C.7. Obtener el BindStatus de un atributo dentro de un formulario

Obtener el BindStatus de un atributo dentro de un formulario:

<spring:bind path="${field}">
        <c:set var="fieldValue" value="${status.value}" />
    </spring:bind>

Appendix D: Código generado por gvNIX/Roo

D.1. Clases Java y ficheros AJ

D.1.1. Archivos Java

Por lo general, la norma que se sigue es mantener la clase Java, el archivo .java, lo más sencillo posible y por ello, muchas veces, se puede observar que el archivo .java está prácticamente vacio. Contiene poco más que la declaración de la clase y anotaciones asociadas a la misma. El resto del código, campos y métodos se declaran en sus aspectos java de los que se hablará a continuación.

D.1.2. Archivos AJ

Estos son los ficheros que genera automáticamente el framework y que contienen las operaciones básicas, los campos definidos con sus getter y setter, el identificador, etc. En general contine el código que un programador haria de manera rutinaria. Estos ficheros tienen nombres como Roo.aj y gvNIX.aj. Se trata de aspectos java que no son más que porciones de código que al compilar el proyecto, se asocian como código de la propia clase Java a la que están vinculadas. Si se desea personalizar alguna de las operaciones básicas, un getter determinado o añadir nuevas funcionalidades, estas deberán realizarse en los ficheros .java. En los ficheros aj no se debe de hacer ningún cambio. El motivo de esto es, que teniendo la consola funcionando, o al arrancarla, se volvería a generar el código automáticamente perdiendo las modificaciones que se hubiesen realizado. Y al contrario si en el fichero .java se ha creado el getter personalizandolo, automáticamente lo borrara del fichero .aj.

Appendix E: Mejoras de rendimiento

E.1. Descripción

En las aplicaciones generadas en algún caso pueden requerir la implementación de alguna pequeña mejora para mejorar su rendimiento.

Las mejoras de rendimiento no serán siempre necesarias ya que dependen de las características de la aplicación en desarrollo.

E.2. Patrones de conversión óptimos en el log

Se puede mejorar el rendimiento del sistema de log (log4j) evitando que se muestre información innecesaria. Para ello modificar el fichero src/main/resources/log4j.properties modificando el ConversionPattern del appender que esté utilizando la aplicación, por ejemplo log4j.appender.stdout.layout.ConversionPattern=.

El ConversionPattern adecuado depende del entorno en el que nos encontremos. Será interesante disponer de mayor información en el log en entornos de desarrollo aunque se reduzca algo el rendimiento y ofrecer una menor información en los logs en entornos productivos. A continuación se recomiendan unos valores adecuados para cada tipo de entorno:

Entornos de desarrollo e integración: %d{dd/MM/yyyy HH:mm:ss.SSS} [%t] %p %c{1}.%M(%L) | %m%n
Entornos de preproducción y producción: %d{dd/MM/yyyy HH:mm:ss.SSS} [%t] %p %c{1} | %m%n

Los distintos valores en función del entorno se pueden establecer de forma automática mediante el add-on de configuración dinámica.

E.3. Evitar la carga de listas de valores innecesarias

Las vistas (páginas jspx) y los controladores (clases Java) son generadas con toda la información necesaria para que funcionen todas las acciones de listado, creación, actualización, borrado, búsqueda, etc. sobre una entidad.

En algunos casos, estas pantallas son personalizadas para ocultar campos que no son necesarios. Esto es especialmente importante en el caso de las relaciones con otras entidades y que se representan en página como campos desplegables.

        ... field="propertyname" render="false" ...

En dicho caso es recomendable evitar que se carguen las listas de datos que no se van a utilizar ya que realizan consultas a la base de datos innecesarias. Para ello, se puede personalizar los métodos del controlador llamados populate y comentar aquellas líneas relacionadas con el campo que se ha ocultado.

        void populateEditForm(Model uiModel, Entity entity) {
        ...
        uiModel.addAttribute("propertyname", OtherEntity.findAllOtherEntities());
        ...
        }

IV. Recursos

1.1. Recursos

En este apartado pondremos una lista de recursos de documentación, tutoriales, etc que pueden ser útiles.

1.1.1. Proyecto gvNIX

1.1.3. Proyectos relacionados con gvNIX

Proyectos relacionados con gvNIX y con la Conselleria de Infraestructuras, Transporte y Medio Ambiente de la Generalitat Valenciana.

1.1.5. Recursos de librerías relacionadas

Enlaces a recursos de librerías relacionadas con los proyectos generados.