Spring WebFlow con Validator

0
19790

Spring WebFlow con Validator

En el tutorial “Manual Básico
de Spring WebFlow” hemos visto cómo poner a funcionar
este maravilloso controlador. Cuando comenzamos a desarrollar una
aplicación, descubrimos inmediatamente que la interfaz de
usuario involucra validaciones básicas de los datos que
introduce el usuario. Habitualmente utilizamos validaciones
específicas en las acciones del controlador o en componentes
especializados pero a medida que crece la complejidad de la
aplicación esta solución no es escalable ni mantenible.
Surgen entonces propuestas como Apache Validator donde mediante uno o
más ficheros de configuración se definen las reglas de
validación y la aplicación de dichas reglas a los
campos de los formularios.

El objetivo de este tutorial es
facilitar el primer contacto con esta tecnología partiendo del
ejemplo realizado en el tutorial “Manual Básico de
Spring WebFlow” analizar su aplicabilidad, recomendar algunos
links y comentaros nuestras conclusiones.

Preparación del proyecto

Comenzaremos a partir del proyecto que creamos en el ejemplo
realizado en el tutorial “Manual Básico de Spring
WebFlow”.

Lo primero que haremos será descargarnos el spring modules
http://projects.spring.io/spring-webflow/
seleccionando Releases y la última disponible:

Y la versión del fichero sin dependencias:

Entonces, abrimos el zip

y copiamos el spring-modules-validation.jar en nuestra carpeta
/WEB-INF/lib del proyecto.

Configurando la aplicación

Abrimos el fichero pruebaWebFlowSimple-servlet-config.xml y
añadimos las siguientes definiciones:

<bean
id=«messageSource»

class=«org.springframework.context.support.ResourceBundleMessageSource»>

<property
name=«alwaysUseMessageFormat»
value=«true»
/>

<property
name=«basenames»>

<list>

<value>messages</value>

</list>

</property>

</bean>

<bean
id=«validatorFactory»

class=«org.springmodules.validation.commons.DefaultValidatorFactory»>

<property
name=«validationConfigLocations»>

<list>

<value>/WEB-INF/validations/validator-rules.xml</value>

<value>/WEB-INF/validations/validation.xml</value>

</list>

</property>

</bean>

Primero definimos un messageSource
con el que se resolverá la internacionalización de la
aplicación. Luego se declara el factory del validador y
configurándolo con un fichero de definición de reglas y
otro de definición de la aplicación de dichas reglas a
un formulario. También vamos a modificar la definición
del formAction en /web/WEB-INF/flows/asistente-beans.xml para
incluirle el validador (resaltado en negrita):

<beans
xmlns=«http://www.springframework.org/schema/beans»

xmlns:xsi=«http://www.w3.org/2001/XMLSchema-instance»

xsi:schemaLocation=«http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd»>

<bean
id=«formAction»

class=«es.autentia.tutoriales.manualBasicoSpringWebFlow.controller.action.AsistenteAction»>

<property
name=«formObjectScope»
value=«FLOW»
/>

<property
name=«formObjectName»
value=«form»
/>

<property
name=«formObjectClass»

value=«es.autentia.tutoriales.manualBasicoSpringWebFlow.controller.form.AsistenteForm»
/>

<property
name=«validator»
ref=«formActionValidator»/>

</bean>

<bean
id=«formActionValidator»
class=«org.springmodules.validation.commons.ConfigurablePageBeanValidator»>

<property
name=«formName»
value=«formAction»
/>

<property
name=«validatorFactory»
ref=«validatorFactory»
/>

</bean>

</beans>

Vamos a crear los ficheros /WEB-INF/validator-rules.xml
y /WEB-INF/validation.xml.Para
hacerlo sencillo copiaremos los que vienen en el ejemplo
spring-modules-validation-commons-samples-src.zip que viene en
spring-modules-0.8.zip y que encontraremos en
\spring-modules-0.8\samples\sources\spring-modules-validation-bean-samples-src.zip.
Los encontraremos en la carpeta \webapp\WEB-INF\.

Analicemos un fragmento de validator-rules.xml:

<form-validation>

<global>

<validator
name=»required»

classname=»org.springmodules.validation.commons.FieldChecks»

method=»validateRequired»

methodParams=»java.lang.Object,

org.apache.commons.validator.ValidatorAction,

org.apache.commons.validator.Field,

org.springframework.validation.Errors»

msg=»errors.required»>

