JSF 2 Ajax y Bean Validation

5
31654

Í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:
http://www.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:
http://www.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 atributo for. 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 el for, 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 atributo event. 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 estilo onclickonfocus, onkeypress, … los nombres de los eventos correspondientes serán click, focuskeypress, … es decir, quitamos el prefijo on.
    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 el styleClass. 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'}".
    Con component.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»

http://www.autentia.com

Alejandro es socio fundador de Autentia y nuestro experto en Java EE, Linux y optimización de aplicaciones empresariales. Ingeniero en Informática y Certified ScrumMaster. Seguir @alejandropgarci Si te gusta lo que ves, puedes contratarle para darte ayuda con soporte experto, impartir cursos presenciales en tu empresa o para que realicemos tus proyectos como factoría (Madrid). Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación.

5 COMENTARIOS

  1. 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

  2. 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.

  3. 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

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad