Contacto

Nos puedes enviar un artículo a publicar (si te fue útil, seguro que a otros también).
Nos puedes sugerir temas/profundidad de interés.
correo-e - perfil

Busquedas

Validar datos de formulario con Spring mvc

 Continuando con los ejemplos de spring mvc, al formulario del artículo anterior (Formulario con Spring MVC) le agregamos validación de los datos.

  1) Para esto agregamos un campo adicional en el formulario (la edad del usuario), para validar un entero como ejemplo, por lo que incluimos en la página usuario.jsp la siguiente línea:
    Edad: <form:input path="edad"/>

  2) En la clase que se mantiene los datos del formulario, test.bean.Usuario.java, se tiene que incluir el atributo "edad", con el get/set correspondiente.

 private int edad;
 public int getEdad() { return edad; }
 public void setEdad(int edad) { this.edad = edad; }


  3) Creamos una nueva clase, que será la encargada de la validación de los campos del formulario. Se tiene que implementar la interface Validator (org.springframework.validation.Validator), junto con los métodos 'supports' y 'validate'.

 Usamos ValidationUtils.rejectIfEmptyOrWhitespace, que verifica que el campo que indicamos (segundo parámetro, por ejemplo "nombre") no este vacío, ni contenga solo espacios en blanco.
 Si se cumple la condición, genera un error con un código (tercer parámetro, por ejemplo 'error.usuario.nombre', el cuál se busca en el archivo de resource bundle configurado (si se hizo), para desplegar el texto que corresponda con ese código.
 En caso de no encontrar el código, se muestra el mensaje por defecto (cuarto parámetro, por ejemplo 'Error en nombre').

test.bean.validator.UsuarioValidator.java
   package test.bean.validator;
   import org.springframework.validation.Errors;
   import org.springframework.validation.ValidationUtils;
   import org.springframework.validation.Validator;
   import test.bean.Usuario;
     /** @author dlix */
   public class UsuarioValidator implements Validator {
     public boolean supports(Class type) {
       return Usuario.class.isAssignableFrom(type);
     }
     public void validate(Object command, Errors errors) {
       Usuario form = (Usuario) command;
       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "nombre", "error.usuario.nombre", "Error en nombre");
       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "apellido", "error.usuario.apellido", "Error en apellido");

      validateEdad(form.getEdad(), errors);
      validateApellido(form.getApellido(), errors);
   }
      // tiene que ser mayor de 18
   private void validateEdad(int edad, Errors errors) {
       if( edad < 18){ errors.rejectValue("edad", "error.usuario.edad", "Error en  edad"); } }

      // El apellido solo puede tener letras 
   private void    validateApellido(String apellido, Errors errors) {
      if (!apellido.trim().matches("[a-zA-Z]*") ) {
           errors.reject("error.usuario.apellido.nomatches", 
               "El apellido solo tiene  que tener letras"); } } 
}

 4) Se le tiene que indicar al framework, la clase encargada de validar el formulario.
  Una de las formas de hacer esto, es en la configuración del Dispatcher Servlet. En el archivo dispatcher-servlet.xml, en el bloque donde se configuró el controlador (<bean id="usuController" ...), se agrega:
   <property name="validator">
     <bean class="test.bean.validator.UsuarioValidator"/>
   </property>


 5) Se tiene que modificar la página nuevamente, en esta oportunidad para mostrar los mensajes de error.
  Para esto tenemos varias posibilidades, según la forma que se quiera desplegar los mensajes al usuario.
 En la página tenemos que tener el taglibs 'core' <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>, y recordamos que ya tenemos el 'form' de spring (<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" % > )

  Los errores pueden representar un campo del formulario (al validar, cuando se indica, por ejemplo, errors.rejectValue("edad", ...) ).
  En este caso, podemos ver el error mediante: <form:errors path="edad" />. Con la propiedad 'path' se indica el campo del formularo que representa el error.

  Pueden haber errores que no representen un campo en particular, por ejemplo, al validar, errors.reject("error.usuario.apellido.nomatches",...).
  En la página podemos desplegar todos estos errores mediante: <form:errors />

  Con <form:errors path="*"> estamos indicando todos los errores ('path=*' matchea con todos los valores), y de esta forma podemos reccorrer todos los mensajes (en la variable 'messages') de error, de la siguiente forma:

  <form:errors path="*">
     <c:forEach items="${messages}" var="message">
        <c:out value="${message}"/><br />
     </c:forEach>
  </form:errors>


 En este momento podemos ejecutar la aplicación, y verificar que se realizan las validaciones correctamente.

 Si en el campo de 'edad', que corresponde a un entero, ingresamos un valor que no puede ser convertido a Integer, en la página se desplega el error:
'Failed to convert property value of type [java.lang.String] to required type [int] for property 'edad'; nested exception is java.lang.NumberFormatException: For input string: "5AA"

 Por último configuramos ResourceBundleMessageSource, para tener fuera del código los mensajes de error, y agregar un mensaje amigable al usuario, para la exception de NumberFormatException.

 6) Configuración de mensajes.
  6.1) Se crea dentro del paquete "test.resource" (obviamente, puede tener la ruta y nombre de nuestra preferencia), el archivo "messages.properties" en donde se va a ingresar los mensajes de error a desplegar en la página.

     messages.properties
  error.usuario.nombre=Se tiene que ingresar nombre valido.
  error.usuario.apellido=Se tiene que ingresar apellido valido.
  error.usuario.edad=Se tiene que ingresar edad.
  error.usuario.apellido.nomatches=El apellido solo puede contener letras, sin espacios.
  typeMismatch.usuario.edad=Edad solo puede tener Nros. enteros.


 Nota: con typeMismatch contolamos el mensaje del error NumberFOrmatException

 Se puede agregar caracteres especiales en el texto. Por ejemplo, si tienes que incluir tildes y eñes, agrega estos caracteres con su código unicode.
 Los códigos unicode para tildes y eñes se pueden obtener en el articulo Caracteres Html y Unicode en español.
 Por ejemplo, se pudo haber indicado el siguiente error:
  "error.usuario.edad=N\u00famero inv\u00e1lido para edad." para indicar :"Número inválido ..."

  6.2) Se modifica 'dispatcher-servlet.xml' para configurar el archivo que contiene los mensajes, agregando el siguiente bloque:

  <bean id="messageSource"   class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename">
       <value>test.resource.messages</value>
    </property>
  </bean>


Al ejecutar la aplicación con estos nuevos cambios, y generar los errores, podemos ver los diferentes textos que que incluimos en el archivo "messages.properties", en lugar de los mensajes por defecto "hardcodeados" en el código.

(El proyecto TestSpring para descargar fuentes y .war)

1 comentario:

Anónimo dijo...

Gracias, fue de gran ayuda, y todo funciono correctamente. muy bien.