> Manuales > Ayudas técnicas

Ya tenemos instalada una implementación de JSF. Ahora vamos a hacer una pequeña aplicación de ejemplo, para demostrar como funcionan las principales características de JSF (el movimiento se demuestra andando).



Primero vamos a describir nuestra aplicación de ejemplo (este ejemplo está basado en los ejemplos del tutorial Core-Servlets JSF Tutorial by Marty Hall –http://www.coreservlets.com/JSF-Tutorial), presentando cada uno de los ficheros que forman parte de ella, junto con una captura de las ventana correspondiente (si tiene representación visual), y junto a su código fuente.

Después, en cada capítulo, explicaremos concretamente cada uno de los puntos de la aplicación. Al final del tutorial habremos visto:


customize.jsp

Dentro de la carpeta WebContent.

Esta será la ventana inicial de la aplicación. Es un simple formulario de entrada donde podemos personalizar los colores de nuestro CV (“Resume” en ingles), introducir nuestro nombre, la edad, y nuestra profesión.

En las siguientes imágenes se puede apreciar la aplicación en distintos lenguajes, y como se muestran los errores de validación.

En el código podemos ver como se utilizan librerías de etiquetas para “pintar” los distintos componentes. En este sentido JSF es muy similar a Struts, ya que el interfaz de usuario se implementa con JSPs, la ventaja de JSF frente a Struts es que JSF desde un principio está pensado para que las herramientas de desarrollo faciliten la elaboración del interfaz de forma visual. Dentro de las este tipo de herramientas (también permiten modificar los ficheros de configuración de JSF de forma visual) podemos encontrar, entre otras muchas:


<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://myfaces.apache.org/extensions" prefix="x"%>

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

<html>
<f:view>
<f:loadBundle basename="MessageResources" var="msg"/>
<head>
   <title>${msg.customize_title}</title>
</head>

<body>
<center>
<table BORDER=5>
   <tr><th>${msg.customize_title}</th></tr>
</table>
<p/>
<h:form>
   <h:outputLabel for="changeColorMode" value="#{msg.changeColorMode}" />
   <h:selectBooleanCheckbox id="changeColorMode"
      valueChangeListener="#{resumeBean.changeColorMode}"
      immediate="true"
      onchange="submit()" />
   <br/>
   <h:panelGrid columns="2">
      <h:outputLabel for="fgColor" value="#{msg.fgColor}" />
      <h:selectOneMenu id="fgColor"
         value="#{resumeBean.fgColor}"
         disabled="#{!resumeBean.colorSupported}">
      <f:selectItems value="#{resumeBean.availableColors}" />
   </h:selectOneMenu>

    <h:outputLabel for="bgColor" value="#{msg.bgColor}" />
   <h:selectOneMenu id="bgColor"
      value="#{resumeBean.bgColor}"
      disabled="#{!resumeBean.colorSupported}">
   <f:selectItems value="#{resumeBean.availableColors}" />
   </h:selectOneMenu>
    </h:panelGrid>
   <h:commandButton value="#{resumeBean.colorSupportLabel}"
      actionListener="#{resumeBean.toggleColorSupport}"
       immediate="true" />
   <br/>
   <br/>
   <br/>
   <hr width="25%"/>
   <h:panelGrid id="i5" columns="2">
       <h:outputLabel for="name" value="#{msg.name}" />
      <h:inputText id="name" value="#{resumeBean.name}" required="true" />

      <h:outputLabel for="age" value="#{msg.age}" />
      <h:inputText id="age" value="#{resumeBean.age}" required="true">
         <f:validateLongRange minimum="16" maximum="64"/>
      </h:inputText>

      <h:outputLabel for="jobTitle" value="#{msg.jobTitle}" />
      <h:inputText id="jobTitle" value="#{resumeBean.jobTitle}" required="true" />
    </h:panelGrid>
    <x:messages showSummary="false" showDetail="true" style="color: red" />
   <br/>
   <h:commandButton value="#{msg.showPreview}" action="#{resumeBean.showPreview}" />
</h:form>

</center>
</f:view>
</body>
</html>

same-color.jsp

Dentro de la carpeta WebContent.

Esta pantalla muestra un mensaje de error cuando se selecciona el mismo color para el fondo y para las letras.


<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://myfaces.apache.org/extensions" prefix="x"%>

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

<html>
<f:view>
<f:loadBundle basename="MessageResources" var="msg"/>
<head>
   <title>${msg.sameColor_title}</title>
</head>

<body>
<center>

<table border=5>
   <tr><th>${msg.sameColor_title}</th></tr>
</table>
<p/>
<h:outputFormat value="#{msg.sameColor_message}" escape="false">
    <f:param value="#{resumeBean.fgColor}"/>
</h:outputFormat>

</center>
</f:view>
</body>
</html>

show-preview.jsp

Dentro de la carpeta WebContent.

Muestra un borrador del CV según lo que hemos puesto en el formulario de la ventana inicial.


<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://myfaces.apache.org/extensions" prefix="x"%>

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

<html>
<f:view>
<f:loadBundle basename="MessageResources" var="msg"/>
<head>
   <title>
      <h:outputFormat value="#{msg.preview_title}">
          <f:param value="#{resumeBean.name}"/>
       </h:outputFormat>
   </title>
</head>

<body text="<h:outputText value="#{resumeBean.fgColor}" />"
    bgcolor="<h:outputText value="#{resumeBean.bgColor}" />">
<h1 align="CENTER">
    <h:outputText value="#{resumeBean.name}"/><BR>
    <small><h:outputText value="#{resumeBean.jobTitle}"/></small>
</h1>
<h:outputFormat value="#{msg.summary}">
    <f:param value="#{resumeBean.age}"/>
   <f:param value="#{resumeBean.jobTitle}"/>
</h:outputFormat>
<h2>${msg.employmentHistory}</h2>
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
<h2>${msg.education}</h2>
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
<h2>${msg.publications}</h2>
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
Blah, blah, blah, blah. Yadda, yadda, yadda, yadda.
</f:view>
</body>
</html>

Ficheros de recursos

Dentro de la carpeta JavaSource.

Estos ficheros son los que contienen la traducción de los textos dependiendo del lenguaje.
MessageResources_es.properties

customize_title=Previsualizar Currículum Vítae
changeColorMode=Usar RGB en vez nombres de color
fgColor=Color de letra
bgColor=Color de fondo
name=Nombre
age=Edad
jobTitle=Titulación
colorSupportEnable=Activar configuración de color
colorSupportDisable=Desactivar configuración de color
showPreview=Previsualizar

sameColor_title=Error en el Color
sameColor_message=Has elegido "{0}" tanto para el color de letra
como para el color de fondo.<p/>No te mereces encontrar un trabajo,
pero supongo que te dejaremos <a href="customize.jsf">probar de nuevo</a>.

preview_title=Currículum Vítae de {0}
summary=Experimentado {1} con {0} años de edad, busca una posición de
desafío haciendo algo.
employmentHistory=Historia Laboral
education=Educación
publications=Publicaciones y Reconocimientos

MessageResources_en.properties

customize_title=Preview Resume
changeColorMode=Use RGB instead of color names
fgColor=Foreground color
bgColor=Background color
name=Name
age=Age
jobTitle=Job Title
colorSupportEnable=Enable Colors Customization
colorSupportDisable=Disable Color Customization
showPreview=Show Preview

sameColor_title=Color Error
sameColor_message=You chose "{0}" as both the foreground and background
color.<p/>You don't deserve to get a job, but I suppose we will let you
<a href="customize.jsf">try again</a>.

preview_title=Resume for {0}
summary={0} years old experienced {1}, seeks challenging position doing
something.
employmentHistory=Employment History
education=Education
publications=Publications and Awards

ResumeBean.java

Dentro de la carpeta JavaSource/com/autentia/jsfexample.

Este bean es el que guardará toda la información recogida en el formulario. El equivalente en Struts sería una mezcla entre la clase de formulario (ActionForm) y la clase acción (Action). Esto lo podríamos ver como una ventaja ya que simplifica el código, aunque si nos gusta más la aproximación de Struts también es posible hacer dos clases distintas en JSF (ejemplo de la mayor flexibilidad de JSF frente a Struts).

También podemos observar que la clase no define ninguna relación de herencia (en Struts extendemos de Action o ActionForm). Esto es una ventaja ya que hay menos acoplamiento entre nuestro modelo y JSF.

package com.autentia.jsfexample;

import java.util.Locale;
import java.util.ResourceBundle;

import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

public class ResumeBean {
   private String name = "";
   private int age = 0;
    private String jobTitle = "";
    private String fgColor = "BLACK";
    private String bgColor = "WHITE";
   private SelectItem[] availableColorNames = {
      new SelectItem("BLACK"), new SelectItem("WHITE"),
       new SelectItem("SILVER"), new SelectItem("RED"),
      new SelectItem("GREEN"), new SelectItem("BLUE") };

   private SelectItem[] availableColorValues = {
       new SelectItem("#000000"), new SelectItem("#FFFFFF"),
       new SelectItem("#C0C0C0"), new SelectItem("#FF0000"),
       new SelectItem("#00FF00"), new SelectItem("#0000FF") };

    private boolean isColorSupported = true;

   private boolean isUsingColorNames = true;

    public String getName() {
       return name;
   }
   public void setName(String name) {
       this.name = name;
    }

    public String getJobTitle() {
       return jobTitle;
    }

    public void setJobTitle(String jobTitle) {
       this.jobTitle = jobTitle;
    }
   public String getFgColor() {
      return fgColor;
   }
    public void setFgColor(String fgColor) {
       this.fgColor = fgColor;
    }
    public String getBgColor() {
       return bgColor;
    }
    public void setBgColor(String bgColor) {
       this.bgColor = bgColor;
   }

    public SelectItem[] getAvailableColors() {
       if (isUsingColorNames) {
          return (availableColorNames);
       } else {
          return (availableColorValues);
       }
   }

    public boolean isColorSupported() {
      return isColorSupported;
   }

   public void toggleColorSupport(ActionEvent event) {
      isColorSupported = !isColorSupported;
    }

    public String getColorSupportLabel() {
       FacesContext context = FacesContext.getCurrentInstance();
       Locale locale = context.getViewRoot().getLocale();
       ResourceBundle bundle = ResourceBundle.getBundle("MessageResources", locale);
       String msg = null;
       if (isColorSupported) {
          msg = bundle.getString("colorSupportDisable");
       } else {
          msg = bundle.getString("colorSupportEnable");
      }
      return msg;
   }

    public boolean isUsingColorNames() {
       return isUsingColorNames;
   }

    public void setUsingColorNames(boolean isUsingColorNames) {
      this.isUsingColorNames = isUsingColorNames;
   }

    public void changeColorMode(ValueChangeEvent event) {
       boolean flag = ((Boolean)event.getNewValue()).booleanValue();
       setUsingColorNames(!flag);
   }

   public String showPreview() {
      if (isColorSupported && fgColor.equals(bgColor)) {
          return "same-color";
      } else {
          return "success";
       }
   }

   public int getAge() {
       return age;
   }

    public void setAge(int age) {
       this.age = age;
   }
}


faces-config.xml

Dentro de la carpeta WebContent/WEB-INF.

Este fichero es donde configuramos JSF. Es como el “pegamento” que une modelo, vista y controlador. El equivalente en Struts sería el fichero struts-config.xml.

En este fichero por un lado declaramos los beans que vamos a utilizar para recoger la información de los formulario (en el struts-config.xml teníamos una sección similar), y por otro lado las reglas de navegación (en el struts-config-xml se podría comparar con la definición de forwards de las acciones).

<?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>
   <application>
      <locale-config>
         <default-locale>es</default-locale>
          <supported-locale>en</supported-locale>
       </locale-config>
   </application>

   <!--
       - managed beans
       -->
   <managed-bean>
       <managed-bean-name>resumeBean</managed-bean-name>
       <managed-bean-class>com.autentia.jsfexample.ResumeBean</managed-bean-class>
       <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>

   <!--
       - navigation rules
       -->
    <navigation-rule>
       <from-view-id>/customize.jsp</from-view-id>
       <navigation-case>
          <from-outcome>same-color</from-outcome>
          <to-view-id>/same-color.jsp</to-view-id>
       </navigation-case>
       <navigation-case>
          <from-outcome>success</from-outcome>
          <to-view-id>/show-preview.jsp</to-view-id>
      </navigation-case>
   </navigation-rule>
</faces-config>

Alejandro Pérez García

Dir. Implantación y Rendimiento.

Manual