JSF proporciona una serie de validadores estándar a través de sus librerías de acciones, a la par que permite definir validadores propios por parte de cada aplicación. Su propósito es validar la información introducida en el cliente, a través de un formulario normalmente.
Estándar
Los validadores estándar se encuentran dentro de la librería core de JSF, y se usan en conjunción con los componentes HTML de la librería html.
– f:validateLength
: Valida que la longitud de una cadena de texto esté dentro de un rango.
– f:validateDoubleRange
: Valida que un valor numérico esté dentro de un rango.
– f:validateLongRange
: Valida que un valor numérico, o una cadena de texto convertible a número, esté dentro de un rango.
– f:validateRegEx
: Valida que un valor case con una expresión regular.
– f:validateRequired
: Valida que un elemento tenga valor. Es equivalente al atributo required
de HTML.
– f:validateBean
: Registra un validador personalizado para el bean.
En el siguiente ejemplo se muestra un formulario para la introducción de un nombre que debe tener al menos cinco caracteres de longitud:
<h:form id="formulario"> <h:outputLabel for="nombre" value="Nombre:"/> <h:inputText id="nombre" value="#{usuario.nombre}"> <f:validateLength minimum="5"/> </h:inputText> <h:commandButton type="submit" value="Enviar" action="enviar"/> <h:message for="nombre" style="color: red;"/> </h:form>
Si el valor no pasa la validación se muestra un mensaje en el elemento h:message
con el siguiente detalle:
formulario:nombre: Error de validación: el largo es inferior que el mínimo permitido de '5'
Un aspecto que resulta un tanto confuso a veces es que JSF inicializa las cadenas de texto con una cadena vacía por defecto, y no a nulo. Si se quiere cambiar este comportamiento se puede añadir un parámetro al contexto a través del fichero web.xml
de la siguiente forma:
<context-param> <param-name> javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL </param-name> <param-value>true</param-value> </context-param>
Anotaciones
JSF permite utilizar el conjunto de anotaciones estándar definido por la especificación JavaBean Validation. Estas anotaciones se aplican a las propiedades de los bean y permiten indicar las condiciones que deben de cumplir para considerarse válidas.
Algunas de las anotaciones disponibles:
– @AssertFalse
: Valida que el valor es false
.
– @AssertTrue
: Valida que el valor es true
.
– @DecimalMax
: Valida que el valor es menor o igual que el indicado en la anotación.
– @DecimalMin
: Valida que el valor es mayor o igual que el indicado en la anotación.
– @Digits
: Valida que el valor tiene como mucho la cantidad de enteros y decimales indicados en la anotación.
– @Future
: Valida que el valor es una fecha a futuro.
– @Max
: Valida que el valor es un entero menor o igual que el indicado en la anotación.
– @Min
: Valida que el valor es un entero mayor o igual que el indicado en la anotación.
– @NotNull
: Valida que el valor no es nulo.
– @Null
: Valida que el valor es nulo.
– @Past
: Valida que el valor es una fecha del pasado.
– @Pattern
: Valida que el valor casa la expresión regular indicada en la anotación.
– @Size
: Valida que la longitud del valor está dentro de un rango indicado en la anotación.
En el siguiente ejemplo se muestra un bean con anotaciones de validación sobre sus propiedades:
@ManagedBean public class Usuario { @NotNull @Size(min=5, max=25) private String nombre; @NotNull @Past private Date nacimiento; @AssertTrue private Boolean activo; ...
No obstante, para utilizar estas anotaciones es necesario disponer de una librería (jar) que las implemente, como por ejemplo la desarrollada por Hibernate, y que puede obtenerse añadiendo la siguiente dependencia en el fichero pom.xml de Maven :
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.3.0.Final</version> </dependency>
Binding
Otra forma de definir validadores por parte de una aplicación es utilizar las facilidades de binding que ofrece JSF.
De forma general, el binding es el proceso de asociar el valor de un componente a una propiedad de un bean, de manera que cuando cambia el valor del componente se refleja en el bean, y cuando cambia en el bean se refleja en el componente.
JSF extiende el concepto de binding al permitir asociar un validador a una propiedad de un bean:
<h:inputText id="nombre" value="#{usuario.nombre}"> <f:validateLength binding="#{usuario.validador}"/> </h:inputText>
En buena lógica, la propiedad del bean debe ser del mismo tipo que el validador:
@ManagedBean public class Usuario { private LengthValidator validador = new LengthValidator(); public LengthValidator getValidador() { validador.setMinimum(10); return validador; } ...
Lo interesante del código es que las propiedades del validador pueden hacerse variar de forma dinámica dentro del bean. Por ejemplo, el tamaño mínimo puede hacerse que cambie en función de alguna lógica determinada, y dicho cambio afectaría inmediatamente al componente.
Validator
Otra posibilidad que ofrece JSF a la hora de definir validadores es crear una clase que implemente la interface Validator
. Los validadores implementados de esta forma se anotan con @FacesValidator
o se definen dentro del fichero faces-config.xml. Normalmente tienen que implementar otras interfaces como StateHolder
e incluirse dentro de una TLD para poder ser utilizados como una acción más dentro de una vista.
Una alternativa más sencilla que ofrece JSF es implementar un método propio dentro de un bean sin que la clase del bean tenga que heredar de ninguna otra ni implementar ninguna interface. Basta con que el método que se quiera utilizar como validador tenga los mismos parámetros que admite la interface definida por Validator
:
@ManagedBean public class Usuario { public void validateNombre(FacesContext context, UIComponent toValidate, Object value) { String nombre = (String)value; if (nombre.equals("admin")) { ((UIInput)toValidate).setValid(false); FacesMessage message = new FacesMessage("¡Tramposo!"); context.addMessage(toValidate.getClientId(context), message); } } ...
El valor a validar se recibe en el parámetro value
. El componente siendo validado en toValidate
. Y el contexto en context
. Si el valor no pasa la validación se debe cambiar a false
la propiedad valid
del componente y opcionalmente añadir un mensaje al contexto.
Para utilizar un método de validación propio se debe utilizar el atributo validator
del componente:
... <h:inputText ... value="#{usuario.nombre}" validator="#{usuario.validateNombre}"> ...