You are on page 1of 19

3

Primeros pasos
En este capítulo, empezaremos a entender cómo escribir una aplicación rica utilizando
RichFaces.

Con el fin de hacer esto, hemos decidido empezar con un ejemplo sencillo que implementa una
lista de contactos al estilo Ajax. El usuario será capaz de listar, agregar y eliminar contactos, sin
necesidad de recargar la página del navegador.

Vamos a ver cómo algunos componentes importantes de Ajax trabajan y cómo ajaxizaremos
una aplicación JSF utilizando los conceptos del marco de trabajo RichFaces.

Las características desarrolladas en este ejemplo se verán en profundidad en los próximos


capítulos.

Un administrador de contactos
La aplicación de ejemplo es un simple administrador de contactos, tiene una lista de contactos
y un formulario para añadir nuevos contactos. También, puede eliminar un contacto específico
de la lista.

El ejemplo muestra cómo funciona el marco de Ajax y cómo se puede utilizar los componentes
Ajax RichFaces. También utiliza algunos componentes gráficos RichFaces como:
rich:panel, rich:spacer, y rich:separator. Se utiliza el componente
rich:calendar para la entrada de la fecha, y la versión RichFaces de dataTable
(rich:dataTable y rich:column) con capacidad de filtrado automático y de ordenación.

También usamos el componente de validación de Ajax (rich:beanValidator) para ajaxizar


y mejorar la validación de JSF estándar.

El tema (skin) que hemos elegido puede cambiar editando el nombre del tema en el archivo
web.xml (veremos cómo hacer ésto en los capítulos siguientes).
Creación del nuevo proyecto
Como hemos visto en el capítulo 2, preparándose, a fin de utilizar la seam-gen, abra una
ventana de terminal y vaya al directorio de JBoss Seam. Desde aquí, podrá ejecutar comandos
seam-gen. Antes de ejecutar el comando seam-gen que crea un proyecto nuevo, debemos
configurarlo con los siguientes comandos.

Si está utilizando Microsoft Windows, utilice el siguiente comando:

seam setup

Si usted está usando un sistema operativo tipo Unix como GNU/Linux o Mac OS X, use el
siguiente comando:

./seam setup

Después del texto de bienvenida, seam-gen nos hará algunas preguntas acerca de la
configuración del proyecto, nos gustaría tener, para cada pregunta hay una respuesta por
defecto (encerrada entre corchetes) que puede elegir pulsando la tecla Intro.

Las preguntas no son difíciles de entender, vamos a ir a través de ellos y crear nuestro
proyecto para el ejemplo:

Pregunta Descripción Respuesta


Introduzca el lugar de Este es el directorio en el que queremos (La nueva ruta de
trabajo para sus proyectos salvar nuestro nuevo proyecto (que depende directorio del proyecto)
de Java (el directorio que de nuestro entorno y preferencias)
contiene sus proyectos de
Seam)
Ingrese el directorio Es el directorio donde está instalado el (El directorio de JBoss)
predeterminado de JBoss AS servidor de aplicaciones JBoss
Introduzca el nombre del El nombre de la aplicación SimpleContactManager
proyecto
¿Quieres usar ICEfaces en seam-gen también es compatible con No
lugar de RichFaces [n]? ICEfaces (otro marco de componentes), pero
queremos utilizar RichFaces, así que pulse
Enter
Seleccione un tema para Tenemos la opción de seleccionar cualquiera Solo presione Intro
RichFaces [classic] de los temas mostrados para nuestro
(blueSky, [classic], proyecto, tambien podemos cambiarlo más
deepMarine, DEFAULT, tarde, por ahora, el tema classic esta bien
emeraldTown, japanCherry,
ruby, wine)
Este proyecto es Podemos generar un paquete WAR o un Solo presione Intro
empaquetado como un EAR paquete EAR para nuestra aplicación. Nos
(con componentes EJB) o un gustaría una aplicación completa EAR con
WAR (sin soporte EJB) [ear] soporte EJB
Introduzca el nombre del El nombre del paquete que contiene los book.richfaces.scm
paquete Java para el beans beans de sesión (generado por seam-gen)
de sesión
Introduzca el nombre del El nombre del paquete que contiene los book.richfaces.scm
paquete de Java para su beans de entidad (generado por seam-gen)
beans de entidad
Introduzca el nombre del El nombre del paquete que contiene los book.richfaces.scm.test
paquete Java para los casos beans para nuestros casos de prueba
de prueba
¿Qué tipo de base de datos Por este simple ejemplo, no usamos ninguna Solo presione Intro por
se utiliza? base de datos defecto (hsql)
Introduzca el dialecto de No se utiliza en nuestro proyecto Solo presione Intro
Hibernate para la base de
datos
Escriba la ruta del sistema No se utiliza en nuestro proyecto Solo presione Intro
para los controladores jar
de JDBC
Introduzca la clase para el No se utiliza en nuestro proyecto Solo presione Intro
controlador JDBC de la base
de datos
Introduzca la dirección URL No se utiliza en nuestro proyecto Solo presione Intro
de conexión JDBC de la base
de datos
Introduzca el nombre de la No se utiliza en nuestro proyecto Solo presione Intro
base de datos
Introduzca la contraseña de No se utiliza en nuestro proyecto Solo presione Intro
la base de datos
Introduzca el nombre del No se utiliza en nuestro proyecto Solo presione Intro
esquema de base de datos (
está bien dejar este
espacio en blanco)
Introduzca el nombre de No se utiliza en nuestro proyecto Solo presione Intro
catálogo de base de datos
(que está bien dejar este
espacio en blanco)
¿Trabajar con las tablas No se utiliza en nuestro proyecto Solo presione Intro
que ya existen en la base
de datos?
¿Quieres borrar y volver a No se utiliza en nuestro proyecto Solo presione Intro
crear las tablas de base de
datos y los datos en
Import.sql cada vez que se
implante ?

Bien, hemos completado la configuración del proyecto. Vamos a ver cómo configurar un
proyecto para la conexión a un DBMS MySQL en el capítulo 4, la Aplicación (cuando
empezemos a hacer la aplicación real), por ahora está bien utilizar la opción predeterminada
respuestas.

Estamos listos para crear el proyecto utilizando los siguientes comandos. Si está utilizando
Microsoft Windows, utilice el siguiente comando:

seam create-project

Si usted está usando un sistema operativo tipo Unix como GNU/Linux o Mac OS X, utilizar el
siguiente comando:

./seam create-project

Si está utilizando el IDE de Eclipse, tiene que importar el proyecto en el área de trabajo (se
describe cómo hacer esto en el capítulo 2). Con otros IDE (como IntelliJ IDEA o NetBeans),
puede abrir el proyecto en la ubicación especificada durante la ejecución de seam-gen.

Plantillas y Facelets
Nuestro nuevo proyecto no sólo tiene el soporte de Facelets incluido, sino también un archivo
de plantilla, en el que se puede editar para agregar nuestras características. Usted lo puede
encontrar en la ruta /view/layout/template.xhtml.

Esta es la estructura que usamos en otras páginas para evitar volver a escribir en varias
ocasiones los mismos componentes en las demás páginas.

Así es como se ve:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view contentType="text/html"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a="http://richfaces.org/a4j"
xmlns:s="http://jboss.com/products/seam/taglib">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html;charset=UTF-8"/>
<title>AdvContactManager</title>
<link rel="shortcut icon"
href="#{request.contextPath}/favicon.ico"/>
<a:loadStyle src="resource:///stylesheet/theme.xcss"/>
<a:loadStyle src="/stylesheet/theme.css"/>
<ui:insert name="head"/>
</head>
<body>
<ui:include src="menu.xhtml">
<ui:param name="projectName" value="AdvContactManager"/>
</ui:include>
<div class="body">
<h:messages id="messages"
globalOnly="true"
styleClass="message"
errorClass="errormsg"
infoClass="infomsg"
warnClass="warnmsg"
rendered="#{showGlobalMessages != 'false'}"/>
<ui:insert name="body"/>
</div>
<div class="footer">
Powered by <a href="http://jboss.com/products/seam">Seam</a>.
Generated by seam-gen.
</div>
</body>
</html>
</f:view>

Discutamos la página.