<javascript><![CDATA[

En dicho fichero se define bastante intuitivamente cada regla de
validación. Commons validation incluye una serie de reglas
predefinidas pero podemos desarrollar fácilmente las nuestras
(será parte de un futuro tutorial). Básicamente
indicamos su nombre, clase, nombre y parámetro del método
que implementa dicha validación y finalmente se puede incluir
un javascript que realizará dicha valdación en cliente.
Esto último requiere que incluyamos unas taglibs en las jsps
del formulario.

Aprovecharemos el validation.xml del ejemplo para definir el que
utilizaremos en el proyecto:

<?xml
version=«1.0»
encoding=«UTF-8»?>

<!DOCTYPE
form-validation PUBLIC

«-//Apache
Software Foundation//DTD Commons Validator Rules Configuration
1.1//EN»

«http://jakarta.apache.org/commons/dtds/validator_1_1.dtd»>

<form-validation>

<formset>

<form
name=«asistenteForm»>

<field
property=«numero1»
depends=«required,integer,intRange»>

<arg
position=«0»
key=«asistente.numero1.etiqueta»
/>

<arg
position=«1»
name=«intRange»
key=«${var:min}»

resource=«false»
/>

<arg
position=«2»
name=«intRange»
key=«${var:max}»

resource=«false»
/>

<var>

<var-name>min</var-name>

<var-value>1</var-value>

</var>

<var>

<var-name>max</var-name>

<var-value>20</var-value>

</var>

</field>

<field
property=«numero2»
depends=«required,integer,intRange»>

<arg
position=«0»
key=«asistente.numero2.etiqueta»
/>

<arg
position=«1»
name=«intRange»
key=«${var:min}»

resource=«false»
/>

<arg
position=«2»
name=«intRange»
key=«${var:max}»

resource=«false»
/>

<var>

<var-name>min</var-name>

<var-value>1</var-value>

</var>

<var>

<var-name>max</var-name>

<var-value>20</var-value>

</var>

</field>

</form>

</formset>

</form-validation>

Ahora creamos el messages.properties en la carpeta src y copiamos
las claves necesarias:

asistente.numero1.etiqueta=Primer
número

asistente.numero2.etiqueta=Segundo
número

#
Struts Validator Error Messages

errors.required={0}
es obligatorio.

errors.minlength={0}
no debe ser
menor a {1}
caracteres.

errors.maxlength={0}
no debe ser
mayor a {1}
caracteres.

errors.invalid={0}
es invalido.

errors.byte={0}
debe ser un
byte.

errors.short={0}
debe ser un
short.

errors.integer={0}
debe ser un
integer.

errors.long={0}
debe ser un
long.

errors.float={0}
debe ser un
float.

errors.double={0}
debe ser un
double.

errors.date={0}
no es una
fecha válida.

errors.range={0}
no está
entre {1}
y {2}.

errors.creditcard={0}
no es un
número de
tarjeta de
crédito válido.

errors.email={0}
no es una
dirección de
e-mail válida.

Para poder apreciar mejor la validación, vamos a comentar
las validaciones que se realizan en el AsistenteAction.java, dejando
como resultado siempre success:

public
Event validarPaso1YPrepararPaso2(RequestContext context)

throws
Exception {

AsistenteForm
form = (AsistenteForm) getFormObject(context);

Event
resultado = success();

//
if (form.getNumero1() < 0 || form.getNumero2() < 0) {

//
form.setMensaje(«Los números a sumar deben ser
positivos»);

//
resultado = error();

//
} else {

//
form.setMensaje(«El resultado de la suma es «

//
+ (form.getNumero1() + form.getNumero2()));

//
resultado = success();

//
}

return
resultado;

}

Para que podamos visualizar los mensajes de error, vamos a incluir
en /web/WEB-INF/jsp/paso1.jsp el siguiente código (resaltado
en negrita):

<%@
taglib
uri=«http://www.springframework.org/tags»
prefix=«spring»%>

<%@
taglib prefix=«c»
uri=«http://java.sun.com/jsp/jstl/core»%>

<html
xmlns=«http://www.w3.org/1999/xhtml»
xml:lang=«en»
lang=«en»>

<head>

<title>Asistente
sumador
</title>

</head>

<body>

<h1>Asistente
sumador: Paso 1
</h1>

<spring:hasBindErrors
name=«asistenteForm»>

<h2>Solucione
los siguientes errores
</h2>

<ul>

<c:forEach
var=«error»
items=«${errors.allErrors}«>

<li>

<spring:message
code=«${error.code}«
arguments=«${error.arguments}«/>

</li>

</c:forEach>

</ul>

</spring:hasBindErrors>

<form>

<input
type=«hidden»
name=«_flowId»
value=«asistente-flow»
/>

<input
type=«hidden»
name=«_eventId»
value=«siguiente»
/>

<input
type=«hidden»
name=«_flowExecutionKey»
value=«${flowExecutionKey}«
/>

<p>${asistenteForm.mensaje}</p>

<p>Primer
número:
<input
type=«text»
name=«numero1»
value=«${asistenteForm.numero1}«/></p>

<p>Segundo
número:
<input
type=«text»
name=«numero2»
value=«${asistenteForm.numero2}«/></p>

<input
type=«submit»
value=«siguiente»
/>

</form>

</body>

</html>

También deberemos cambiar las páginas del paso 2 y 3
para que utilicen el formulario asistenteForm
en lugar de form
como se llamaba antes.

En el /web/WEB-INF/flows/asistente-beans.xml vamos a definir el
validador a utilizar y vamos a cambiar el nombre del formulario:

<beans
xmlns=«http://www.springframework.org/schema/beans»

xmlns:xsi=«http://www.w3.org/2001/XMLSchema-instance»

xsi:schemaLocation=«http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd»>

<bean
id=«formAction»

class=«es.autentia.tutoriales.manualBasicoSpringWebFlow.controller.action.AsistenteAction»>

<property
name=«formObjectScope»
value=«FLOW»
/>

<property
name=«formObjectName»
value=«asistenteForm»
/>

<property
name=«formObjectClass»

value=«es.autentia.tutoriales.manualBasicoSpringWebFlow.controller.form.AsistenteForm»
/>

<property
name=«validator»
ref=«formActionValidator»/>

</bean>

<bean
id=«formActionValidator»
class=«org.springmodules.validation.commons.DefaultBeanValidator»>

<property
name=«validatorFactory»
ref=«validatorFactory»
/>

</bean>

</beans>

Finalmente, en el /web/WEB-INF/flows/asistente-flow.xml vamos a
invocar al método bindAndValidate en la transición del
paso 1 al 2 como se indica en negrita:

<?xml
version=«1.0»
encoding=«UTF-8»?>

<flow
xmlns=«http://www.springframework.org/schema/webflow»

xmlns:xsi=«http://www.w3.org/2001/XMLSchema-instance»

xsi:schemaLocation=«http://www.springframework.org/schema/webflow

http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd»>

<start-actions>

<action
bean=«formAction»
method=«setupForm»
/>

</start-actions>

<start-state
idref=«mostrarPaso1»
/>

<view-state
id=«mostrarPaso1»
view=«paso1»>

<transition
on=«siguiente»
to=«avanzaAPaso2»>

<action
bean=«formAction»
method=«bindAndValidate»
/>

</transition>

</view-state>

<action-state
id=«avanzaAPaso2»>

<action
bean=«formAction»
method=«validarPaso1YPrepararPaso2»
/>

<transition
on=«success»
to=«mostrarPaso2»
/>

<transition
on=«error»
to=«mostrarPaso1»
/>

</action-state>

<view-state
id=«mostrarPaso2»
view=«paso2»>

<transition
on=«siguiente»
to=«avanzaAPaso3»>

<action
bean=«formAction»
method=«bind»
/>

</transition>

<transition
on=«anterior»
to=«mostrarPaso1»>

<action
bean=«formAction»
method=«bind»
/>

</transition>

</view-state>

<action-state
id=«avanzaAPaso3»>

<action
bean=«formAction»
method=«validarPaso2YPrepararPaso3»
/>

<transition
on=«success»
to=«mostrarPaso3»
/>

<transition
on=«error»
to=«mostrarPaso2»
/>

</action-state>

<end-state
id=«mostrarPaso3»
view=«paso3»
/>

<import
resource=«asistente-beans.xml»
/>

</flow>

Ejecutando
la aplicación

Lanzamos el servidor con la URL
http://localhost:8080/pruebaWebFlowSimple/asistente.flow
y veremos en funcionamiento el ejemplo si ponemos 0 en los valores
para el número 1 y 2:

Algunos links interesantes

  • Sitio oficial de Spring Modules, http://projects.spring.io/spring-webflow/

  • Documentación oficial de Referencia ,
    https://springmodules.dev.java.net/docs/reference/0.8/html/validation.html

  • Documentación oficial de Commons Validator,
    http://struts.apache.org/1.x/faqs/validator.html

Conclusiones

Tras utilizarlo en proyectos de envergadura concluimos que:

  • El framework nos simplifica
    asombrosamente la implementación de las validaciones de
    interfaz de usuario y nos aporta ya resueltas las validaciones más
    frecuentes.

  • Nos aporta la capacidad de poder
    centralizar y generar reportes actualizados de todas las
    validaciones de interfaz de usuario que se realizan en la
    aplicación. Esto es muy interesante de cara a presentar
    informes de revisión y auditoría a equipos de negocio.

  • La configuración de las
    validaciones (validation.xml) se podría generar desde una
    herramienta o una excel operada por integrantes del equipo de
    negocio.

  • El Apache Commons Validator se
    integra perfectamente con Spring WebFlow.

  • Su internacionalización es
    muy potente y completa.

  • No debemos confudir validaciones
    de interfaz de usuario con las validaciones de negocio. Las primeras
    son relativas a tipos de datos, rangos, etc. y las segundas tienen
    que ver con restricciones de negocio, cálculos, etc.

  • Incluye características
    avanzadas como soporte a validaciones en interfaces tipo asistente
    (varios pasos), validación de múltiples campos,
    validaciones condicionales y hasta soporte a un lenguaje de
    validaciones en xml llamado valang.

Desde Autentia contamos con los
conocimientos y experiencia para ayudarle a sacar la máxima
ventaja de las tecnologías más innovadoras y mejorar la
calidad de sus desarrollos software.

No dude en contactarse con nosotros
mediante www.autentia.com .

Dejar respuesta

Please enter your comment!
Please enter your name here