Introducción a JSF

Ramiro Lago (Mayo 2007)

Aspectos preliminares

JSF es un framework para construir interfaces de usuario en aplicaciones web. Sabemos que la construcción de los interfaces de usuario suelen ser la parte más costosa del esfuerzo de desarrollo, sobre todo por la dificultad de mantenimiento. En especial cuando se mezcla en un mismo archivo JSP el interfaz de usuario, las reglas de validación y el acceso a la base de datos. JSF nos ofrece un marco de trabajo que facilita el desarrollo de aplicaciones, separando las diferentes capas de una arquitectura: presentación, reglas y entidades de negocio. En este sentido toma una orientación semejante a Struts.

JSF fue creado dentro del Java Community Process de SUN, en el que han participado líderes de la industria como Oracle, BEA, IBM, etc. Es el framework oficial de SUN para el desarrollo de aplicaciones. Uno de los lideres, Craig McClanahan, es el creador del popular framework Struts. Además, como un desarrolllo adicional al JCP, encontramos dentro del proyecto Yakarta el framework MyFaces. Para más información puede ver el tutorial de SUN.

Lo que nos ofrece JSF es:

Organización de una aplicación que usa JSF

Seguimos la versión 1.1 de JSF, que podemos bajar  del sitio de SUN. Lo primero que se necesita es incorporar las librerías:

A continuación tenemos que tener los archivos web.xml y faces-config.xml en WEB-INF. Lo más importante que haremos en el primero es especificar el servlet que controla el uso de JSF. En el segundo se especifican los eventos, acciones, beans de respaldo (backend bean), etc. Más adelante explicaremos el contenido de estos archivos.

Puede ser conveniente cargar los tlds (definiciones de etiquetas JSF): html_basic.tld y jsf_core.tld, aunque sólo sea para curiosear y consultar detalles de implementación. El dtd que usa faces-config.xml tampoco es necesario que se lo descargue, ya que desde el archivo xml se hace referencia a la versión que está en SUN, su nombre es web-facesconfig_1_1.dtd.

Una visión panorámica de la arquitectura del proyecto, que es una adaptación del ejemplo que se puede descargar con JSF 1.1:



Los archivos jsp se han colocado en el directorio raíz (lo cual no es evidentemente obligatorio). El código fuente de las clases java se sitúan en src y, lo que si resulta imprescindible,  ponemos en el directorio classes los archivos .class. Los archivos que empiezan por un punto son recursos de configuración propios de Eclipse.


Introducción al árbol de componentes

Veamos un sencillo ejemplo en el que se pide la introducción de un número:

El código fuente (greeting.jsp) puede verse a continuación:


<HTML>
    <HEAD> <title>Hello</title> </HEAD>
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
    <body bgcolor="white">
    <f:view>
    <h:form id="helloForm" >
      <h2>Hi. My name is Duke.  I'm thinking of a number from
      <h:outputText value="#{UserNumberBean.minimum}"/> to
      <h:outputText value="#{UserNumberBean.maximum}"/>.  Can you guess
      it?</h2>

        <h:graphicImage id="waveImg" url="/wave.med.gif" />
  	<h:inputText id="userNo" value="#{UserNumberBean.userNumber}"
                      validator="#{UserNumberBean.validate}"/>          
	 <h:commandButton id="submit" action="success" value="Submit" />
         <p>
	 <h:message style="color: red; font-family: 'New Century Schoolbook', serif; font-style: oblique; text-decoration: overline" id="errors1" for="userNo"/>

    </h:form>
    </f:view>
    </body>
</HTML>  
	

Con las declaraciones "taglib uri" hacemos referencia a las librerías de etiquetas. La primera contiene la definición de componentes y la segunda la definición de validaciones y eventos. A continuación puede ver que hay un árbol de componentes que se cargarán en el servidor. La etiqueta raíz es f:view. La etiqueta h:form señala el inicio del formulario. Dentro de ésta tendremos las etiquetas correspondientes a los h:outputText (texto se salida), h:inputText (campo de texto), h:graphicImage (imagen) y h:commandButton (botón).


Asociando componentes de UI con beans

Un aspecto interesante es que JSF permite sincronizar los valores de los componentes con los atributos de un bean de respaldo. Por ejemplo, h:outputText value="#{UserNumberBean.minimum}" inserta el valor del atributo en el "value" de la etiqueta. Además podemos validar el contenido de un campo por medio de su bean de respaldo: el componente h:inputText id="userNo" llamará al método UserNumberBean.validate() cuando se pulse el botón. Un ejemplo parcial del bean:


public class UserNumberBean {

    private int maximum = 0;
    private int minimum = 0;


    public int getMaximum() { return (this.maximum); }
    public int getMinimum() { return (this.minimum); }

    public void setMaximum(int maximum) {
        this.maximum = maximum;
        ....
    }
    public void setMinimum(int minimum) {
        this.minimum = minimum;
        ....
    }
    ....
	

Los bean en JSF se construyen con la misma lógica que los JavaBeans de JSP: todo atributo tiene sus métodos set/get; pueden existir otros métodos adicionales, pero dejando claro que los atributos que asociamos a los componentes necesitan sus correspondientes métodos set/get.

Además de asociar los componentes con los bean podemos asociar los componentes con acciones, por ejemplo el botón tiene action="success". En faces-config se define la página destino (response.jsp) a la que se dirige JSF cuando el resultado (la acción) de la pagina origen (greeting.jsp ) es "success". Por ejemplo:


  <navigation-rule>
    <from-view-id>/greeting.jsp</from-view-id>
    <navigation-case>
        <description>
            Indicates to the NavigationHandler that the response.jsp
            view must be displayed if the Action referenced by a 
            UICommand component on the greeting.jsp view returns 
            the outcome "success".
        </description>
      <from-outcome>success</from-outcome>
      <to-view-id>/response.jsp</to-view-id>
    </navigation-case>
  </navigation-rule>
	

En este ejemplo se establece una regla de navegación que se podría enunciar así: "Si estamos en greeting.jsp y su acción/resultado (from-outcome) es 'success', entonces invoca response.jsp".


Volver al índice