Podemos ver la declaración DOCTYPE, que nos dice el tipo de documento que es, y después la
etiqueta <f:view> con las declaraciones de espacio de nombres XML Facelets de las
bibliotecas de componentes que vamos a utilizar. Tenga en cuenta que en esta página, no
usamos los componentes RichFaces (todavía), únicamente está escrito el espacio de nombres
para los componentes de Ajax4JSF (xmlns:a="http://richfaces.org/a4j". Esto es
porque se utiliza la etiqueta <a:loadStyle>. Si desea utilizar los componentes RichFaces,
tiene que incluir el correspondiente xmlns (el espacio de nombres necesario para poder utilizar
todos los componentes RichFaces con el prefijo rich) como sigue:

xmlns:rich=http://richfaces.org/Rich

Vamos a insertarlo como queremos para utilizar los componentes RichFaces en la página
template.xhtml.
Vamos a seguir analizando la página. Nuestro empieza documento (podemos ver las etiquetas
<html>, <head>, <meta>, <title>, y <link>) después de la etiqueta <f:view>.

Después de las etiquetas estándar, podemos ver <a:loadStyle>, que es un componente


Ajax4jsf muy útil para hacer enlaces a la sección head de la página.

Hay un componente llamado Facelets <ui:insert>. No vamos a explicar el marco Facelets


en detalle, todo lo que tiene que saber es que el componente hace que los puntos de inserción
con el fin de agregar el código de otras páginas, que utilizan esta plantilla. Por lo tanto, es muy
útil para colocar el código en la sección head de otras páginas.

Encontramos la etiqueta Facelets <ui:include> usada para incluir a otra página llamada
menu.xhtml en la sección body. En el menú superior que puede ser utilizada para toda la
aplicación. También pasamos dentro de la etiqueta ui:param, que incluye la página que
puede que se puede usar (el parámetro es el nombre del proyecto en este caso).

Ahora nos encontramos con un elemento div que contiene el componente estándar
<h:messages>, el cual vamos a reemplazar con el componente RichFaces correspondiente.

Debajo de la etiqueta h:messages, se encuentra el cuerpo Facelets del punto de inserción


que es utilizada por otras páginas para insertar contenido específico (veremos cómo funciona
esto en los párrafos siguientes).

Al final del código, hay otra sección div, incluyendo algunos de texto con el enlace del sitio
web de JBoss Seam.

Modificar el proyecto creado


Para este ejemplo, sólo se utiliza una página y no aparece ningún menú, así que vamos a
editar la página template.xhtml y eliminar la sección que incluye el menú en cada página:

<ui:include src="menu.xhtml">
<ui:param name="projectName"
value="AdvContactManager"/>
</ui:include>

Si queremos, también podemos personalizar el pie de página al cambiar el texto o borrarlo.

Tenemos que cambiar el título de la página en la plantilla a Simple Contact Manager.

Ahora abra el archivo home.xhtml para la edición, viene con el texto estándar de la
presentación de la seam-gen. Vamos a eliminar la h1 sección y el componente rich:panel
para tener una página en blanco.

Además, podemos añadir el soporte para los componentes de Ajx4JSF mediante la inserción
del espacio de nombres XML en la parte superior de la página. Ahora, la página tiene el
siguiente aspecto:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
xmlns:rich="http://richfaces.org/rich"
template="layout/template.xhtml">
<ui:define name="body">
<!-- my code -->
</ui:define>
</ui:composition>

Tenemos que agregar la estructura para hacer el formulario y la lista de contactos. Vamos a
utilizar una etiqueta estándar h:panelGrid con dos columnas para este fin, así que vamos a
colocar el siguiente código dentro de la sección body ( reemplazando el comentario <!-- my
code -->):

<h3>Simple Contact Manager</h3>


<rich:separator height="1"
lineType="solid" width="100%"/>
<h:panelGrid columns="2" width="100%"
columnClasses="form-column, table-column">
<!-- Insert new contact form -->
<!-- Contact list -->
</h:panelGrid>

Como puede ver, también hemos añadido un encabezado (h3) y un espaciador entre el
encabezado y h:panelGrid. También se utilizaron dos clases CSS para el panelGrid, pero no
la hemos definido todavía.

Por lo tanto, vamos a abrir el archivo theme.css dentro del directorio stylesheet. Puede ver
algunas clases agregadas por seam-gen, no hay que hacerles caso y sólo agregue el código
CSS siguiente al final del archivo:

form-column {
vertical-align: top;
width: 20%;
}
table-column {
vertical-align: top;
width: 80%;
}

Esas clases simples CSS defininen el ancho de las dos columnas y alineación del contenido en
la parte superior.

El modelo
Tenemos que almacenar la información de contacto en una clase Java. En este caso, no
tenemos el soporte de una base de datos y los datos permanecen en la memoria. En una
aplicación real que vamos a desarrollar en los próximos capítulos vamos a usar MySQL.

Por lo tanto, estaremos utilizando un sencillo Plain Old Java Object (POJO) para almacenar la
información que necesitamos. Vamos a crear una clase de Java llamado ContactBean en el
paquete book.richfaces.scm (carpeta src/main) e insertar el siguiente código:

package book.richfaces.scm;
import java.util.Date;
public class ContactBean {
private String name;
private String surname;
private String email;
private Date birthdate;
public ContactBean() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirthdate() {
return birthdate;
}
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
}

Como puede ver, esta es una simple clase Java con propiedades privadas, así como
analizadores y modificadores públicos.

El bean administrado
A fin de administrar las acciones de este ejemplo simple (como la inserción de un nuevo
contacto, borrar un contacto, lista de todos los contactos), necesitamos un bean administrado.
Podemos utilizar un bean administrado JSF estándar (lo que tenemos que haces es configurar
el archivo faces-config.xml) o un componente de Seam y hemos elegido la segunda
opción porque no tenemos que configurar nada durante el uso de un componente de Seam.
Nos limitaremos a añadir una anotación a la clase que se va a utilizar (Seam simplifica el
desarrollo de JSF). De todas formas, el código es simple y puede ser utilizado como un bean
administrado estándar de JSF.

Por lo tanto, vamos a crear una clase de Java llamado ContactsManager en el paquete de
book.richfaces.scm (carpeta src/hot). Al principio, la clase está vacía:

package book.richfaces.scm;
public class ContactsManager {
}

En primer lugar, necesitamos un lugar para salvar a nuestra lista de contactos, una lista
estándar de instancias ContactBean. Por lo tanto, vamos a agregar el código para su manejo:

package book.richfaces.scm;
import java.util.ArrayList;
import java.util.List;

public class ContactsManager {


private List<ContactBean> contactsList;

public List<ContactBean> getContactsList() {


if (contactsList==null) {
contactsList=new ArrayList<ContactBean>();
}
return contactsList;
}
public void setContactsList(List<ContactBean> contactsList) {
this.contactsList = contactsList;
}
}

Es una simple propiedad privada con un accesor y un modificador. El accesor inicializa


lentamente la propiedad contactsList.

Para insertar contactos, creamos una nueva instancia de ContactBean para conectar con el
formulario Insertar nuevo contacto y una acción para insertarlo en la lista. Vamos a añadir el
código que necesitamos dentro de la clase ContactsManager:

private ContactBean newContact;


public ContactBean getNewContact() {
if (newContact==null) {
newContact=new ContactBean();
}
return newContact;
}
public void setNewContact(ContactBean newContact) {
this.newContact = newContact;
}
public void insertContact() {
getContactsList().add(0, getNewContact());
setNewContact(null);
}

Una vez más, tenemos la propiedad newContact con el accesor y modificador, y una acción
insertContact.

Crear el bean administrado


Como hemos dicho, con el fin de hacer la clase de un bean administrado, podemos utilizar la
forma estándar de JSF o la forma de Seam.

Le mostraremos la dos maneras, para que así usted pueda entender por qué el uso de Seam
es más simple.

Uso de la forma normal de JSF, tenemos que editar el archivo faces-config.xml para
decirle JSF que la clase ContactsManager es un bean administrado. Tenemos que agregar
el siguiente código dentro del elemento faces-config:

<managed-bean>
<managed-bean-name>contactsManager</managed-bean-name>
<managed-bean-class>
com.test.manager.ContactsManager
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

No es un código difícil para todos, pero debe detallarse ya que tenemos que describir la clase,
sus propiedades, y declarar el ámbito de aplicación de la clase (que es la sesión en este caso).
Incluso si las herramientas nos ayudan a hacer esta tarea, manteniendo el archivo faces-
config.xml es muy complicado.

Uso de JBoss Seam, lo único que tienes que hacer es anotar la clase ContactsManager,
que se convierte de esta manera:

package book.richfaces.scm;
import java.util.ArrayList;
import java.util.List;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
@Name("contactsManager")
@Scope(ScopeType.SESSION)
public class ContactsManager {
// code...
}

En este caso, sólo se agregaron dos anotaciones, uno (@Name) esto dice a Seam que es un
componente Seam (y también un bean administrado) llamado contactsManager, y el otro
(@Scope) le dice a Seam que la clase tiene ámbito de sesión (por lo que se mantendrá en la
memoria a través de las diversas solicitudes).

No necesita modificar el archivo faces-config.xml y describir todos los campos de la


clase. Simple, ¿no? Ahora estamos listos para escribir el XHTML y conectar con el bean
administrado (podemos referirnos a ésta en XHTML utilizando su nombre, es decir
contactsManager).

El formulario “Insertar nuevo contacto”


Este es el formulario que le pide al usuario algunos datos y los inserta en la lista de contactos
cuando el usuario hace clic en el botón Insertar. Todo esto se realiza mediante las llamadas a
Ajax!

Todos las validaciones de datos se realizan en Ajax al introducir los valores en los campos
Nombre y Apellidos, y después de que el botón ha sido pulsado en los demás campos. Pero es
sólo nuestra elección. Además, podemos aprovechar de las anotaciones Validator de Hibernate
para establecer los validadores en los campos, utilizando el soporte para Ajax RichFaces
Validator en f:validation (veremos cómo se hace esto en esta sección).

Con el fin de mostrar otras funcionalidades Ajax, también queremos que el botón Insertar
cambie el título, mientras el usuario está escribiendo su nombre y apellido.

La captura de pantalla siguiente muestra el aspecto final que queremos para el formulario:
El formulario principal
Para describir la caja del formulario, usamos un componente rich:panel con un encabezado.
Dentro de él, ponemos un h:panelGrid con una columna para insertar campos, uno debajo
del otro. Por lo tanto, tenemos el diseño del formulario listo, solo tienen que insertar este código
en el archivo de home.xhtml (sustituir el comentario <!-- Insert new contact form -
->):

<rich:panel>
<f:facet name="header">Insert new contact</f:facet>
<h:form id="fInsertContact">
<h:panelGrid columns="1">
<!-- fields -->
</h:panelGrid>
</h:form>
</rich:panel>

Hemos declarado un panel simple con un encabezado utilizando el facet "header", al declararlo.
Si el header es sólo texto, también puede utilizar el atributo de cabecera de esta manera:

<rich:panel header="Header text">


...
</rich:panel>

Como puede ver, un panel es fácil de usar y puedes poner lo que quiera dentro de ella.
Además, es totalmente personalizable mediante temas.

f:verbatim tag

Es importante no usar f:verbatim para auto-contenedores, ya que es un componente transitorio


y no se guardan en el árbol de componentes JSF.

Los campos del formulario


Después de declarar el panel, tenemos que poner los campos en su interior, a fin de
conectarlos a los beans administrados.

Hemos declarado un bean administrado llamado contactsManager, que contiene una


instancia de ContactBean (el bean que representa un contacto), distintos métodos para listar ,
insertar y eliminar contactos. Para insertar un nuevo contacto utilizamos newContact, vamos a
conectar los campos a esta instancia (que está dentro del bean contactsManager).

Aquí está el código para la descripción de los campos del formulario, inserta en el lugar del
comentario <!--fields -->:

<h:outputLabel for="name" value="Name"/>


<h:inputText id="name"
value="#{contactsManager.newContact.name}"
required="true">
<rich:beanValidator/>
a4j:support event="onkeyup"
timeout="200"
ajaxSingle="true"
reRender="insertButton"/>
</h:inputText>
<rich:message for="name" style="color: red;"/>
<h:outputLabel for="surname" value="Surname"/>
<h:inputText id="surname"
value="#{contactsManager.newContact.surname}"
required="true">
<rich:beanValidator/>
<a4j:support event="onkeyup" timeout="200"
ajaxSingle="true" reRender="insertButton"/>
</h:inputText>
<rich:message for="surname" style="color: red;"/>
<h:outputLabel for="email" value="Email"/>
<h:inputText id="email"
value="#{contactsManager.newContact.email}"
required="true">
<rich:beanValidator/>
</h:inputText>
<rich:message for="email" style="color: red;"/>
<h:outputLabel for="birthdate" value="Birthdate"/>
<rich:calendar id="birthdate"
value="#{contactsManager.newContact.birthdate}"
required="true">
<rich:beanValidator/>
</rich:calendar>
<rich:message for="birthdate" style="color: red;"/>
<rich:spacer height="15"/>
<rich:separator height="1" lineType="dotted" width="100%"/>
<a4j:commandButton id="insertButton"
action="#{contactsManager.insertContact}"
value="Insert #{contactsManager.newContact.name} #{contactsManager.
newContact.surname}"
reRender="fInsertContact"/>

Como podemos ver, en el primer bloque de código (en el campo nombre) tenemos una etiqueta
estándar de JSF h:outputLabel para la inserción de la etiqueta de la entrada y una etiqueta
estándar h:inputText conectado al campo ContactBean con el atributo de valor.

Después de eso, hemos utilizado rich:message en lugar del componente estándar


h:message, ya que apoya AJAX fuera de la caja (y ofrece más personalización también).
Consulte la siguiente sección para una mejor explicación.
Volviendo a h:inputText, podemos ver dos nuevas etiquetas, rich:beanValidator para
la validación de campo Ajax y a4j:support para actualizar la imagen del botón Insertar
mientras escribe.

Uso de mensajes RichFaces y componentes de mensajes en lugar


de las estándar
Al utilizar un componente est[andar h:message o h:messages, usted no recibe el JSF Ajax
de mensajes de apoyo para los eventos JSF Ajax y los mensajes no se muestran después de
un evento de AJAX.

Con los componentes ricos rich:message y rich:messages, no tienes que preocuparte si


estos trabajan con Ajax y peticiones JSF tradicionales.

El uso básico es muy simple y es lo mismo que la estándar:

<rich:message for="myComponentId" />

Hacer una versión de Ajax de la componente estándar es sólo una parte de la labor del equipo
RichFaces ha hecho en este componente. De hecho, añadieron una serie de características
interesantes que se pueden utilizar para personalizar su aplicación.

De hecho, proporcionan una mirada altamente personalizable y se sienten con soporte CSS.
Además, puede personalizar cada parte de los componentes mediante la adición de una carilla
para diferentes tipos de mensajes (WARN, INFO, FATAL, ERROR), y personalizar el
"marcador" (por ejemplo, un icono) en consecuencia:

<rich:message for="myComponentId">
<f:facet name="warnMarker">
<h:graphicImage url="/images/warning.png"/>
</f:facet>
<f:facet name="errorMarker">
<h:graphicImage url="/images/error.png"/>
</f:facet>
<f:facet name="passedMarker">
<h:graphicImage url="/images/passed.png"/>
</f:facet>
</rich:message>

Además, puede agregar una cadena de texto passedLabel que se muestra cuando no hay
mensaje de error.

Validación de nuestro campo de una manera sencilla


Hay tres componentes JSF que puede utilizar para la validación. Vamos a ver en más detalle
en el capítulo 4, la aplicación. Hemos utilizado los rich:beanValidator aquí, ya que utiliza
el marco de Hibernate Validator para leer las reglas de validación directamente en el campo de
ContactBean.

De esta manera, no tenemos que escribir (y mantener!) los mismos validadores en diferentes
campos, que se refieren a la misma entrada.

En nuestro caso, podemos añadir anotaciones de Hibernate Validator a la clase del modelo
(ContactBean).
rich:beanValidator lee y utiliza éstos para decidir la estrategia de validación; la clase
ContactBean se define ahora como sigue:

public class ContactBean {


private String name;
private String surname;
private String email;
private Date birthdate;
public ContactBean() {
}
@NotNull
@Length(min = 3, max = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@NotNull
@Length(min = 3, max = 20)
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
@NotNull
@Email
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@NotNull
@Past
public Date getBirthdate() {
return birthdate;
}
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
}

No es el propósito de este libro para explicar cómo funciona el marco de Hibernate Validator,
pero es sencillo de comprender desde el ejemplo. Si nos fijamos en el método getName,
podemos ver las anotaciones @NotNull y @Length (este último con dos parámetros). Dicen
rich:beanValidator que el campo no debe ser nulo, y que tiene una longitud mínima de
dos caracteres y una longitud máxima de 20 caracteres. En el 99% de las solicitudes, sólo
tenemos que anotar validadores para cada campo y ya está. De todos modos, siempre es
posible agregar otro f:validator con rich:beanValidator con el fin de agregar reglas
de validación específicos.

Si nos fijamos en los otros campos de la clase ContactBean, podemos encontrar otros
validadores como @Email y @Past. Hay otros que se pueden utilizar y usted puede incluso
crear sus propios validadores para un propósito específico.
Agregar Ajax a componentes estándar de JSF: a4j:support
Volviendo al código de forma, después de la etiqueta del validador, podemos ver otra etiqueta,
a4j:support.

Este es el componente más importante de Ajax de la biblioteca y lo coloca como un niño añade
capacidades de Ajax para componentes estándar de JSF. El atributo event se utiliza para
definir el evento de JavaScript que la solicitud se adjuntará el Ajax (en este caso, onkeyup que
dispara un evento para todas las claves que el usuario).

El atributo timeout describe el número de milisegundos (ms) para esperar antes de disparar
la petición Ajax. En este caso, es útil para evitar una gran cantidad de peticiones Ajax, mientras
el usuario está escribiendo.

El atributo ajaxSingle cuenta el marco que acaba de enviar el valor del campo y no para
enviar el formulario completo (sólo necesitamos la fecha que se incluirá en el campo, y los
datos del formulario se presentará haciendo clic en el botón Insertar).

Por último, el atributo reRender contiene el id (s) del componente JSF para "reRender"
después de la petición Ajax. En este caso, queremos actualizar el título de la componente
insertButton, que contiene el valor del campo (contactsManager. newContact.name)
actualizado por la petición Ajax.

Otro ejemplo se muestra como sigue:

<h:form>
<h:inputText value="#{aBean.myText}">
<a4j:support event="onblur" reRender="out1" />
</h:inputText>
</h:form>
<h:outputText
id="out1"
value="#{aBean.myText}" />
Cuando el usuario pone un poco de texto dentro de inputText y presiona la tecla Tab o haga
clic fuera del campo de entrada (onblur evento JavaScript), a4j:support actualizará la
propiedad myText del grano aBean con el texto escrito. Luego se actualizará el outputText
con id="out1".

El campo Apellido obras como el campo Nombre, a diferencia del campo de correo
electrónico no contiene a4j:support y se valida (siempre usando una petición Ajax) cuando el
usuario hace clic en el botón Insertar (a4j:commandButton).

El campo Calendario
En el cuarto campo, se utiliza el componente rich:calendar para obtener la fecha de
nacimiento del contacto. Es muy simple de usar, pero tiene un montón de campos opcionales y
pueden llegar a ser muy poderosos. Se puede utilizar para ajustar el tiempo también. Es
totalmente personalizable, muestra una ventana emergente, y también trabaja con entrada
manual.

En la siguiente captura de pantalla, puede ver cómo aparece cuando el usuario hace clic en el
icono de la derecha para seleccionar la fecha.

Tendremos en cuenta el uso de este componente con mayor profundidad en los capítulos
siguientes.

Componentes de diseño simples: rich:separator y rich:spacer


Esos son dos simples, pero los componentes de diseño de gran utilidad. Pueden mostrar una
línea personalizables (por ejemplo, continuos, discontinuos, doble, y así sucesivamente) y
personalizado (en tamaño), bloque vacío representa como una imagen transparente,
respectivamente.

El resultado HTML de la inserción de un elemento rich:separator con el atributo la height


establecido en 1, el atributo width establecido a 100%, y el atributo lineType establecido a
dotted es el siguiente:

<div class="rich-separator " style="height: 1px; width: 100%;


background-image: url(/SimpleContactManager/a4j/g/3_2_2.SR1org.
richfaces.renderkit.html.images.SimpleSeparatorImage/DATB/
eAFjYNxa6sUIAATTAXc_); null;"></div>
En lugar de utilizar el componente rich:separator, si se utiliza un componente
rich:spacer con el atributo height establecido a 15, se obtiene el código XHTML:

<img class="rich-spacer " height="15" id="fInsertContact:j_id21"


src="/SimpleContactManager/a4j/g/3_2_2.SR1images/spacer.gif"
width="1"
/>

Botones de comando Ajax: a4j:commandButton


El último componente que se puede ver en el código de campo del formulario es
a4j:commandButton. Es la versión Ajax de h:commandButton y produce peticiones Ajax
en lugar de los estándar, así como los atributos que tienen que gestionar las opciones de Ajax.

El más importante es el atributo reRender que le dice al motor de JavaScript que área (s) de
la página o componente debe ser actualizado después de una respuesta Ajax.

Se puede volver a hacer uno o más componentes después de una petición Ajax. Se acepta un
objeto String (un ID de componente o una coma lista de ID separados), Set, Collection, o Array
(pasa a través de EL JSF).

En nuestro código, se utiliza para llamar al método de acción


(contactsManager.insertContact) que se inserta el grano newContact en el arreglo de
la lista de contactos, a continuación, volver a revisualizar el formulario y la lista de contactos
rich:dataTable. El formulario puede ser re-emitida para limpiar los campos (de hecho,
después de la inserción, el método de contactsManager.insertContact limpia el campo
para que podamos insertar otro contacto en una nueva instancia de ContactBean).

Además, como se puede ver, el valor contiene el nombre y apellidos inserta. Por lo tanto, si el
usuario escribe a John como el nombre y Wilson como el apellido, el valor del título de
a4j:commandButton se convierte en "Insertar John Wilson", y gracias a a4j:support (como
hemos visto en los párrafos anteriores), cambia mientras el usuario está escribiendo.

He aquí otro ejemplo:

<h:form>
<a4j:commandButton value="update" action="#{myBean.
anOptionalAction}"
reRender="block1,text1"
</h:form>
<h:panelGroup id="block1">
...
</h:panelGroup>
<h:outputText id="text1" ... />

Cuando el usuario hace clic en el botón de actualización dictado por a4j:commandButton, el


motor de JavaScript RichFaces hará una petición Ajax al servidor y esperar la respuesta.
Después de eso, se actualizará los elementos block1 y text1. Tiene muchos más atributos
útiles, que veremos en los capítulos siguientes.

Comandos de enlace Ajax: a4j:commandLink


Otra etiqueta útil es a4j:commandLink, que es la versión Ajax de h:commandLink. Funciona
como a4j:commandButton, sino que hace un enlace (tag HTML) en lugar de el elemento de
entrada. Es necesario mantenerlo dentro de la etiqueta h:form.

La lista de contactos
Con el fin de mostrar (y permitir al usuario eliminar) la lista de contactos, que vamos a utilizar la
versión RichFaces del clásico h:dataTable. Funciona de la misma manera, pero es muy útil y
fácil de usar las características mejoradas. Se incluye en una etiqueta rich:panel (esta vez
sin una cabecera, porque vamos a utilizar la de cabecera el facet rich:dataTable).

También utilizaremos rich:datascoller para agregar paginación Ajax a los registros


rich:dataTable y a4j:commandLink para agregar un botón para cada contacto en la lista.

Usted puede ver el aspecto final en la siguiente captura de pantalla (el botón de borrar se
muestra como un icono X en la última columna de la tabla.)

Aquí está el código que hay que añadir a su página home.xhtml ( reemplazar el comentario <!-
-Contact list -->) a fin de hacer la lista de contactos:

<rich:panel>
<h:form id="fContactsList">
<rich:dataTable id="edtContactsList"
value="#{contactsManager.contactsList}"
var="contact" rows="5" width="100%">
<f:facet name="header">Contact List</f:facet>
<rich:column sortBy="#{contact.name}"
filterBy="#{contact.name}">
<f:facet name="header">Name</f:facet>
<h:outputText value="#{contact.name}"/>
</rich:column>
<rich:column sortBy="#{contact.surname}"
filterBy="#{contact.surname}">
<f:facet name="header">Surname</f:facet>
<h:outputText value="#{contact.surname}"/>
</rich:column>
<rich:column sortBy="#{contact.email}"
filterBy="#{contact.email}">
<f:facet name="header">Email</f:facet>
<h:outputText value="#{contact.email}"/>
</rich:column>
<rich:column align="center">
<f:facet name="header">Birthdate</f:facet>
<h:outputText value="#{contact.birthdate}">
<f:convertDateTime type="date" dateStyle="short"/>
</h:outputText>
</rich:column>
</rich:dataTable>
<h:outputText value="No contacts found"
rendered="#{empty contactsManager.contactsList}"/>
<rich:datascroller id="dsContactsList" for="edtContactsList"
renderIfSinglePage="false" />
</h:form>
</rich:panel>

Como podemos ver, hemos usado una etiqueta rich:dataTable como una etiqueta
h:dataTable estándar (De hecho, hemos utilizado el valor del parámetro var y rows,
respectivamente, para establecer el arreglo de la lista de contactos. El parámetro de rows es la
solicitud variable de alcance para manejar el objeto de la fila actual y el número de filas por
página.).

También hemos utilizado las versiones "ricas" de h:column, rich:column, con el fin de
configurar el filtrado y funciones de ordenación para los campos nombre, apellido, y correo
electrónico. La habilitación de la columna de base para la ordenación y filtrado es muy simple,
sólo tienes que conectar los atributos sortBy y filterBy de rich:column con el campo
que desea ordenar (o filtro).

No hay nada nuevo en el código.

Hablaremos acerca de la "No hay contactos" valor de h:outputText en el siguiente capítulo


(hablando de marcadores de posición Ajax). Después de ello, hemos insertado
rich:datascroller y conectado a rich:dataTable utilizando el atributo for. El atributo
renderIfSinglePage no visualizará el datascroller hasta que la tabla contenga al
menos seis registros (uno más que el atributro rows de los rich:dataTable), lo que significa
que serán dos páginas de datos.

Volver a visualizar la lista de contactos después de añadir un


nuevo contacto
En este punto, si tratamos de añadir un nuevo contacto, la lista de contactos no se actualizará.
¿Por qué?

Esto es porque tenemos que decirle a insertButton que actualice no sólo la forma, sino
también la lista de contactos después de ejecutar la acción.

Con el fin de hacer eso, basta con modificar la propiedad reRender de insertButton
añadiendo el id del formulario de la lista de contactos (fContactList), por lo que el
componente aparece ahora como esta:

<a4j:commandButton
id="insertButton"
action="#{contactsManager.insertContact}"
value="Insert #{contactsManager.newContact.name}
#{contactsManager.newContact.surname}"
reRender="fContactsList,fInsertContact" />
Ahora también se actualizará la lista de contactos que le mostrará el contacto acaba de
insertar.

Agregando el botón de eliminar


Nos gustaría añadir un botón de borrar como la última columna de la tabla. Con el fin de
hacerlo, basta con insertar el código siguiente después de la columna birthdate:

<rich:column width="50" align="center">


<f:facet name="header">Delete</f:facet>
<a4j:commandLink reRender="fContactsList"
action="#{contactsManager.deleteContact}">
<h:graphicImage style="border-width: 0px;"
value="images/buttons/delete.gif" />
<f:setPropertyActionListener value="#{contact}"
target="#{contactsManager.contactToDelete}"/>
</a4j:commandLink>
</rich:column>

Se utilizó a4j:commandLink y una imagen (pero que debería haber utilizado el


a4j:commandButton con el atributo graphicImage con la imagen correspondiente) para
añadir agregar la funcionalidad de borrar los contactos.

Este código es sencillo de entender. Cuando el usuario hace clic en el icono de supresión (es
una X de color rojo), la variable contact (que apunta a la instancia ContactBean de la fila de
la tabla seleccionada) se establecerá en la propiedad contactToDelete del bean
contactsManager. Después de eso, la acción contactsManager.deleteContact será
llamado y la instancia será removido de la lista de contactos. Tras la ejecución de la acción, en
el marco RichFaces volverá a visualizar el formulario lista de contactos (de acuerdo con lo
establecido en la propiedad reRender de a4j:commandLink) que muestra la nueva lista
(sin la fila eliminada).

Resumen
En este capítulo, se probó el poder de los componentes de RichFaces construir aplicaciones
AJAX mediante el desarrollo de un ejemplo sencillo.

Usted aprendió los fundamentos de RichFaces paso a paso, desde la creación del proyecto
hasta la modificación del código, utilizando componentes muy importantes (como
a4j:commandButton, a4j:commandLink, rich:dataTable, y rich:messages) y
sus propiedades Ajax (por ejemplo , reRender).

En el próximo capítulo, vamos a empezar a construir una aplicación real (un gestor de
contactos avanzada), utilizando el marco en profundidad.

You might also like