Índice de contenidos
1. Introducción
2. Entorno
3. Dependencias
4. Un back-bean sencillo
5. La vista con el campo de entrada
6. Conclusiones
7. Sobre el autor
1. Introducción
Bean Validation es una especificación de Java (JSR-303) que permite definir validaciones de una clase/bean/POJO mediante anotaciones.
JSF 2 tiene de serie soporte Ajax mediante la etiqueta <f:ajax>
.
En este tutorial vamos a ver como combinar estas dos tecnologías para, ante determinados eventos, se nos hagan validaciones mediante AJAX.
Podríamos decir que este tutorial es un pasito más en lo que ya se vio en el tutorial:
https://adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=jsf2Return
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 17′ (2.93 GHz Intel Core 2 Duo, 4GB DDR3 SDRAM, 128GB Solid State Drive).
- NVIDIA GeForce 9400M + 9600M GT with 512MB
- Sistema Operativo: Mac OS X Snow Leopard 10.6.3
- JDK 1.6.0_20
- Maven 2.2.1
- JSF 2 (2.0.2)
- hibernate-validator 4.0.2.GA como implementación de la JSR-303
- Tomcat 6.0.26
3. Dependencias
Vamos a usar como proyecto base el que tenemos en el tutorial:
https://adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=jsf2Return.
En este tutorial podéis encontrar el código fuente, donde ya tenemos las dependencias necesarias para la JSR-303 (esto es necesario porque estamos desplegando en Tomcat, si usáramos la última versión de GlassFish no nos haría falta el jar, con lo que podríamos poner el scope
como provided
):
... <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.0.2.GA</version> </dependency> ...
4. Un back-bean sencillo
Para el ejemplo nos vamos a crear un xhtml con un ejemplo de un campo de entrada, y una clase java que será el correspondiente back-bean.
La clase java es la siguiente:
import javax.faces.bean.ManagedBean; import javax.validation.constraints.Size; @ManagedBean public class InputTextView { @Size(min = 6, max = 8) private String textValue; public void setTextValue(String textValue) { this.textValue = textValue; } public String getTextValue() { return textValue; } public String send() { return null; } }
Simplemente tenemos un atributo donde guardaremos nuestro el valor del campo de entrada. Y este atributo lo marcamos con @Size para indicar que el valor solo será válido si tiene entre 6 y 8 caracteres. Es decir, será inválido si tiene menos de 6 o más de 8.
5. La vista con el campo de entrada
Queremos conseguir algo de este estilo:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Autentia InputText demo</title> <style type="text/css"> .invalid { border:1px solid red; } </style> </h:head> <h:body> <h1>Autentia InputText demo</h1> <h:form> <h:outputLabel for="inputText" value="Campo de texto: " /> <h:inputText id="inputText" value="#{inputTextView.textValue}" styleClass="#{component.valid ? '' : 'invalid'}"> <f:validateBean for="inputText" /> <f:ajax event="keyup" render="@this inputTextMessage" /> </h:inputText> <h:message id="inputTextMessage" for="inputText" /> <p /> <h:commandButton action="inputTextView.send" value="Enviar" /> </h:form> </h:body> </html>
Vemos que la página es bastante sencilla. Vamos a comentar algunos aspectos:
- Línea 22 – Con
f:validateBean
, estamos diciendo que queremos usar las validaciones que hemos puesto en el managed-bean mediante las anotaciones de la JSR-303. Esto ya lo hacíamos en el tutorial anterior, pero podemos destacar el uso del atributofor
. Con este atributo indicamos el nombre del atributo que queremos validar dentro de la clase. Si no indicamos nada se validan todos los atributos de la clase (si no ponemos elfor
, también funcionaría, pero es porque como la petición es AJAX el resto de campos de entrada no viajarán al servidor). - Línea 23 – Con
f:ajax
conseguimos que se haga una petición AJAX donde, por defecto, viajará sólo este campo de entrada. Aquí podemos destacar el atributoevent
. Gracias a este atributo podemos engancharnos a cualquier evento del componente. El nombre del evento lo podemos ver en la documentación del componente (en el javadoc), de forma que si en la documentación nos dice que el componente tiene atributos del estiloonclick
,onfocus
,onkeypress
, … los nombres de los eventos correspondientes seránclick
,focus
,keypress
, … es decir, quitamos el prefijoon
.
También estamos usando@this
en el atributo render. Con esto estamos indicando que queremos que se repinte el propio componente donde se produce la petición AJAX, y así aplique elstyleClass
. Tenemos varias palabras de este estilo:@none
,@this
,@form
,@all
. - Línea 21 – Lo que podemos destacar en esta línea es la expresión regular que encontramos dentro del
styleClass="{comoponent.valid ? '' : 'invalid'}"
.
Concomponent.valid
estamos accediendo a un atributo de este componente que indica que la validación ha sido correcta o no. De esta forma, gracias al operador ternario ? : conseguimos aplicar un estilo concreto cuando la validación ha sido incorrecta.
Como hemos puesto en la línea 23 el evento keyup, conseguimos que cada vez que se pulse una tecla salte la validación, de esta forma hasta que no escribimos al menso 6 caracteres, el validador no nos va a dejar tranquilos.
6. Conclusiones
Vemos como con simplemente la implementación de referencia y sin usar ninguna librería de componentes adicional podemos hacer cosas bastante elaboradas con apenas líneas de código. Esta claro que librerías como ICEfaces van a tener que ponerse las pilas si no
quieren perder su posición privilegiada dentro del mundo JSF, ya que con JSF 2 ya no son necesarias la mayoría de funcionalidades extra que nos daban este tipo de librerías.
7. Sobre el autor
Alejandro Pérez García, Ingeniero en Informática (especialidad de Ingeniería del Software) y Certified ScrumMaster
Socio fundador de Autentia (Formación, Consultoría, Desarrollo de sistemas transaccionales)
mailto:alejandropg@autentia.com
Autentia Real Business Solutions S.L. – «Soporte a Desarrollo»
Muchas gracias Alejandro ….
Saludos, soy nuevo en esto del jsf y se me presentan muchas dudas…. pues aca dejo una a ver si me podrian ayudar…
tengo una consulta a la bd.. esta consulta la muestro en pantalla en unos inputText de la siguiente manera
donde objeto es la respuesta obtenida de la consulta y atributo pues es el atributo
Ahora bien… en el bean tengo solo definido el objeto, con sus getters y setters.
La cuestion esta en cuanto quiero modificar y enviar al bean… no lo hace de manera correcta me muestra el objeto como estaba al llegar al jsf
el bean tiene el metodo guardar solo con un \\\»syso\\\» para ver el atributo
public String guardar(){
System.out.println(\\\»Metodo guardar\\\»);
System.out.println(\\\»Atributo: \\\» +objeto.getAtributo());
}
Mi duda es : ¿Por que no veo reflejados los cambios al pasar al bean?
Mi config de faces
solicitanteBean
ve.gob.alcaldia.workflow.web.beans.SolicitanteBean
session
Agradezco toda la ayuda de antemano.
Grax
Mola.
Buenas Alejandro, tengo una duda y no encuentro solución.
¿sabes si es posible parametrizar el mensaje para que indique el nombre del campo? Es decir no tener que mostrarlo junto al campo si no en la posición global.
Saludos y gracias de antemano.
Hola muy buen material, nada mas que tengo unas dudas, para que el f:ajax funciones correctamente ¿debe estar dentro de un h:form? por que yo estoy utilizando el icefaces y lo tengo dentro de un ice:form y el problema viene cuando en la propiedad render le pongo mas de un id