Componentes, conversión y validación

Componentes

Hay dos tipos de componentes de interfaz de usuario (UI Components), los que inician una acción, como los botones, por ejemplo, y los que proporcionan datos, como los campos de texto. El comportamiento de los componentes UI viene definido por los distintos interfaces de comportamiento que provee la especificación de Faces. Por ejemplo, un componente de acción implementará “UICommand”… y así sucesivamente. Casi todos los componentes UI extienden de la clase “UIComponentBase”, que implementa mucha de la funcionalidad necesaria en la construcción de componentes. Vamos a comentar algunos interfaces:

  • EditableValueHolder → Tiene un “value” que puede ser editado por el usuario
  • ActionSource2 → Produce un “ActionEven” cuando es pulsado por el usuario
  • PartialStateHolder → Mantiene el estado desde un request hasta otro request
  • ValueHolder → Tiene un “value” que no puede ser editado por el usuario
  • ClientBehaviorHolder → Añade comportamiento al cliente, como por ejemplo de tipo Ajax
  • NamingContainer → Los identificadores de los componentes hijo, deben ser únicos.

El core de los componentes UI se encuentra en el paquete “javax.faces.component”, como UIComponent, UIComponentBase, UIInput, etc.. Hay otro grupo de componentes que facilita el desarrollo de clientes HTML, y que se encuentran en el paquete “javax.faces.component.html”. Normalmente extienden de los componentes del core, por ejemplo, HtmlCommandButton es un botón que se representa en html y extiende del core UICommand. La clase Renderer, habla con el UIComponent y es responsable de representar al componente en algún tipo de cliente, como un explorador web.  

Accediendo a los componentes de manera programática

En los anteriores ejemplos, hemos visto como se enlazaban las propiedades de un managed-bean con los componentes Jsf. Si queremos tener acceso a los componentes propiamente dichos, de manera que podamos alterar su comportamiento, podemos incluirlos en el managed-bean, y enlazarlos en la vista. Por ejemplo, vamos a crear una vista con un campo de texto de entrada, un campo de texto de salida y un botón. Queremos que cuando se pulse el botón, el texto de entrada se muestre en el de salida y además, que el campo de texto de entrada, se haga no editable y muestre un mensaje. Para ello definimos el managed-bean, del siguiente modo.

Y creamos la página “inicio.xhtml”, con este contenido:

Como se puede ver, con “binding”, enlazamos el componente. De este modo, si ejecutamos el ejemplo, y escribimos algo en la caja de texto, al pulsar el botón se mostrará algo como esto:

Accediendo a los componentes

Accediendo a los componentes

Podemos comprobar que ahora el textarea  es de solo lectura. En general es recomendable enlazar propiedades en lugar de enlazar componentes.

Conversión y validación de datos

Como ya hemos visto, empleando validaciones, nos aseguramos de que los datos tienen el valor correcto y con las conversiones, nos aseguramos de que es del tipo adecuado. Las validaciones se aplican a componentes de entrada, sin embargo las conversiones se pueden aplicar a componentes de entrada o de salida. Por ejemplo:

Se mostraría, por ejemplo, como: “Iva aplicable: 22%”. En el siguiente ejemplo se aplican a la vez validaciones y conversiones personalizadas.

Los conversores y los validadores, normalmente son instancias de javax.faces.convert.Converter, y javax.faces.validator.Validator respectivamente, y producen una salida “success” o “failure” que altera el flujo de la aplicación.

Conversión

El interfaz javax.faces.convert.Converter define estos dos métodos:

El parámetro context, hace referencia al “facesContext” del request, component, es el componente del que se toma el valor que se va a convertir (es aconsejable, que en la implementación del conversor, no se altere el estado del componente) y “value” es el valor a convertir. Cuando se representa el componente en la vista, se invoca a getAsString(). En el proceso de envío de datos, se invoca a getAsObjet(), para convertir la cadena al tipo de dato adecuado.

Cuando editamos un componente en una vista, es sencillo conocer desde eclipse los conversores estándar, pulsando “Ctrl+espacio”. Por ejemplo:

Conversores

Conversores

DateTimeConverter y NumberConverter tienen sus propias etiquetas “$lt;f:convertdatetime$gt;” y “$lt;f:convertnumber$gt;”, y que permiten añadir configuración, como por ejemplo el patrón a utilizar: “$lt;f:convertdatetime pattern=”dd/MM/yyyy”$gt;”. Esto sería lo que se llama, definir la conversión de manera explícita.

En la etiqueta “$lt;f:converter$gt;”, en el parámetro converterId se especifica un conversor específico definido en el archivo faces-config.xml, o anotado con @FacesConverter, o por la clase. Un ejemplo de definición de un conversor en el archivo faces-config.xml, podría ser el siguiente:

Como hemos comentado anteriormente, esta clase “ConversorCantidades” implementaría “javax.faces.convert.Converter”. También se puede registrar un conversor, por el tipo de objeto que puede convertir, por ejemplo, si implementamos la clase, y la anotamos de este modo:

O bien, la definimos en faces-config.xml de este modo:

Cuando se asocia un componente con una propiedad del bean, de un determinado tipo, se está realizando una conversión implícita. Los tipos pueden ser:

  • java.math.BigDecimal
  • java.math.BigInteger
  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Double
  • java.lang.Float
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Short

Por ejemplo, en:

Como el campo “peso”, del bean ”producto” es de tipo “Integer” (por ejemplo), automáticamente se asocia el conversor “javax.faces.convert.IntegerConverter” de manera implícita.

Validación

El interfaz “javax.faces.validator.Validator” define un método “valídate()”:

El parámetro context, hace referencia a “facesContext” del request, “component”, es el componente del que se toma el valor que se va a validar, y “value” es el valor a validar. El método debe lanzar una excepción ValidatorException, en el caso de que falle la validación.

Existen validaciones estándar, que como en el caso anterior, se puede mostrar en Eclipse editando la vista y pulsando “Ctrl+espacio”:

Validaciones estándar

Validaciones estándar

Vamos a ver algunos ejemplos:

Se pueden añadir componentes entre un par de etiquetas “f:validaterequired” de modo que en lugar de poner componente por componente el flag requierd=”true”, se aplique esta condición a un grupo de componentes.

Las validaciones disponen de una propiedad disabled=”” de modo que si está a true, no se aplica la validación. Se pueden utilizar expresiones EL para configurar el valor de esta propiedad.

Implementar Validadores

Se puede utilizar un método de un bean como validador, siempre y cuando, dicho método tenga los mismos parámetros y devuelva lo mismo que Validator.validate( ). Por ejemplo:

El método, se definirá como:

Este tipo de asociación, únicamente permite un validador.

Otro modo de crear un validador, es implementar el interfaz “Validator”. La clase se registrará con un validator-id, para lo cual, se utiliza la siguiente anotación:

En lugar de la anotación @FacesValidator, se puede incluir en el fichero faces-config.xml

Aquí terminamos este artículo. Hemos hablado de conversores y validadores y hemos visto que Jsf ofrece la posibilidad de usar las implementaciones estándar de estos componentes. Cuando falle la conversión o la validación se mostrará el mensaje correspondiente, pero ¿Qué ocurre si queremos personalizar dicho mensaje?. Hablaremos de esto en el próximo artículo: Internacionalización

Un comentario:

  1. Excelente Articulo sobre las conversiones y Validaciones para JSF.
    Gracias por las explicaciones.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *