jsf basico

54
Java Server Faces (JSF) Autor: Antonio J. Martín

Upload: mcwewe

Post on 29-Jun-2015

6.444 views

Category:

Documents


4 download

DESCRIPTION

Manual básico para empezar con JSF

TRANSCRIPT

Page 1: JSF Basico

Java Server Faces (JSF)

Autor: Antonio J. Martín

Page 2: JSF Basico

ÍNDICE

1. INTRODUCCIÓN................................................................................................... 5

1.1. CARACTERÍSTICAS DE JSF ................................................................................... 5

2. COMPONENTES DE UNA APLICACIÓN JSF .................................................... 5

2.1. ARCHIVO DE CONFIGURACIÓN FACES-CONFIG.XML ................................................. 6

2.2. SERVLET FACESSERVLET..................................................................................... 6

2.3. BEANS GESTIONADOS .......................................................................................... 7

2.4. CONTEXTO DE APLICACIÓN. LA CLASE FACESCONTEXT ......................................... 8

2.5. ACCIONES JSP.................................................................................................... 9

3. CREACIÓN DE UNA PRIMERA APLICACIÓN JSF............................................ 9

3.1. CREACIÓN DE LA ESTRUCTURA DE LA APLICACIÓN................................................ 10

3.2. IMPLEMENTACIÓN DEL MODELO........................................................................... 11

3.3. CREACIÓN Y REGISTRO DE BEANS GESTIONADOS................................................. 11

3.4. IMPLEMENTACIÓN DE CONTROLADORES DE ACCIÓN.............................................. 11

3.5. DEFINICIÓN DE REGLAS DE NAVEGACIÓN ............................................................. 12

3.6. CREACIÓN DE LAS VISTAS................................................................................... 13

EJERCICIO 1.................................................................................................. 16

EJERCICIO 2.................................................................................................. 20

4. EVENTOS DE ACCIÓN (ACTIONEVENT)......................................................... 24

5. CICLO DE VIDA DEL PROCESAMIENTO DE UNA PETICIÓN JSF................ 26

5.1. RESTORE VIEW.................................................................................................. 27

5.2. APPLY REQUEST VALUES................................................................................... 28

5.3. PROCESS VALIDATION........................................................................................ 28

5.4. UPDATE MODEL VALUES .................................................................................... 28

5.5. INVOKE APPLICATION ......................................................................................... 28

5.6. RENDER RESPONSE........................................................................................... 29

6. COMPONENTES GRÁFICOS JSF..................................................................... 29

6.1. RENDERIZACIÓN ................................................................................................ 30

6.2. TAGS DE COMPONENTES JSF............................................................................. 30

Page 3: JSF Basico

6.2.1. Formulario ................................................................................................. 32

6.2.2. Controles: atributos comunes. .................................................................. 32

6.2.3. Campos de texto ....................................................................................... 32

6.2.4. Controles de comando .............................................................................. 33

6.2.5. Generación de texto.................................................................................. 33

6.2.6. Casillas de verificación.............................................................................. 33

6.2.7. Listas de selección única .......................................................................... 33

6.2.7.1. Componentes de una lista ................................................................. 34

6.2.8. Listas de selección múltiple ...................................................................... 35

6.3. EL EVENTO VALUECHANGEEVENT ...................................................................... 36

EJERCICIO 3.................................................................................................. 36

7. CONVERSORES Y VALIDADORES.................................................................. 41

7.1. VALIDADORES.................................................................................................... 42

7.1.1. Validación automática ............................................................................... 42

7.1.2. Validadores implícitos JSF........................................................................ 45

7.1.3. Validadores personalizados ...................................................................... 46

7.2. CONVERSORES.................................................................................................. 47

7.2.1. Conversores implícitos JSF ...................................................................... 48

Page 4: JSF Basico
Page 5: JSF Basico

1. INTRODUCCIÓNJavaServer Faces (JSF) es un framework, incluido dentro de la especificación Java EE,

que tiene como misión facilitar la construcción y mantenimiento de aplicaciones Web en Java,siguiendo la arquitectura Modelo Vista Controlador.

En la definición anterior hemos indicado una característica que hace especial a JSF y ladiferencia de otros frameworks existentes, también orientados a la creación de aplicacionesMVC, como Struts; se trata del hecho de que JSF es parte de la especificación Java EE. Estoimplica que la mayoría de las herramientas creadas por terceros fabricantes para trabajar conJava EE soportan esta tecnología, convirtiendo así a JSF en el framework más “estandarizado”de todos los existentes y favoreciendo su rápida extensión.

1.1. CARACTERÍSTICAS DE JSF

Además de lo comentado anteriormente, otras características que nos ofrece esteframework son:

Componentes de la interfaz de usuario. Habitualmente se suele decir queJSF es un framework de interfaz de usuario, lo cual es debido al amplioconjunto de componentes incluidos en el API JSF orientados a la creación deelementos gráficos. Con ellos podemos construir potentes interfaces gráficasde una manera sencilla e independiente de la tecnología utilizada para eldesarrollo de la vista, es decir, no sólamente podemos emplear estoscomponentes con páginas JSP, sino también con otras tecnologías como porejemplo velocity.

Modelo de navegación declarativo. Como en cualquier aplicación que siga elpatrón MVC, las peticiones son dirigidas al Controlador que se encarga deanalizarlas, despacharlas e invocar a la vista adecuada para la generación dela respuesta. En el caso de JSF la información referente a las posibles vistasque deben ser generadas para cada página origen de la petición se encuentraregistrada en un archivo de configuración propio de JSF, llamado faces-config.xml. Esta información, conocida como reglas de navegación, esconsultada por el Controlador tras el procesamiento de una petición cliente.

Ejecución basada en eventos. De manera similar a como funcionan lasaplicaciones de escritorio, la programación de una aplicación JSF está basadaen parte en la captura de eventos sobre la interfaz gráfica. A través de losatributos de las acciones JSF que representan a los componentes gráficos, esposible asociar estos eventos con métodos de respuesta implementados enlos beans gestionados u otras clases del Controlador, de modo que cuando selance una petición desde la página a la aplicación (lo que se conoce como unpostback) el framework será capaz de detectar los eventos producidos yejecutar los métodos de respuesta a los mismos en el orden en que han tenidolugar.

2. COMPONENTES DE UNA APLICACIÓN JSFComo sucede con otros frameworks, JSF está orientado a prestar soporte para la

construcción de las capas Controlador y Vista de la aplicación, implementándose el Modelo conlos elementos habituales para la encapsulación de la lógica de negocio: clases estándares yEJBs.

Page 6: JSF Basico

En lo que respecta a las otras dos capas de la aplicación, Controlador y Vista, latecnología JSF aporta los siguientes elementos:

2.1. ARCHIVO DE CONFIGURACIÓN FACES-CONFIG.XML

Se utiliza para definir diversos elementos clave para el funcionamiento de la aplicaciónJSF, como las reglas de navegación o los beans gestionados y su ámbito de utilización.

Esta información es utilizada por el controlador FacesServlet para despachar laspeticiones que llegan a la aplicación y activar las vistas que deben generar las respuestas alcliente en cada caso.

La estructura de un documento faces-config es la que se muestra en el siguientelistado:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE faces-config PUBLIC

"-//Sun Microsystems, Inc.//DTD JavaServer Faces

Config 1.1//EN"

"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

:

</faces-config>

2.2. SERVLET FACESSERVLET.

Incluido dentro del paquete javax.faces.webapp, este servlet constituye el punto deentrada a la aplicación Web, haciendo las tareas de Front Controler. A el llegan todas laspeticiones procedentes de la capa cliente, encargándose de despachar cada una de ellas enfunción de la información almacenada en el archivo de configuración faces-config.xml.

Como sucede con cualquier otro servlet de una aplicación, FacesServlet debe serregistrado en el archivo de configuración web.xml. Por convención suele utilizarse la expresión“/faces/*” como patrón de URL asociado al servlet, lo que significa que cualquier URL relativaque comience por “/faces/” provocará la ejecución del servlet. He aquí el bloque de sentenciasde configuración típico de FacesServlet:

<!-- Faces Servlet -->

<servlet>

<servlet-name>Faces Servlet</servlet-name>

<servlet-class>javax.faces.webapp.FacesServlet

</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<!-- Faces Servlet Mapping -->

<servlet-mapping>

<servlet-name>Faces Servlet</servlet-name>

<url-pattern>/faces/*</url-pattern>

Page 7: JSF Basico

</servlet-mapping>

2.3. BEANS GESTIONADOS

Los beans gestionados son uno de los elementos más característicos de una aplicaciónJSF. Se trata de simples JavaBeans que, además de ser utilizados para la encapsulación delos datos procedentes de la capa cliente, incluyen los métodos de respuesta a los eventosproducidos en la capa cliente.

Buscando una comparativa con struts, un bean gestionado es una combinación de unActionForm y un Action en una misma clase, con la particularidad añadida de que el beangestionado es implementado mediante una simple clase POJO (Plain and Old Java Object), esdecir, una clase que no necesita heredar ni implementar ninguna clase o interfaz especial.Precisamente se les llama gestionados porque es el propio framework el que se encargatotalmente de la gestión de su ciclo de vida, es decir, de su instanciación, recuperación,rellenado de datos, invocación a los métodos de respuesta a eventos, etc. El programadorsimplemente tendrá que codificarlo y registrarlo en el archivo de configuración de JSF.

El siguiente ejemplo representa un bean que encapsula los credenciales de usuario eincluye un método para realizar la validación del mismo:

package javabeans;

public class CredencialesBean {

private String user;

private String password;

public CredencialesBean () {

}

public String getUser() {

return user;

}

public void setUser(String user) {

this.user = user;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String doLogin(){

if(password.equals(“admin”)){

return “valido”;

}

else{

return “novalido”;

}

Page 8: JSF Basico

}

}

El método doLogin() es el llamado controlador de acción o método de aplicación.Se trata de un método asociado a los controles de comando (componentes gráficosUICommand que pueden ser representados como un botón de pulsación o un enlace). Cadavez que uno de estos controles es activado, se lanza una petición a la aplicación(postback) que hará que se ejecute este método. Más adelante analizaremos el significadodel objeto String devuelto por este tipo de métodos.

En caso de requerir una lógica de negocio más compleja para realizar la validación delos datos, que incluyera por ejemplo un acceso a los datos, dichas operaciones serían aisladasen una clase o EJB independiente, incluyendo únicamente el método doLogin() la llamada a losmétodos de negocio.

Para registrar este bean en el archivo faces-config.xml habría que incluir el siguientebloque de texto en el interior del elemento faces-config:

<managed-bean>

<managed-bean-name>credencialesBean</managed-bean-name>

<managed-bean-class>

javabeans.CredencialesBean

</managed-bean-class>

<managed-bean-scope>request</managed-bean-scope>

</managed-bean>

A continuación se explica el significado de los elementos utilizados para el registro deun bean gestionado:

managed-bean. Es el elemento principal en el que se incluyen los datos deregistro del bean. Será necesario añadir un bloque <managed-bean> por cadabean que se quiera sea gestionado por el framework.

managed-bean-name. Es el nombre que permite referirse a la instancia delbean. Este nombre es utilizado mediante el lenguaje EL desde los componentesde la interfaz para acceder a las propiedades y métodos del objeto.

managed-bean-class. Nombre cualificado de la clase a la que pertenece elbean.

managed-bean.scope. Ámbito en el que será mantenida la instancia, siendo susposibles valores: request, session y application.

El bean gestionado es parte tanto de la Vista como del Controlador ya que es utilizadopor ambas capas, en el primer caso para almacenar los datos cliente y en el segundo paradespachar la petición.

2.4. CONTEXTO DE APLICACIÓN. LA CLASE FACESCONTEXT

Las aplicaciones JSF deben ser capaces de almacenar información sobre la petición encurso. Toda esta información es accesible al programador a través de la clase FacesContextexistente en el paquete javax.faces.context.

Más adelante veremos algunas de las aplicaciones más importantes de esta clase.

Page 9: JSF Basico

2.5. ACCIONES JSP

Como se ha indicado con anterioridad, JSF incluye un elevado número decomponentes gráficos para la construcción de potentes interfaces de usuario.

En el caso de que las vistas sean implementadas mediante páginas JSP el acceso aestos componentes se realizará a través de una serie de librerías de acciones JSP.Concretamente, la especificación JSP incluye dos tipos de librerías de acciones:

La librería html. Esta librería proporciona además de los controles básicos htmlcon capacidades mejoradas, una serie de componentes gráficos complejosorientados a la presentación de datos en la página. Todos los controles incluidosen esta librería se integran perfectamente con el modelo de JavaBean de Java,permitiendo vincular de manera automática las propiedades de un objeto con lasde un control de la interfaz.

Para poder hacer uso de esta librería en el interior de una página JSP se deberíaincluir la siguiente directiva taglib:

<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

La siguiente etiqueta representa un ejemplo de uso de un componente gráfico detipo caja de texto, en el que a través del elemento value conseguimos vincular elcontenido del control a un la propiedad de un JavaBean:

<h:inputText value="${credencialesBean.user}"/>

La librería core. Además de incluir elementos básicos para la generación de unavista JSF, esta librería proporciona unos componentes especiales conocidoscomo validadores y conversores que permiten realizar validaciones yconversiones de datos, respectivamente, de la información suministrada por elusuario a través de la interfaz, todo ello de manera que el programador no tengaque incluir una sola línea de código para esta tarea.

La directiva taglib necesaria para utilizar las acciones de esta librería sería:

<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>

3. CREACIÓN DE UNA PRIMERA APLICACIÓN JSFVamos a realizar una sencilla aplicación que nos permita poner en práctica los

conceptos explicados anteriormente, así como conocer el proceso básico de creación de unaaplicación basada en este framework.

La aplicación consistirá en validar los credenciales introducidos por el usuario a travésde una página de login. Si el usuario es válido se mostrará una página con los dos datosintroducidos y si no se le llevará a una página de error. El esquema con las tres páginasinvolucradas se muestra en la figura 1.

Page 10: JSF Basico

Figura. 1.

Vamos a ir viendo los pasos que tenemos que seguir para construir la aplicación.

3.1. CREACIÓN DE LA ESTRUCTURA DE LA APLICACIÓN.

En este primer paso debemos crear la estructura de la aplicación Web y añadir laslibrerías necesarias para trabajar con JSF, así como crear el archivo de configuración faces-config.xml y registrar el servlet FacesServlet en el web.xml.

Si contamos con un entorno de desarrollo como NetBeans todas estas operaciones sepueden realizar de forma automática. Para ello, en el asistente de creación de aplicación Webdebemos activar en el último paso la casilla correspondiente al framework JavaServer Faces,tal y como se indica en la figura 2.

Figura. 2.

Con esto no sólo se creará la estructura de la aplicación Web, sino que también sellevarán a cabo las operaciones descritas anteriormente.

Password correcto

Password incorrecto

login.jsp valido.jsp

novalido.jsp

Page 11: JSF Basico

3.2. IMPLEMENTACIÓN DEL MODELO

Como se indicó anteriormente, la implementación de la capa de negocio en unaaplicación JSF es un proceso en el que no interviene ningún elemento de está tecnología.

El desarrollo de estos componentes de negocio puede realizarse de maneraindependiente al resto de las capas.

En este ejemplo no hay que desarrollar ninguna clase de negocio, puesto que la únicalógica existente irá incluida en el método controlador de acción que será ejecutado con lapulsación del botón “Aceptar”.

3.3. CREACIÓN Y REGISTRO DE BEANS GESTIONADOS

El único bean gestionado que utilizaremos en esta aplicación será el CredencialesBeanpresentado anteriormente, registrándolo en el archivo faces-config.xml mediante el bloque desentencias XML indicado.

El archivo faces-config.xml podemos encontrarlo en la carpeta configuration files deNetBeans.

3.4. IMPLEMENTACIÓN DE CONTROLADORES DE ACCIÓN

Los métodos controladores de acción, se implementan en los propios beansgestionados. Estos métodos serán ejecutados por el controlador tras procesarse la peticióngenerada por control de comando, después de que se hayan rellenado los campos del beancon los datos recibidos en la petición.

Como resultado de su ejecución, los controladores de acción deben devolver un Stringque es utilizado por FacesServlet para determinar la siguiente vista que deberá ser invocada,información esta que se encuentra definida en las reglas de navegación dentro de faces-config.

En nuestra aplicación de ejemplo, el método doLogin() correspondiente a la pulsacióndel botón “Aceptar” es bastante simple:

public String doLogin(){

if(password.equals("admin")){

return "valido";

}

else{

return "novalido";

}

}

Como vemos se devuelven dos posibles valores en función de si el password seconsidera o no válido. Dichos valores determinarán a donde será redirigido el usuario.

Aunque en este ejemplo no hemos tenido necesidad de ello, en numerosas ocasionespuede ocurrir que necesitemos acceder desde el controlador de acción a alguno de los objetosclásicos del API servlet para interactuar con la aplicación Web.

A diferencia de los métodos execute() de los objetos de Struts, donde se recibía comoparámetros referencias a los objetos HttpServletRequest y HttpServletResponse, los métodos

Page 12: JSF Basico

controladores de acción de los beans gestionados no reciben ningún parámetro. Noobstante, se puede acceder al contexto de aplicación desde estos métodos a través de la clasejavax.faces.context.ExternalContext cuyos métodos getRequest(), getResponse(),getSession(), etc. nos devuelven referencias a los distintos objetos de aplicación.

Para poder obtener un objeto ExternalContext debemos recurrir a la claseFacesContext existente en el mismo paquete. El siguiente bloque de instrucciones de ejemplosería el código que deberíamos utilizar para obtener un objeto Request desde un método deacción:

FacesContext context=FacesContext.getCurrentInstance();

ExternalContext excontext=context. getExternalContext();

HttpServletRequest request=

(HttpServletRequest)excontext. getRequest();

3.5. DEFINICIÓN DE REGLAS DE NAVEGACIÓN

Las reglas de navegación determinan el flujo de navegación entre las distintas vistas dela aplicación. Las reglas de navegación son aplicadas por FacesServlet cuando éste recibe unapetición desde el navegador, con motivo de la generación de un evento de acción en la páginacliente.

En cada regla de navegación se indican, para cada página origen, las posibles páginasdestino a las que será redirigido el usuario en función de los valores devueltos por el método deacción. Una regla de navegación se define mediante el elemento <navigation-rule>, el cualincluirá los siguientes sub elementos:

from-view-id. URL relativa de la página origen para la que se define la regla denavegación.

navigation-case. Define el posible destino al que será reenviada la petición delusuario. Cada uno de estos posibles destinos requiere su propio <navigation-case> que deberá incluir a su vez los siguientes subelementos:

- from-outcome. Valor devuelto por el método de acción, que provocarála navegación a este destino.

- to-view-id. URL relativa de la vista destino.

En el ejemplo que estamos desarrollando únicamente debemos incluir la regla denavegación asociada al evento del botón “Aceptar” de la página login.jsp, regla queindicaremos a continuación de la definición de los beans gestionados:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE faces-config PUBLIC

"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config

1.1//EN"

"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<!-- ======= FULL CONFIGURATION FILE ================== -->

<faces-config>

Page 13: JSF Basico

<managed-bean>

<managed-bean-name>credencialesBean</managed-bean-name>

<managed-bean-class>javabeans.CredencialesBean

</managed-bean-class>

<managed-bean-scope>request</managed-bean-scope>

</managed-bean>

<navigation-rule>

<from-view-id>/login.jsp</from-view-id>

<navigation-case>

<from-outcome>valido</from-outcome>

<to-view-id>/valido.jsp</to-view-id>

</navigation-case>

<navigation-case>

<from-outcome>novalido</from-outcome>

<to-view-id>/novalido.jsp</to-view-id>

</navigation-case>

</navigation-rule>

</faces-config>

Algo muy importante que debemos tener en cuenta a la hora de definir reglas denavegación es que, si el valor devuelto por alguno de los métodos de acción incluidos en lapágina origen no coincide con ninguno de los valores indicados en los elementos <from-outcome>, se producirá la recarga de la página origen.

3.6. CREACIÓN DE LAS VISTAS

Finalmente, procedemos a crear las distintas vistas de la aplicación. Todas laspáginas JSP en las que vayamos a hacer uso de algunas de las librerías de acciones JSFdeberán incluir el elemento <f:view> de la libraría core, dentro del cual se incluirán el restode acciones JSF de la página.

En el caso de la página login.jsp, utilizaremos las acciones inputText e inputSecret deJSF para generar los campos de texto “usuario” y “password”, respectivamente. Estas accionesdisponen de un atributo value que nos permite vincular los controles con las propiedadesde un bean gestionado, mostrando en su interior el valor de la propiedad cuando la página escargada y volcando en la propiedad el contenido del campo cuando se produce el submit de lapágina.

Por su parte, el botón “Aceptar” será generado mediante la acción commandButton, encuyo atributo action habrá que indicar, mediante notación EL, el nombre del métodocontrolador de acción que habrá que invocar cuando se produzca la pulsación del botón.Como ya se indicó con anterioridad, la activación de este tipo de controles provocaautomáticamente el submit o postback de la página.

He aquí el código completo de la página login.jsp:

<%@page contentType="text/html"%>

<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>

Page 14: JSF Basico

<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;

charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<br/><br/>

<center><h1>Página de validación</h1></center>

<f:view>

<h:form>

<table width="50%" align="center" border="0">

<tr>

<td>Nombre usuario:</td>

<td><h:inputText

value="#{credencialesBean.user}"/></td>

</tr>

<tr>

<td>Contraseña:</td>

<td><h:inputSecret

value="#{credencialesBean.password}"/></td>

</tr>

<tr>

<td colspan="2" align="center">

<h:commandButton value="Aceptar"

action="#{credencialesBean.doLogin}"/>

</td>

</tr>

</table>

</h:form>

</f:view>

</body>

</html>

Pudiera ocurrir que la pulsación de un botón de comando no tuviera que ejecutarningún código de servidor concreto, tan solo producir una navegación estática a unadeterminada vista de la aplicación. En este caso, basta con indicar como valor del atributoaction la cadena de caracteres asociada a la página destino en la regla de navegación.

Page 15: JSF Basico

En cuanto a la página valido.jsp encargada de mostrar los credenciales del usuarioválido, utiliza un elemento outputText para mostrar el valor de cada dato. Este elemento realizala misma función que una expresión JSP:

<%=expresion%>

En su atributo value se deberá indicar el valor a mostrar, que podrá ser una cadena detexto estática o una expresión EL que devuelva algún dato existente en cualquiera de losámbitos de aplicación. En este caso, se utiliza una expresión EL para acceder a laspropiedades del bean credencialesBean, que al tener ámbito de petición (request) es accesibledesde esta página. El código de la página valido.jsp se muestra en el siguiente listado:

<%@page contentType="text/html"%>

<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>

<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;

charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<f:view>

<h2>Sus datos:</h2>

Usuario: <h:outputText

value="#{credencialesBean.user}"/><br/>

Password: <h:outputText

value="#{credencialesBean.password}"/><br/>

</f:view>

</body>

</html>

En cuanto a la página novalido.jsp, su contenido se indica en el siguiente listado:

<%@page contentType="text/html"%>

<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>

<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

Page 16: JSF Basico

<meta http-equiv="Content-Type" content="text/html;

charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<f:view>

<h2>Error</h2>

El password <b><h:outputText

value="#{credencialesBean.password}"/>

</b> no es correcto

</f:view>

</body>

</html>

EJERCICIO 1

Seguidamente vamos a realizar una aplicación que permita recoger datos de unapersona y almacenarlos en una colección. así mismo, el programa permitirá al usuario ver losdatos de todas las personas que ha almacenado durante su sesión.

La página de inicio tendrá el aspecto que se indica en la figura 3.

Figura. 3.

El botón “Guardar” almacenará en la colección una nueva persona con los datossuministrados a través de los campos de texto, permaneciendo después el usuario en la mismapágina. Por otro lado, la pulsación del botón “Ver Todos” nos llevará a una nueva página dondese muestren los datos de todas las personas grabadas por ese usuario, tal y como se indica enla figura 4.

Page 17: JSF Basico

Figura. 4.

Para empezar, crearemos un bean gestionado llamado PersonaBean que encapsulelos datos de la persona e incluya un método doGuardar() que tenga como misión almacenar losdatos de la nueva persona en un objeto ArrayList. Este objeto será almacenado en un atributode sesión para que sea accesible desde todas las peticiones realizadas durante la sesión. Elsiguiente listado nos muestra el código de la clase PersonaBean:

package javabeans;import java.util.*;import javax.faces.context.FacesContext;import javax.servlet.http.*;public class PersonaBean { private String nombre; private long telefono; private int edad; public PersonaBean() { } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public long getTelefono() { return telefono; } public void setTelefono(long telefono) { this.telefono = telefono; } public int getEdad() { return edad; } public void setEdad(int edad) { this.edad = edad; } public String doGuardar(){ FacesContext context=FacesContext.getCurrentInstance(); HttpSession sesion=(HttpSession)context. getExternalContext().getSession(true); ArrayList<PersonaBean> listapersonas; listapersonas=(ArrayList<PersonaBean>)sesion. getAttribute("listapersonas"); //comprueba si ya existe la colección de personas

Page 18: JSF Basico

//en la sesión y si no es así la crea if(listapersonas==null){ listapersonas=new ArrayList<PersonaBean>(); sesion.setAttribute("listapersonas",listapersonas); } listapersonas.add(this); return null; }}

Podemos observar en la clase anterior como no hemos creado ningún método pararesponder a la pulsación del botón “Ver Todos”. El motivo es que este botón simplementegenera una navegación estática a la página del listado de personas, ver.jsp.

Otro detalle interesante es la devolución del valor null por el método doGuardar(). Estoes así porque tras ejecutar el método el usuario debe permanecer en la misma página, para loque basta con que el método devuelva un valor no definido en ninguno de los elementos<navigation-case>.

El siguiente listado corresponde al archivo de configuración faces-config.xml, dondepodemos observar el registro de PersonaBean así como las reglas de navegación:

<?xml version='1.0' encoding='UTF-8'?><!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"><faces-config> <managed-bean> <managed-bean-name>PersonaBean</managed-bean-name> <managed-bean-class> javabeans.PersonaBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <from-view-id>/grabadatos.jsp</from-view-id> <navigation-case> <from-outcome>ver</from-outcome> <to-view-id>/ver.jsp</to-view-id> </navigation-case> </navigation-rule></faces-config>

En cuanto a las vistas, el siguiente código corresponde a la página de solicitud dedatos, grabadatos.jsp:

<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%><%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head>

Page 19: JSF Basico

<body> <center><h1>Formulario de datos</h1></center> <f:view> <h:form> <table width="50%" align="center" border="0"> <tr> <td>Nombre:</td> <td><h:inputText value="#{PersonaBean.nombre}"/></td> </tr> <tr> <td>Teléfono:</td> <td><h:inputText value="#{PersonaBean.telefono}"/></td> </tr> <tr> <td>Edad:</td> <td><h:inputText

value="#{PersonaBean.edad}"/></td> </tr> <tr> <td colspan="2" align="center"> <h:commandButton value="Guardar" action="#{PersonaBean.doGuardar}"/> </td> </tr> <tr> <td colspan="2" align="center"> <h:commandButton value="Ver Todos" action="ver"/> </td> </tr> </table> </h:form> </f:view></html>

Obsérvese como el valor del atributo action del commandButton “Ver Todos” contieneúnicamente la cadena de texto asociada a la página ver.jsp en la regla de navegación.

En cuanto a ver.jsp, se ha utilizado la librería core de JSTL para recorrer la colecciónde objetos y mostrar sus propiedades en una tabla HTML. He aquí el código de la página:

<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <center><h1>Listado de personas</h1></center> <table border="1" align="center"> <tr> <th>Nombre</th>

Page 20: JSF Basico

<th>Teléfono</th> <th>Edad</th> </tr> <c:forEach var="per" items="${listapersonas}"> <tr> <td><c:out value="${per.nombre}"/></td> <td><c:out value="${per.telefono}"/></td> <td><c:out value="${per.edad}"/></td> </tr> </c:forEach> </table> </body></html>

EJERCICIO 2

En esta ocasión vamos a realizar un ejercicio que incluya acceso a datos. Se trata deuna página de registro que permita insertar usuarios en una tabla de clientes, tal y como seindica en la figura 5.

Figura. 5.

Cuando se pulse el botón “Grabar” se procederá a guardar los datos del nuevo clienteen la base de datos. Si la inserción del registro se ha realizado correctamente, se mostrará unapágina con un mensaje indicando dicha circunstancia, sino, se volverá a recargar la mismapágina de registro con un mensaje de error en la parte inferior de la misma.

El acceso a los datos lo aislaremos en una clase llamada Operaciones cuyo código semuestra en el siguiente listado:

package modelo;import java.sql.*;import javabeans.*;public class Operaciones { public Connection obtenerConexion() {

Page 21: JSF Basico

Connection cn=null; try{ Class.forName("com.mysql.jdbc.Driver"); cn=DriverManager.getConnection( "jdbc:mysql://localhost:3306/libreria"); } catch(Exception e){e.printStackTrace();} return cn; } public boolean insertarCliente(ClienteBean c){ boolean resultado=false; String sql="Insert into clientes values('"; sql+=c.getUsuario()+"','"; sql+=c.getPassword()+"','"; sql+=c.getEmail()+"',"; sql+=c.getTelefono()+")"; try{ Connection cn=obtenerConexion(); Statement st=cn.createStatement(); st.execute(sql); cn.close(); resultado=true; } catch(Exception e){c.setTextoError(

"error en los datos!"); e.printStackTrace();} return resultado; }}

Por su parte, utilizaremos un bean gestionado al que llamaremos “ClienteBean” paracapturar los datos del nuevo cliente. Este bean, contará además con un método que seráejecutado como respuesta al comando de acción, y que será el encargado de operar con elmodelo.

A continuación se indica el código de esta clase:

package javabeans;

import modelo.*;public class ClienteBean { private String usuario; private String password; private String email; private long telefono; private String textoError; public ClienteBean() { } public String getUsuario() { return usuario; }

public void setUsuario(String usuario) { this.usuario = usuario; }

public String getPassword() { return password; }

Page 22: JSF Basico

public void setPassword(String password) { this.password = password; }

public String getEmail() { return email; }

public void setEmail(String email) { this.email = email; }

public long getTelefono() { return telefono; }

public void setTelefono(long telefono) { this.telefono = telefono; }

public String getTextoError() { return textoError; }

public void setTextoError(String textoError) { this.textoError = textoError; } public String grabar(){ Operaciones op=new Operaciones(); if(op.insertarCliente(this)){ return "ok"; } else{ return "mal"; } }}

En cuanto a la página de registro, el siguiente listado corresponde al código JSP de lamisma:

<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%><%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body>

<f:view> <h1>Página de registro</h1> <h:form>

Page 23: JSF Basico

<table> <tr> <td>Usuario:</td> <td><h:inputText value="#{ClienteBean.usuario}"/></td> </tr> <tr> <td>Password:</td> <td><h:inputText value="#{ClienteBean.password}"/></td> </tr> <tr> <td>Email:</td> <td><h:inputText value="#{ClienteBean.email}"/></td> </tr> <tr> <td>Teléfono</td> <td><h:inputText value="#{ClienteBean.telefono}"/></td> </tr> <tr> <td colspan="2" align="center"> <h:commandButton value="Grabar" action="#{ClienteBean.grabar}"/> </td> </tr> <h2> <h:outputText value="#{ClienteBean.textoError}"/> </h2> </table> </h:form> </f:view> </body></html>

Obsérvese el uso del tag <h:outputText> para mostrar el mensaje de error.

El siguiente será el listado de la página que se muestra cuando el usuario ha sidoregistrado correctamente:

<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body>

<h1>El usuario ha sido registrado correctamente!</h1>

</body>

Page 24: JSF Basico

</html>

En cuanto a faces-context.xml, el siguiente listado muestra el contenido del mismodonde se refleja el registro del bean y la regla de navegación:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config> <managed-bean> <managed-bean-name>ClienteBean</managed-bean-name> <managed-bean-class>javabeans.ClienteBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <from-view-id>/registro.jsp</from-view-id> <navigation-case> <from-outcome>ok</from-outcome> <to-view-id>/registrado.jsp</to-view-id> </navigation-case> </navigation-rule>

</faces-config>

4. EVENTOS DE ACCIÓN (ACTIONEVENT)La activación de un botón o enlace generado mediante un control de comando, además

de provocar el submit de la página genera un evento, conocido como evento de acción al quese puede asociar un método escuchador en alguna de las clases Java del servidor.

Normalmente, estos métodos escuchadores se codifican en el bean gestionado juntocon los métodos controladores de acción.

Así pues, nos encontramos con que un control de comando puede tener asociado dostipos de métodos que serán ejecutados como respuesta a su activación: los controladores deacción y los escuchadores de acción.

Es importante tener en cuenta las diferencias entre ambos métodos:

Los controladores de acción realizan operaciones de aplicación, relacionadascon la funcionalidad de esta (aunque normalmente se suele aislar toda la lógicade negocio en el Modelo), mientras que los escuchadores de acción se utilizanpara realizar algún tipo de actuación sobre la interfaz gráfica. Para ello, losmétodos de escuchadores reciben como parámetro un objetojavax.faces.event.ActionEvent que proporciona información sobre el componenteque produjo el evento.

Los controles de acción afectan a las reglas de validación, mientras que losescuchadores no. Un método escuchador no devuelve ningún resultado.

Page 25: JSF Basico

Los escuchadores de acción pueden ser ejecutados antes de procederse a lavalidación de los datos (según valor del atributo inmediate), mientras que, comoya sabemos, los controladores de acción siempre son ejecutados después deque esta validación se haya realizado.

Para asociar a un control de comando el correspondiente método escuchador, seemplea el atributo actionListener de la etiqueta correspondiente. Por ejemplo, la siguienteinstrucción genera un commandButton al que asocia el método “limpiar” definido en el bean“DatosBean”, como respuesta a su evento de acción:

<h:commandButton value=“Reset”

actionListener= “#{DatosBean.limpiar}”/>

El formato del método limpiar sería:

public void limpiar (ActionEvent e){

//código

}

Mediante el atributo boolean inmediate de commandButton se puede especificar elmomento exacto en que queremos ejecutar el método escuchador. Si su valor es true, laejecución se producirá antes de que los datos sean validados, mientras que si es false seejecutará después de que los datos hayan sido almacenados en el bean al final del ciclo devida de la petición, justo antes de la ejecución del controlador de acción.

4.1. INFORMACIÓN SOBRE EL EVENTO: LAS CLASES ACTIONEVENT YUICOMPONENT

Es habitual que desde un método escuchador se quiera acceder a los objetos gráficosde la interfaz.

Para este fin, el método getComponent() de la clase ActionEvent (método heredado dela subclase FacesEvent) devuelve un objeto UIComponent que representa el componenteorigen del evento.

UIComponent es la clase base de todos los componentes de interfaz de usuario deJSF. Esta clase dispone un amplio conjunto de métodos con los que podemos acceder adiversas propiedades gráficas de interés no sólo del componente en el que se ha producido elevento, sino también del resto de objetos de la interfaz.

Aunque más adelante estudiaremos con más detenimiento la clase UIComponent y sussubclases específicas correspondientes a los distintos componentes gráficos JSF,comentaremos a continuación algunos de los métodos más importantes incluidos en esta clase.Entre ellos se encuentran:

String getId(). Devuelve un String con el valor del atributo id del componente.

UIComponent getParent(). Devuelve el componente padre del objeto.

List getChildren(). Devuelve la colección con todos los hijos del componente.

UIComponent findComponent(String id). Este método intenta localizar en lamisma interfaz un componente cuyo id se especifica. Este método resultabastante útil para acceder desde el método manejador de evento al resto de loscomponentes del formulario.

Page 26: JSF Basico

void setRendered(boolean render). Establece la propiedad rendered delcomponente. Esta propiedad indica si el componente será o no renderizado(generado dentro de la interfaz) al ser enviada la página al cliente.

Veamos un ejemplo de utilización de eventos de acción en el ejercicio anterior dealmacenamiento y visualización de personas.

La modificación consistirá en hacer inicialmente invisible el botón “Ver Todos” para queno se pueda acceder a la lista de personas hasta que no se haya guardado al menos una. Alpulsar el botón “Guardar” se procederá a hacer visible el botón “Ver Todos” la próxima vez quese muestre la página.

Para hacer invisible inicialmente el botón “Ver Todos” simplemente tenemos queestablecer el valor false en el atributo rendered del componente, así mismo, estableceremos unvalor a su atributo id para poder referirnos después al componente desde código:

<h:commandButton id="vertodos" rendered="false"

value="Ver Todos" action="ver"/>

La visualización del botón la programaremos en el evento ActionListener del botón“Guardar”:

<h:commandButton value="Guardar"

actionListener="#{PersonaBean.doHabilitar}"

action="#{PersonaBean.doGuardar}" />

Como vemos, se vincula este evento con un nuevo método doHabilitar() definido en laclase PersonaBean, he aquí el código de este método:

public void doHabilitar(ActionEvent ev){

UIComponent cp=ev.getComponent();

UIComponent btnver=cp.findComponent("vertodos");

btnver.setRendered(true);

}

5. CICLO DE VIDA DEL PROCESAMIENTO DE UNAPETICIÓN JSFEn este contexto entendemos por ciclo de vida el proceso que tiene lugar desde que el

controlador FacesServlet recibe una petición procedente del navegador cliente hasta quedevuelve la respuesta apropiada.

Es importante tener en cuenta que las fases por las que pase este proceso variaran enfunción de si la petición ha sido enviada desde una página generada previamente por elframework JSP (postback) o no. En este último caso hablaríamos de petición inicial, pues serefiere a aquellos casos en los que la petición se realiza mediante la introducción de la URLdirectamente en el navegador, o al activar un vínculo de alguna página HTML estática.

Page 27: JSF Basico

La figura 6 muestra las diferentes fases que tienen lugar durante el ciclo de vida de lapetición.

Figura. 6.

Tal como se puede apreciar, en el caso que se trate de una petición inicial las fases 2al 5 serán omitidos, pasando directamente a la última fase encargada de generar la respuestaal usuario.

Seguidamente analizaremos las acciones que tienen lugar en cada una de estas seisfases.

5.1. RESTORE VIEW.

Durante esta primera fase, se intenta recuperar el estado del cliente. El estado delcliente está formado por el conjunto de objetos gráficos UIxxx que forman la interfaz gráfica dela página desde la que se realiza la petición y que durante la anterior petición fue salvado por elframework (normalmente en el objeto session), luego este estado solo ha podido seralmacenado anteriormente si no se trata de una petición inicial.

Lógicamente, en caso de que se trate de una petición inicial el estado anterior noexistirá, procediéndose a crear un nuevo árbol del componentes asociado a la páginasolicitada.

El árbol de componentes consta de un objeto raíz UIViewRoot que no está asociado aningún elemento visual concreto. De él colgarán los distintos objetos gráficos de la página(formularios, botones, etc.). La figura 7 muestra un árbol de componentes de ejemplo formadopor tres elementos gráficos.

FacesServlet Restore ViewPetición

Apply Request Values

Process Validations

Update Model Values

Invoke Application

Render ResponseRespuesta

Page 28: JSF Basico

Figura. 7.

Una vez que se dispone del árbol de componentes (nuevo o recuperado), se procede aalmacenarlo en el contexto de aplicación (FacesContext).

Tras realizar esta operación se pasa a la siguiente fase que, en el caso de una peticióninicial, será la última fase del ciclo (Render Response), mientras que si es un postback será lasiguiente del ciclo (Apply Request Values).

5.2. APPLY REQUEST VALUES

El propósito de esta fase es permitir que el árbol de componentes pueda alimentarsecon los datos procedentes de la petición. Durante esta fase, además, son ejecutados losmétodos escuchadores de evento para todos aquellos componentes en los que el atributoinmediate se haya establecido al valor true. Para aquellos en los que el valor de dicho atributosea false, los eventos generados serán enviados a una cola de la cual serán extraídos durantela penúltima fase del ciclo para la ejecución de sus métodos escuchadores en el ordenproducido.

5.3. PROCESS VALIDATION

Una vez actualizados los valores de los componentes, se procede a la validación de losdatos mediante el procesado de los validadores y conversores asociados a cada componentes(más adelante veremos el uso de estos elementos).

Si el proceso de validación de alguno de los componentes falla se dará por terminadoel procesamiento de la petición y se pasará a la última fase del ciclo.

5.4. UPDATE MODEL VALUES

Durante esta fase, todos los valores recibidos en la petición y que ya han sidocorrectamente validados y convertidos, son asignados a los correspondientes propiedades delos beans gestionados, según se indica en el atributo value de cada componente gráfico.

Si durante este proceso de asignación se produce algún error, el procesamiento de lapetición se dará por terminado y se pasará a la última fase del ciclo.

5.5. INVOKE APPLICATION

Se procederá a la ejecución de los métodos escuchadores de los eventos encolados,siguiendo el orden en que dichos eventos se han producido.

Finalmente, se ejecutará el método controlador de acción, cuyo valor de devoluciónserá utilizado por FacesServlet para determinar la siguiente página a ejecutar, finalizando eneste punto el procesamiento de la petición.

HtmlForm

UIViewRoot

HtmlTextBoxButtonHtmlCommandButton

Page 29: JSF Basico

Si el valor devuelto por el método controlador es null, o no coincide con ninguno de losvalores definidos en las reglas de navegación o, simplemente, no existe el método controlador,se procederá a la ejecución de la siguiente y última fase. En este caso pues, la respuesta querecibirá el cliente será la propia página desde la que lanzó la petición.

5.6. RENDER RESPONSE

El propósito de esta fase es preparar la respuesta para el usuario, la cual es generadadirectamente a partir de las codificaciones definidas por los renderizadores asociados a cadauno de los componentes del árbol.

Por defecto, cada componente lleva asociado un renderizador que se encarga detransformar el componente en su correspondiente bloque de etiquetas XHTML. No obstante, através del archivo de configuración faces-config.xml pueden especificarse otros kits derenderización que transformen los componentes en otros formatos.

6. COMPONENTES GRÁFICOS JSFEs el momento de enfocar nuestro estudio en el conjunto de componentes gráficos

proporcionados por el framework JSF.

La existencia de estos componentes o bloques prefabricados, además de facilitar lacreación de aplicaciones gráficas complejas, permite a los desarrolladores centrarse en lalógica de aplicación en vez de estar ocupados en las tareas de generación de respuestas. Lafigura 8 nos muestra un diagrama con las principales clases de componentes UI de JSF, todasellas se encuentran en el paquete javax.faces.component.

Figura. 8.

Una de las principales características del API de componentes de JSF es queproporciona una gran cantidad de métodos para manipular la interfaz gráfica, sin preocuparnospor el aspecto concreto que dichos componentes tendrán durante su presentación.

Por eso, aunque mayoritariamente se utilizarán los componentes JSF para la creaciónde interfaces basadas en HTML, su uso no está ni mucho menos limitado a este estándar depresentación; si se dispone del renderizador apropiado, un componente JSF puede adoptarmúltiples formas a la hora de ser presentado.

UIComponentBase

UICommand UIOutput

UIInput

UIForm

UISelectOne UISelectMany

UIComponent

UISelectBoolean

UIData UIPanel UIViewRoot

Page 30: JSF Basico

Esta capacidad de los componentes UI JSF para ser presentados de diferentes formases aplicable también incluso dentro de un mismo estándar de presentación. Por ejemplo, elcomponente UISelectOne representa un elemento de selección simple, que en el caso concretode HTML puede ser implementado como un ListBox de selección simple, un ComboBox o unconjunto de botones de radio.

6.1. RENDERIZACIÓN

La renderización es el proceso mediante el cual un determinado componente UI estransformado en un control específico correspondiente a un determinado lenguaje de marcado.

En el caso de los componentes UI JSF, como ya sabemos, la funcionalidad de losmismos está separada de los detalles de presentación, así, mientras que la funcionalidad esimplementada por el propio componente UI, los detalles de presentación son proporcionadospor el renderizador.

Un renderizador es el objeto que contiene los detalles de presentación de undeterminado tipo de componente, proporcionando los tags apropiados según el lenguaje demarcado que se vaya a utilizar para la presentación en cliente.

Los renderizadores se encuentran agrupados en lo que se conoce como un kit derenderización o RenderKit.

Un RenderKit es una colección de renderizadores que utilizan una tecnología común depresentación para los controles de la interfaz, como por ejemplo HTML.

La especificación JSF proporciona un kit de renderización estándar que incluye unconjunto de renderizadores para la generación de marcado HTML. Este RenderKit estándar seencuentra asociado por defecto a cualquier aplicación JSF, de modo serán aplicados susrenderizadores a la hora de construir la interfaz. No obstante, es posible registrar otrosRenderKits en una aplicación o, incluso, definir kits de renderización personalizados.

En la figura 9 se indican algunas de las clases que utilizan los rederizadores del kitestándar. Como vemos, se trata de subclases de los componentes UI de JSF que añadendetalles específicos para la presentación en HTML.

6.2. TAGS DE COMPONENTES JSF

La especificación JSF incluye una librería de acciones o tags JSP para la inclusión decomponentes gráficos JSF dentro de una página JSP. De forma predeterminada, estasacciones se encuentran asociadas al kit de renderizadores específicos HTML. En la tabla defigura 10 se muestra la equivalencia entre cada componente HTML y el tag que lo genera.

Page 31: JSF Basico

Figura. 9.

Figura. 10.

Seguidamente, vamos a analizar con más detalle cada uno de estos tags, así como lascaracterísticas de los controles que generan.

UICommand UIOutput

UIInput

UIForm

UISelectOne UISelectMany

HTMLCommandButton

HTMLCommandLinkHTMLInputSecret

HTMLInputText

HTMLInputTextArea

HTMLSelectOneRadio

HTMLSelectOneMenu

HTMLSelectOneListBox

HTMLSelectManyCheckBox

HTMLSelectManyMenu

HTMLSelectManyListBox

HTMLForm

UISelectBoolean

HTMLSelectBooleanCheckBox

controles de comando

controles de selección simple

controles de selección múltiple controles de texto

Casilla de verificación<h:selectBooleanCheckBox ..>HTMLSelectBooleanCheckBox

Conjunto de casillas de verificación

<h:selectManyCheckbox ..>HTMLSelectManyCheckBox

Conjunto de botones de radio

<h:selectOneRadio ..>HTMLSelectOneRadio

Lista desplegable<hselectOneMenu ..>HTMLSelectOneMenu

Caja de texto multilínea<h:inputTextarea ..>HTMLInputTextArea

Lista normal<h:selectOneListbox ..>HTMLSelectOneListBox

Lista desplegable de selección múltiple

<h:selectManyMenu ..>HTMLSelectManyMenu

Campo de texto<h:inputText ..>HTMLInputText

Campo de texto con caracteres ocultos

<h:inputSecret ..>HTMLInputSecret

Lista normal de selección múltiple

<h:selectManyListbox ..>HTMLSelectManyListBox

Enlace HTML<h:CommandLink ..>HTMLCommandLink

Botón submit<h:CommandButton..>HTMLCommandButton

Tipo de controlTag JSFComponente HTML

Casilla de verificación<h:selectBooleanCheckBox ..>HTMLSelectBooleanCheckBox

Conjunto de casillas de verificación

<h:selectManyCheckbox ..>HTMLSelectManyCheckBox

Conjunto de botones de radio

<h:selectOneRadio ..>HTMLSelectOneRadio

Lista desplegable<hselectOneMenu ..>HTMLSelectOneMenu

Caja de texto multilínea<h:inputTextarea ..>HTMLInputTextArea

Lista normal<h:selectOneListbox ..>HTMLSelectOneListBox

Lista desplegable de selección múltiple

<h:selectManyMenu ..>HTMLSelectManyMenu

Campo de texto<h:inputText ..>HTMLInputText

Campo de texto con caracteres ocultos

<h:inputSecret ..>HTMLInputSecret

Lista normal de selección múltiple

<h:selectManyListbox ..>HTMLSelectManyListBox

Enlace HTML<h:CommandLink ..>HTMLCommandLink

Botón submit<h:CommandButton..>HTMLCommandButton

Tipo de controlTag JSFComponente HTML

Page 32: JSF Basico

6.2.1. Formulario

Todos los componentes gráficos encargados de la captura de datos deben estarincluidos en un formulario HTML, cuya generación corre a cargo del tag <h:form>. Los valoresde los atributos method y action del formulario se encuentran implícitamente establecidosPOST y a la URL de la página actual, respectivamente. El elemento <h:form> no dispone deningún atributo para establecer estos valores, por lo que no podrán ser modificados por elprogramador.

En el interior de este elemento se incluirán los tags de controles gráficos.

6.2.2. Controles: atributos comunes.

Hay una serie de atributos que presentan todos los tags para la generación decontroles gráficos y que tienen el mismo significado en todos ellos. He aquí los másimportantes:

id. Identificador del elemento. Representa un identificador único para cada objetoexistente en el formulario. Como ya vimos anteriormente al estudiar alguno delos métodos de la clase UIComponent, este identificador puede ser utilizadodesde código para referirse a un determinado componente desde métodos comofindComponent().

rendered. Especifica si el control será renderizado inicialmente o no. Tal y comocomprobamos en el ejercicio 2, este atributo puede ser modificado a través delmétodo serRedered() de cada componente.

6.2.3. Campos de texto

Los campos de texto son componentes de tipo UIInput y se utilizan para solicitar laentrada de datos al usuario. En una interfaz gráfica HTML podemos utilizar cuatro campos detexto: Text, Textarea, Secret y Hidden, los cuales son generados por los tags <h:inputText>,<h:inputTextarea>, <h:inputSecret> e <h:inputHidden>, respectivamente.

Todos estos tags disponen de un atributo value que es utilizado en un doble sentido:

Para asignar un valor inicial al campo a partir de la propiedad de un beangestionado.

Para volcar en la propiedad de un bean gestionado el contenido del campo unavez que se produzca el submit de la página.

Se utilizará la notación EL para indicar en el atributo value la propiedad del beanimplicada en las operaciones anteriores:

<h:inputText value=“#{bean.propiedad}” />

Además del atributo value, estos tags disponen de otro atributo de tipo boolean llamadorequired, de modo que si este atributo es true será obligatorio que el usuario suministre unvalor al campo; de no hacerlo, la página será recargada de nuevo y se generará unmensaje de error. Más adelante, en el capítulo dedicado a los conversores y validadoresanalizaremos con detalle este punto.

El valor de este atributo puede ser modificado dinámicamente utilizando e métodosetRequired() proporcionado por la clase UIInput.

Page 33: JSF Basico

6.2.4. Controles de comando

Se trata de componentes UICommand cuya misión es, como ya hemos tenidooportunidad de ver, generar el envío de datos del formulario cuando son activados.

Tenemos dos clases de renderización específica HTML para este componente:HTMLCommandButton y HTMLLinkButton, que son generados mediante los tags<h:commandoButton> y <h:linkButton>, respectivamente. Se trata de dos maneras distintas derealizar esta operación de envío de datos desde la página: mediante la pulsación de un botón omediante la activación de un enlace.

Además del atributo value, utilizado para indicar el texto del enlace o botón, estoscontroles disponen como atributos más importantes action, actionListener e inmediate, cuyossignificados ya han sido estudiados con anterioridad.

6.2.5. Generación de texto

Se trata de un objeto cuya misión es presentar un texto estático en la página. Segenera mediante el tag <h:outputText> que corresponde al control HTMLOutputText, subclasede UIOutput. Mediante el atributo value se establece el texto a mostrar. Este atributo puedetener dos tipos de valores:

Una cadena de caracteres que represente el texto a mostrar.

Una expresión EL que indique la propiedad del bean cuyo contenido se va a mostrar.Por ejemplo, el siguiente tag mostraría en contenido de la propiedad mensaje de un bean:

<h:outputText value=“#{ErrorBean.mensaje}” />

6.2.6. Casillas de verificación

La casilla de verificación corresponde a un componente de tipo UISelectOneBoolean ycuya presentación corre a cargo del tag <h:selectBooleanCheckbox>.

Su atributo value permite vincular el estado del control a una propiedad boolean de unbean gestionado.

Mediante el método setSelected() de la clase UISelectOneBoolean es posible modificarel estado del control desde código.

6.2.7. Listas de selección única

La selección de un elemento dentro de un conjunto constituye una funcionalidad típicade cualquier aplicación Web. Dicha funcionalidad es proporcionada en JSF por el componenteUISelectOne, el cual puede ser renderizado de tres formas diferentes en una página:

Como una lista simple. Representada por el renderizador específicoHTMLSelectOneListbox, es generada mediante el tag <h:selectOneListbox>.

Como una lista desplegable. Representada por el renderizador específicoHTMLSelectOneMenu, es generada mediante el tag <h:selectOneMenu>.

Como un conjunto de botones de radio. Representado por el renderizadorespecífico HTMLSelectOneRadio, es generado mediante el tag<h:selectOneRadio>.

Page 34: JSF Basico

Los tres tags disponen de un atributo value que permite indicar la propiedad del beangestionado donde será almacenado el valor del elemento seleccionado, una vez se produzca elsubmit de la página.

6.2.7.1. Componentes de una lista

Los elementos contenidos una lista de selección son objetos de tipojavax.faces.model.SelectItem. Cada uno de estos objetos encapsula el valor y el texto amostrar del elemento que representa.

Existen dos maneras de indicar durante la fase de diseño de la aplicación el conjuntode objetos SelectItem que formará la lista:

Mediante componentes UISelectItem. Cada componente UISelectItem generaun elemento SelectItem. Los componentes UISelectItem son incluidos dentro dela lista mediante el tag <f:selectItem>. Cada tag de este tipo dispone de dosatributos:

- itemLabel. Texto que se va a mostrar para el elemento.

- itemValue. Valor asociado al elemento.

Así pues, deberán anidarse tantos <f:selectItem> dentro del tag que genera lalista como elementos vaya a contener ésta. El siguiente bloque crearía unListBox en la página con los días laborables de la semana:

<h:selectOneListbox id="lista">

<f:selectItem itemLabel="lunes" itemValue="1"/>

<f:selectItem itemLabel="martes" itemValue="2"/>

<f:selectItem itemLabel="miércoles" itemValue="3"/>

<f:selectItem itemLabel="jueves" itemValue="4"/>

<f:selectItem itemLabel="viernes" itemValue="3"/>

</h:selectOneListbox>

Como podemos observar, esta forma de generar una lista de opciones esadecuada cuanto el contenido de la lista es estático (no será modificado) y esconocido durante la fase de diseño de la aplicación.

Mediante un componente UISelectItems. Cuando el contenido de la lista va aser generado de forma dinámica podemos hacer uso de este componente, cuyafunción es la de crear un conjunto de objetos SelectItem dentro de la lista. Elcomponente UISelectItems se genera con el tag <f:selectItems> que, mediantesu atributo value, deberá indicar la propiedad del bean gestionado donde estácontenido el conjunto de objetos SelectItem. Este conjunto puede ser tanto unarray como una colección de objetos SelectItem.

Por ejemplo, las siguientes tags generarían un conjunto de botones de radio conlas opciones disponibles en una colección de objetos SelectItem almacenada enla propiedad “turnos” del bean CursosBean:

<h:selectOneRadio value="#{CursosBean.seleccionado}" >

<f:selectItems value="#{CursosBean.turnos}"/>

</h:selectOneRadio>

Page 35: JSF Basico

Por su parte, el bloque de código que genera el contenido de la propiedad turnosdel bean podría estar implementado de la siguiente manera:

class CursosBean{

private List<SelectItem> turnos;

:

public CursosBean(){

turnos = new ArrayList<SelectItem>();

turnos.add(new SelectItem(0, “mañana”));

turnos.add(new SelectItem(1, “tarde”));

turnos.add(new SelectItem(2, “noche”));

}

:

public List<SelectItem> getTurnos(){

return turnos;

}

:

}

Podemos observar como durante la creación del los objetos SelectItem se pasacomo parámetros al constructor, en este orden, el valor asociado al elemento y eltexto a mostrar.

6.2.8. Listas de selección múltiple

La funcionalidad de las listas de selección múltiple es suministrada por el componenteUISelectMany, pudiendo ser renderizado de tres formas diferentes en una página:

Como una lista de selección múltiple. Representada por el renderizadorespecífico HTMLSelectManyListbox, es generada mediante el tag<h:selectManyListbox>.

Como una lista de selección múltiple y una línea de altura. En cuanto atamaño es similar a las listas desplegables, si bien se muestra siempre abiertacon dos flechas para realizar desplazamientos arriba y abajo. Está representadapor el renderizador específico HTMLSelectManyMenu, que es generadomediante el tag <h:selectManyMenu>.

Como un conjunto de casillas de verificación. Representado por elrenderizador específico HTMLSelectManyCheckbox, es generado mediante eltag <h:selectManyCheckbox>.

El atributo value deberá especificar la propiedad del bean donde se almacenarán losvalores de los elementos seleccionados. En este caso, dicha propiedad tendrá que ser de tipoarray o colección.

En cuanto a la creación del contenido de la lista, se utilizan exactamente las mismastécnicas que en las listas de selección simple.

Page 36: JSF Basico

6.3. EL EVENTO VALUECHANGEEVENT

El evento ValueChangeEvent se produce en todos los componentes de tipo UIInput,como las listas simples, listas desplegables o cajas de texto y tiene lugar cuando se produce uncambio en el dato de entrada del componente. Por ejemplo, en el caso de las cajas de textoeste evento se produce cada vez que se modifica el contenido del campo, mientras que en laslistas se produce al seleccionar un nuevo elemento.

A diferencia de ActionEvent, el evento ValueChangeEvent no produce el submit dela página; todos los eventos de este tipo producidos en los distintos componentes de la interfazquedan añadidos a una cola para después proceder a la ejecución de sus métodos derespuesta una vez que se lance la petición al servidor.

Al igual que sucede con ActionEvent, los métodos de respuesta a los eventosValueChangeEvent pueden ser codificados en alguno de los beans gestionados. Estosmétodos deberán tener el formato:

public void metodoRespuesta(ValueChangeEvent ev)

A través de las propiedades del objeto ValueChangeEvent podemos acceder ainformación de interés sobre el evento. Entre ellas destacan:

getComponent(). Al igual que en ActionEvent, nos devuelve una referencia alcomponente donde se ha producido el evento.

getOldValue(). Devuelve el valor anterior del componente, antes de producirseel evento.

getNewValue(). Devuelve el nuevo valor del componente.

Por otro lado, la vinculación entre el control y el método manejador de eventocorrespondiente se realizará a través del atributo valueChangeListener del tag. El siguienteejemplo asociaría el evento de cambio de turno al método actualiza() del bean CursosBean:

<h:selectOneRadio value="#{CursosBean.seleccionado}"

valueChangeListener="#{CursosBean.actualiza}">

<f:selectItems value="#{CursosBean.turnos}"/>

</h:selectOneRadio>

EJERCICIO 3

En este ejercicio vamos a desarrollar una aplicación para una tienda de ordenadores,consistente en una página de inicio que permita al usuario configurar su equipo, permitiéndoleelegir un módulo de memoria de una lista y una serie de accesorios adicionales, tal y como seindica en la figura 11.

Page 37: JSF Basico

Figura. 11.

Así mismo, se le permitirá indicar la forma de pago elegida, de modo que si elige“transferencia” se le aplicará un descuento en el precio final de un 10%.

Al pulsar calcular se mostrará en una nueva página el precio final según laconfiguración elegida (figura 12).

Figura. 12.

Hay que tener en cuenta que se parte de un precio base de 300 euros, al que habráque añadir los precios de la memoria y los accesorios, los cuales están almacenados en unabase de datos.

Inicialmente, crearemos una clase que formará parte del modelo, encargada de obtenerlas listas de precios para poder vincularlas a los controles de lista. Esta clase que llamaremosPreciosBean corresponderá al siguiente listado:

package javabeans;

import java.util.*;import javax.faces.model.*;import java.sql.*;public class PreciosBean { private List<SelectItem> memoria; private List<SelectItem> accesorios;

Page 38: JSF Basico

public Connection obtenerConexion() { Connection cn=null; try{ Class.forName("com.mysql.jdbc.Driver"); cn=DriverManager.getConnection(" jdbc:mysql://localhost:3306/ordenadores"); } catch(Exception e){e.printStackTrace();} return cn; } public List<SelectItem> getMemoria(){ //obtiene la lista de precios de los //módulos de memoria String sql=""; ArrayList<SelectItem> totales= new ArrayList<SelectItem>(); try{ Connection cn=obtenerConexion(); Statement st=cn.createStatement(); sql="SELECT capacidad, precio FROM memoria"; ResultSet rs=st.executeQuery(sql); while(rs.next()){ totales.add(new SelectItem( rs.getString("precio"),rs.getString("capacidad"))); } cn.close(); } catch(Exception e){e.printStackTrace();} finally{memoria=totales;return memoria;} } public List<SelectItem> getAccesorios(){ //obtiene la lista de precios de los //accesorios String sql=""; ArrayList<SelectItem> totales= new ArrayList<SelectItem>(); try{ Connection cn=obtenerConexion(); Statement st=cn.createStatement(); sql="SELECT nombre, precio FROM accesorios"; ResultSet rs=st.executeQuery(sql); while(rs.next()){ totales.add(new SelectItem( rs.getString("precio"),rs.getString("nombre"))); } cn.close(); } catch(Exception e){e.printStackTrace();} finally{accesorios=totales; return accesorios;} }

public void setMemoria(List<SelectItem> memoria) { this.memoria = memoria; }

public void setAccesorios(List<SelectItem> accesorios) { this.accesorios = accesorios; }}

Page 39: JSF Basico

Por otro lado, la clase bean que capturará la configuración elegida, a la que llamaremosConfiguracionBean, tendrá el siguiente código:

package javabeans;

import javax.faces.event.*;import javax.faces.component.*;import javax.faces.component.html.*;public class ConfiguracionBean {

private String preciomemoria; private String[] precioaccesorios; private String envio; private double preciofinal=300; private String datosconfiguracion;

public String getPreciomemoria() { return preciomemoria; }

public void setPreciomemoria(String preciomemoria) { this.preciomemoria = preciomemoria; }

public String[] getPrecioaccesorios() { return precioaccesorios; }

public void setPrecioaccesorios(String[] precioaccesorios) { this.precioaccesorios = precioaccesorios; }

public String getEnvio() { return envio; }

public void setEnvio(String envio) { this.envio = envio; }

public String getDatosconfiguracion() { return datosconfiguracion; }

public void setDatosconfiguracion(String datosconfiguracion) { this.datosconfiguracion = datosconfiguracion; }

public String calcular(){ setPreciofinal(getPreciofinal()+Integer.parseInt( this.getPreciomemoria())); for(String p:this.precioaccesorios){ setPreciofinal(getPreciofinal() + Integer.parseInt(p)); } if(Integer.parseInt(envio)==1){ setPreciofinal(getPreciofinal() * 0.9); }

Page 40: JSF Basico

return "resultado"; } public double getPreciofinal() { return preciofinal; }

public void setPreciofinal(double preciofinal) { this.preciofinal = preciofinal; }

}

Seguidamente se muestran los listados con las vistas de la aplicación:

index.jsp

<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%><%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <f:view> <h:form> <h1>Configuración de Equipo Informático</h1> <br/><br/> <table> <tr> <td><b>Memoria:</b></td> <td><h:selectOneMenu id="memoria" value="#{ConfiguracionBean.preciomemoria}"> <f:selectItems value="#{PreciosBean.memoria}"/> </h:selectOneMenu></td>

<td><b>Accesorios:</b><br/></td> <td><h:selectManyCheckbox id="accesorios" value="#{ConfiguracionBean.precioaccesorios}"> <f:selectItems value="#{PreciosBean.accesorios}"/> </h:selectManyCheckbox</td> </tr> <tr> <td><br/><b>Forma de pago:</b></td> <td><br/><h:selectOneRadio id="pago" value="#{ConfiguracionBean.envio}"> <f:selectItem itemLabel="Transferencia" itemValue="1"/> <f:selectItem itemLabel="Contra reembolso" itemValue="2"/>

Page 41: JSF Basico

</h:selectOneRadio></td> <td></td> <td></td> </tr> <tr> <td colspan="4" align="center"><br/> <h:commandButton value="Calcular" action="#{ConfiguracionBean.calcular}"/> </td> </tr> </table> </h:form> </f:view>

</body></html>

resultado.jsp

<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%><%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <f:view> <h1>Configuración elegida</h1>

<br/><br/> <h3>El precio final es de: <h:outputText value="#{ConfiguracionBean.preciofinal}"/> eur.</h3> </f:view>

</body></html>

7. CONVERSORES Y VALIDADORESEl proceso de conversión y validación de datos es una tarea sumamente importante

dentro de una aplicación Web, pues tiene como objetivo adaptar la información suministradapor el usuario mediante los campos de la interfaz a los tipos y características de los datosmanejados por la aplicación.

Como tuvimos oportunidad de ver durante el análisis del ciclo de vida de una peticiónJSF, este proceso tiene lugar durante la segunda fase del ciclo llamada Proccess Validation.Según se indicó entonces, cualquier error en la validación o conversión de alguno de los

Page 42: JSF Basico

campos producirá el fin del procesado de la petición y la recarga de la página desde la que selanzó la petición, indicando se en la misma los mensajes de error generados durante elproceso.

Seguidamente vamos a analizar de manera independiente las distintas técnicas quenos ofrece la tecnología JSF para realizar las conversiones y validaciones de datos en unaaplicación.

7.1. VALIDADORES

La validación de datos consiste en comprobar la validez de un campo de entrada antesde proceder a la asignación del mismo a la propiedad del bean correspondiente.

Dejando a un lado la validación manual de datos que siempre podríamos incluir en losmétodos set del JavaBean, JSF nos ofrece la siguientes técnicas de validación de datos:

Validación automática.

Utilización de validadores implícitos JSF.

Métodos de validación personalizados.

7.1.1. Validación automática

La validación automática no requiere ninguna acción por parte del programador,aunque afecta únicamente a los tipos de datos y a la obligatoriedad de incluir valores en loscampos.

Por ejemplo, si un determinado campo está asociado a una propiedad int de un bean,JSF intentará realizar la conversión de los caracteres introducidos a int. Si algún carácter no esnumérico, se producirá un error de validación en el campo.

En cuanto a la obligatoriedad de incluir valores en un campo, todos los tags quegeneran componentes UIInput disponen de un atributo llamado required, de modo que si ésteestá establecido a true será obligatorio introducir un valor en el campo. Si el usuario dejaen blanco un campo de estas características se detectará este hecho durante la fase ProcessValidator y se procederá a abortar el procesado de la petición, recargándose de nuevo lapágina en el cliente.

Cada vez que se detecta un error de validación, el entorno JSF genera un mensaje deerror que puede ser mostrado en el momento que vuelva a recargarse la página mediante eltag <h:message>. Este tag incluye un atributo llamado for en el que se debe especificar el iddel control cuyo mensaje de error se quiere mostrar.

Por ejemplo, supongamos que en el formulario utilizado en el ejercicio 1 queremosestablecer la obligatoriedad por parte del usuario de introducir datos en los tres camposutilizados. El código fuente de la página grabadatos.jsp quedaría como se indica en el siguientelistado:

<%@page contentType="text/html"%>

<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>

<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

Page 43: JSF Basico

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;

charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<center><h1>Formulario de datos</h1></center>

<f:view>

<h:form>

<table width="50%" align="center" border="0">

<tr>

<td>Nombre:</td>

<td><h:inputText id="nombre" required="true"

value="#{PersonaBean.nombre}"/></td>

<td><h:message for="nombre"/></td>

</tr>

<tr>

<td>Teléfono:</td>

<td><h:inputText id="tel" required="true"

value="#{PersonaBean.telefono}"/></td>

<td><h:message for="tel"/></td>

</tr>

<tr>

<td>Edad:</td>

<td><h:inputText id="edad" required="true"

value="#{PersonaBean.edad}"/></td>

<td><h:message for="edad"/></td>

</tr>

<tr>

<td colspan="2" align="center">

<h:commandButton value="Guardar"

actionListener="#{PersonaBean.doHabilitar}"

action="#{PersonaBean.doGuardar}" />

</td>

</tr>

<tr>

<td colspan="2" align="center">

Page 44: JSF Basico

<h:commandButton id="vertodos"

rendered="false" value="Ver Todos"

action="ver"/>

</td>

</tr>

</table>

</h:form>

</f:view>

</html>

Podemos ver como además de añadir el atributo required con el valor true a cada unode los campos de texto, hemos incluido una celda al lado de cada campo donde se mostrará elmensaje de error asociado al mismo en caso de no cumplirse el criterio de validación. La figura13 muestra el aspecto de la página en caso de intentar el envío de datos sin haber introducidoningún valor en el campo “nombre”.

Los mensajes de error mostrados están definidos dentro de un archivo de recursosllamado Message.properties que se encuentra en la librería jsf-impl.jar de JSF.

Figura. 13.

Es posible definir nuestros propios mensajes de error personalizados, para ellocrearíamos un archivo .properties con la estructura de Message.properties y lo situaríamos enel directorio WEB-INF\classes de la aplicación Web. El nombre de ese archivo puede sercualquiera, pero para que la aplicación haga uso del mismo en vez de Message.propertiessería necesario añadir la siguiente entrada en faces-config.xml:

<application>

<message-bundle>Nombre_archivo</message-bundle>

</application>

Page 45: JSF Basico

Donde Nombre_archivo será el nombre del archivo de recursos sin la extensión.properties.

La validación automática también se aplica como hemos dicho a los tipos de datos delos campos. Por ejemplo, si en la página anterior se introduce un valor que incluye caracteresno numéricos en el campo edad, se producirá un error de conversión de tipos (recordemos queel campo edad está definido como int en el bean PersonaBean), recargándose de nuevo lapágina con el aspecto indicado en la figura 14.

Figura. 14.

7.1.2. Validadores implícitos JSF

La especificación JSF incluye una serie de validadores que permiten realizarcomprobaciones clásicas en los campos de un formulario.

Estos validadores son clases que implementan la interfazjavax.faces.validator.Validator, en las JSF delega la comprobación de ciertas características delos campos.

Para utilizar uno de estos validadores sobre un determinado campo, tan solotendremos que anidar el tag asociado al validador dentro del campo a validar. El siguienteejemplo utiliza un validador JSF que comprueba que el número de caracteres del campo“codigo” sea como mínimo 4:

Código: <h:inputText id="codigo" value="#{DatosBean.codigo}">

<f:validateLength minimum="4"/>

</h:inputText>

<h:message for="codigo"/>

Al igual que con las validaciones implícitas, utilizamos el tag <h:message> para indicarel lugar donde se debe mostrar el mensaje de error en caso de incumplirse los criterios devalidación.

Tres son los validadores proporcionados por la especificación JSF. Las clases queincluyen la lógica para la realización de las validaciones se encuentran en el paquetejavax.faces.validator, sin embargo, el programador no tendrá que encargarse de instanciar

Page 46: JSF Basico

estas clases e invocar a los métodos de validación, todo ello se hace automáticamente, comohemos visto antes, anidando dentro del campo a validar el tag de validación apropiado. Estostags se incluyen en la librería f de JSF y son:

<f:validateLength>. Comprueba que el número de caracteres introducido en elcampo se encuentra dentro de un determinado rango. Mediante los atributosminimum y maximum se especifica el número mínimo y máximo de caracteres,respectivamente, que debe tener el dato introducido. Ambos atributos sonopcionales, por lo que puede establecerse únicamente un límite inferior osuperior.

<f:validateLongRange>. Comprueba que el valor numérico entero introducido enel campo esté dentro de un determinado rango. Rango que será determinado porlos atributos minimum y maximum de la etiqueta. Como en el tag anterior, ambosvalores son opcionales.

<f:validateDoubleRange>. Comprueba que el valor numérico introducido en elcampo esté dentro de un determinado rango. En este caso, el valor del camposerá interpretado como double. El rango de valores viene determinado, como enlos tags anteriores mediante los atributos minimum y maximum.

En los tres casos, cuando el código de validación determine que el valor introducidono cumple con los criterios definidos se lanzará una excepción ValidationException queprovocará la recarga de la página y la visualización de los mensajes de error en los lugaresdefinidos por <h:message>

7.1.3. Validadores personalizados

Cuando los criterios de validación de los validadores JSF no se ajustan a losrequerimientos de un determinado campo, será necesario definir nuestros propios métodos devalidación personalizados en los que incluiremos el código necesario para realizar lascomprobaciones requeridas.

Estos métodos podrán ser definidos en los beans gestionados utilizados por laaplicación. Podrán ser llamados de cualquier manera, si bien deberán ajustarse al siguienteformato:

public void nombre_metodo(FacesContext context,

UIComponent component,

Object value) throws ValidatorException

Además de no devolver ningún resultado, deberán declarar tres parámetros cuyosignificado será el siguiente:

context. Objeto FacesContext asociado a la aplicación.

component. Componente gráfico a validar.

value. Valor que debe ser validado.

Estos tres parámetros son pasados por el entorno de ejecución de JSF al métododurante la fase de validación de datos (Process Validation).

En el interior de este método se incluirá el código necesario para realizar lascomprobaciones, según los criterios que hayamos establecido. En caso de que dichos criteriosno se cumplan, el método deberá lanzar una excepción de tipojava.faces.validator.ValidatorException.

Page 47: JSF Basico

Por otro lado, para vincular un componente UI con el método de validaciónpersonalizado simplemente debemos indicar la referencia al mismo, utilizando la notación EL,en el atributo validator del tag del elemento.

El siguiente bloque JSP de ejemplo incluye un campo “email” dentro de una página, alque asocia un método de validación definido en el bean “DatosBean”:

Email: <h:inputText id="email" value="#{DatosBean.email}"

validator="#{DatosBean.compruebaemail}"/>

<h:message for="email"/>

El método compruebaemail podría estar definido de la siguiente manera en DatosBean:

public void compruebaemail(FacesContext context,

UIComponent component,

Object value) throws ValidatorException{

String valor=(String)value;

if((valor.indexOf("@")==-1)||(valor.indexOf(".")==-1)){

throw new ValidatorException(

new FacesMessage("Email no valido"));

}

return;

}

Observamos en el código de ejemplo anterior como el constructor de la claseValidatorException requiere como parámetro un objeto javax.faces.application.FacesMessageque representa un mensaje de validación. De los cuatro constructores incluidos en la claseFacesContext, el que se utiliza en este ejemplo recibe como parámetro un Stringcorrespondiente a mensaje resumido de error, mensaje que será mostrado por el tag<h:message>.

7.2. CONVERSORES

La misión de los conversores es doble, por un lado se encargan de realizar unaconversión de los datos suministrados por el usuario a través de los campos, a fin deadaptarlos a las características requeridas por la aplicación.

Por otro lado, los conversores permiten realizar una conversión en sentido contrario,formateando los datos utilizados por la aplicación para que puedan ser adecuadamentepresentados en la página. Por ello, a diferencia de los validadores que, únicamente pueden serutilizados con componentes de entrada de datos, los conversores pueden ser empleadostanto con componentes de entrada como de salida, es decir, con cualquier componenteUIOutput.

Además de las conversiones implícitas realizadas por JSF para adaptar los contenidosde los campos a los tipos definidos por las propiedades del bean asociado, la especificaciónJSF incluye una serie de conversores que podemos utilizar en cualquier aplicación.

Page 48: JSF Basico

7.2.1. Conversores implícitos JSF

Se trata de un conjunto de clases incluidas en el paquete javax.faces.convert quepermiten realizar conversiones en forma bidireccional de los datos. Como sucede con losvalidadores, JSF incluye una serie de tags en la librería “f” que, anidados dentro del campocorrespondiente, permiten hacer uso de las clases conversoras durante la fase de diseño.

El siguiente ejemplo formatea el contenido del campo “salario” como tipo moneda. Deesta manera será en este formato como se presentará en el campo de texto el contenido de lapropiedad “salario” del bean y, por otro lado, cualquier valor introducido en dicho campo seráconvertido a formato moneda al realizar el envío de la página, antes de ser asignado a lapropiedad:

Salario: <h:inputText id="salario"

value="#{EmpleadoBean.salario}">

<f:convertNumber type="currency"/>

</h:inputText>

Los dos tags proporcionados por JSF para la conversión y formato de datos son:

<f:convertNumber>. Es el que hemos utilizado en el ejemplo anterior; se utilizapara realizar operaciones de formato de valores numéricos. Entre los atributosmás importantes de este tag destacamos:

- type. Especifica el tipo de formato del número. Sus posibles valoresson “currency”, “percentage” y “number”, siendo este último el valorpredeterminado.

- integerOnly. Si está establecido a true, únicamente se almacenará enla propiedad la parte entera del valor introducido en el campo. Asímismo, este sólamente mostrará la parte entera de la propiedad.

- minFractionDigits. Indica el número mínimo de decimales con el queserá formateado el número.

- maxFractionDigits. Indica el número máximo de decimales con el queserá formateado el número. Por ejemplo, si este atributo estáestablecido al valor 2 y en el campo se introduce 234,3457, el valorasignado a la propiedad (suponiendo que sea de tipo decimal) será234,34.

- minIntegerDigits. Mínimo número de dígitos con el que seráformateada la parte entera.

- manFractionDigits. Máximo número de dígitos con el que seráformateada la parte entera. Por ejemplo, si el atributo está establecidoal valor 2 y en el campo se introduce el número 123,45, el primer dígitoentero será desechado, almacenándose el valor 23,45 en la propiedad.

- currencySymbol. Símbolo utilizado para formatear el dato cuando seutiliza el tipo “currency”.

- pattern. Cadena de caracteres que define un patrón de formatopersonalizado. Si este atributo se encuentra establecido, se ignoraráel contenido del atributo type. Podemos encontrar información sobrelos caracteres de formato en la ayuda sobre la clasejava.text.NumberFormat. Por ejemplo, en el siguiente ejemplo se

Page 49: JSF Basico

formatearía el campo “salario” como un número con una única cifradecimal:

salario: <h:inputText id="salario"

value="#{DatosBean.salario}">

<f:convertNumber pattern="##.#"/>

</h:inputText>

Si se introduce el valor 234,7967, será formateado como 234,8.

<f:convertDateTime>. Se emplea para realizar operaciones de formato defechas y horas. Sus principales atributos son:

- type. Especifica el tipo de formato a aplicar. Sus posibles valores son“date”, “time” o “both”.

- dateStyle. Especifica el estilo del formato para fechas. Sus posiblesvalores son “default”, “short”, “medium” o “long”. El siguiente ejemplose establece un formato de fecha corta para el campo “fechanacimiento”:

fecha nacimiento <h:inputText id="fecha"

value="#{DatosBean.fecha}">

<f:convertDateTime type="date" dateStyle="short"/>

</h:inputText>

- timeStyle. Especifica el estilo del formato para la hora. Sus posiblesvalores son “default”, “short”, “medium” o “long”.

- pattern. Especifica un patrón de formato personalizado para lafecha/hora. En la clase java.text.DateFormat podemos encontrarinformación sobre los posibles caracteres de formato a utilizar. Si esteatributo se encuentra especificado, se ignorará el contenido de losatributos dateStyle, timeStyle y type.

- timeZone. Cadena de caracteres que representa la zona horaria con laque será formateada la fecha/hora. Por ejemplo, si la propiedad “fecha”del bean DatosBean contiene la fecha/hora actuales, el siguiente tagmostrará en la página la fecha actual en la zona de Los Ángelesformateada con formato corto:

Hora en Los Angeles: <h:outputText id="fecha"

value="#{DatosBean.fecha}">

<f:convertDateTime timeZone="America/Los_Angeles"

type="time" timeStyle="short"/>

</h:outputText>

Page 50: JSF Basico

AUTOEVALUACIÓN

1. Un objeto FacesServlet pertenece a la capa:

A. Controlador

B. Vista

C. Modelo

D. Es un elemento de apoyo a las tres capas anteriores

2. Indica cual de las siguientes características no esaplicable al framework JSF:

A. Las aplicaciones son conducidas por eventos

B. Permite crear aplicaciones bajo arquitectura MVC

C. Los componentes gráficos JSF únicamente pueden serutilizados en páginas JSP

D. La navegación entre páginas se define en el archivode configuración faces-config.xml

3. La ejecución de los métodos de respuesta a los eventosActionEvent de una interfaz JSF se produce en la fase:

A. Restore View

B. Apply Request Values

C. Invoke Application

D. Depende del atributo inmediate del componente

4. El acceso a los atributos de sesión desde un métodocontrolador de acción se realiza:

A. A través del objeto ActionEvent recibido comoparámetro

B. A través de la clase FacesContext

C. A través de la clase FacesServlet

D. Utilizando las propiedades de los beans gestionados

Page 51: JSF Basico

5. Tenemos un bean gestionado de identificador ComprasBeanque incluye un método llamado listado() que recupera unconjunto de filas de una base de datos y las almacenaen un atributo de petición, devolviendo como resultadouna cadena de texto que servirá para determinar lapróxima vista a enviar al usuario. Si queremos que esemétodo sea ejecutado al pulsar un botón de comandolinkCommand, ¿cual de las siguientes accionesdeberíamos incluir en una página JSP para realizar esaoperación?:

A. <h:linkButton value="Aceptar"

actionListener="#{ComprasBean.listado}"/>

B. <h:linkButton value="Aceptar"

actionListener="#{ComprasBean.listado}"

inmediate="true"/>

C. <h:linkButton value="Aceptar"

action="#{ComprasBean.listado}"/>

D. <h:linkButton label="Aceptar"

value="#{ComprasBean.listado}"/>

6. Indica cual de las siguientes acciones JSP serviríapara generar una lista de selección múltiple:

A. <h:selectOneMenu><f:selectItems value="#{LibrosBean.libros}"/>

</h:selectOneMenu>

B. <h:selectManyMenu><f:selectItems value="#{LibrosBean.libros}"/>

</h:selectManyMenu>

C. <h:selectOneListbox multiple="true"><f:selectItems value="#{LibrosBean.libros}"/>

</h:selectOneListbox>

D. <h:selectManyListbox><f:selectItems value="#{LibrosBean.libros}"/>

</h:selectManyListbox>

Page 52: JSF Basico

7. ¿Cual de los siguientes controles no es de tipoUIInput?

A. Lista de botones de radio

B. Botón de pulsación

C. Caja de texto simple

D. Caja de texto multilínea

8. Para forzar a que el dato introducido por el usuariotenga un número de caracteres contenido en undeterminado rango debemos utilizar:

A. El validador <f:validateLength>

B. El validador <f:validateLongRange>

C. El validador <f:textRange>

D. Un validador personalizado

Page 53: JSF Basico

Ejercicios Propuestos

1. Crear una nueva versión del ejercicio 2 resuelto en el tema de servlets,consistente en generar dinámicamente una página formateada según las opcionesindicadas en una página HTML:

Figura. 15.

Al pulsar el botón generar los datos serán enviados a una página JSP que será laencargada de generar dinámicamente la nueva página según las opcioneselegidas. En este caso, emplearemos controles JSF para diseñar la interfaz yrealizaremos la gestión de eventos que consideremos adecuada.

2. Incluir los validadores necesarios en la página de registro del ejercicio 2, de formaque se deban cumplir los siguientes criterios:

i. Todos los campos serán de obligada cumplimentación.

ii. El nº de caracteres del campo password será como mínimo de 4 ycomo máximo de 8.

iii. El campo email debe ser válido (incluirá un punto y la @)

iv. El campo teléfono debe incluir solo caracteres numéricos.

Se deberán mostrar los mensajes de error en cada campo que incumpla las reglasde validación.

3. Crear una nueva versión de la aplicación para la realización de votaciones através de Internet realizada en temas anteriores, basada en este caso en lautilización del framework JSF.

Page 54: JSF Basico

4. Realizar una aplicación de librería, donde un usuario pueda ser validado a travésde una página de login que además contará con un enlace a una página deregistro para que se puedan registrar en caso de no estarlo.

Una vez validado, se mostrará una página con una lista desplegable para laselección del tema, de modo que al seleccionar uno de ellos se visualicen, en lamisma u otra página, todos los libros de ese tema.

La aplicación se desarrollará siguiendo el patrón MVC y con framework JSF. Ydeberá incluir gestión de eventos y validación de datos.

Utilizar como tablas de datos las empleadas en otros ejercicios realizados duranteel curso.