RichFaces

RECU-0134 (Recurso Referencia)

Descripción

 En este apartado se pretende dar una visión de las características que RichFaces ofrece:

  • Intensificar el conjunto de beneficios JSF al trabajar con AJAX. RichFaces está completamente integrado en el ciclo de vida de JSF. Mientras que otros marcos sólo dan acceso a los managed beans, RichFaces permite acceder al action y al valor del listener, así como invocar a validadores y convertidores durante el ciclo de petición-respuesta de AJAX.
  • Añadir capacidad AJAX a aplicaciones JSF. El framework proporciona dos librerías de componentes (Core AJAX y la interfaz de usuario). La librería Core nos permite agregar la funcionalidad AJAX en las páginas que queramos sin necesidad de escribir nada de código JavaScript. RichFaces permite definir eventos en la propia página. Un evento invoca a una petición AJAX, sincronizándose así zonas de la página y componentes JSF después de recibir la respuesta del servidor por AJAX.
  • Crear rápidamente vistas complejas basándose en la caja de componentes. La librería UI (Interfaz de usuario) que contiene componentes para agregar características de interfaz de usuario a aplicaciones JSF. Se amplía el framework de RichFaces incluyendo un gran conjunto de componentes "habilitación de AJAX" que extiende el soporte de la página. Además, los componentes de RichFaces están diseñados para ser usados sin problemas con otras librerías de componentes en la misma página, de modo que existen más opciones para el desarrollo de aplicaciones
  • Escribir componentes propios con función soportada por AJAX. El CDK o Kit de Desarrollo de Componentes basado en MAVEN, incluye un generador de código para plantillas JSP utilizando una sintaxis similar. Estas capacidades ayudan a evitar un proceso de rutina de un componente de creación.
  • Proporciona un paquete de recursos con clases de aplicación Java. Además de su núcleo, la funcionalidad de RichFaces para AJAX proporciona un avanzado soporte a la gestión de diferentes recursos: imágenes, código JavaScript y hojas de estilo CSS. El framework de recursos hace posible empaquetar fácilmente estos recursos en archivos jar junto con el código de los componentes personalizados.
  • Generar fácilmente recursos binarios sobre la marcha. Los recursos del framework pueden generar imágenes, sonidos, hojas de cálculo de Excel, etc.
  • Crear una moderna interfaz de usuario 'look-and-feel' basadas en tecnología de skins. RichFaces proporciona una función que permite definir y administrar fácilmente diferentes esquemas de color y otros parámetros de la interfaz de usuario, con la ayuda de los parámetros del skin. Por lo tanto, es posible acceder a los parámetros del skin desde el código JSP y el código de Java (por ejemplo, para ajustar las imágenes generadas sobre la marcha basadas en la interfaz de usuario). RichFaces viene con una serie de skins predefinidas para empezar, pero también se pueden crear fácilmente skins propios.

Permite gracias a una herramienta del framework generar casos de prueba para los componentes que estas creando (actions, listeners, etc.).

Los componentes de la interfaz de usuario de RichFaces vienen preparados para su uso fuera del paquete, así los desarrolladores ahorrarán tiempo y podrán disponer de las ventajas mencionadas para la creación de aplicaciones Web. Como resultado, la experiencia puede ser más rápida y fácil de obtener.

RichFaces permite definir (por medio de etiquetas de JSF) diferentes partes de una página JSF que se desee actualizar con una solicitud AJAX, proporcionando así varias opciones para enviar peticiones AJAX al servidor.

AjaxFilter. Para obtener todos los beneficios de RichFaces, se debe registrar un filtro en el archivo web.xml de la aplicación. Este filtro reconoce múltiples tipos de peticiones. La solicitud de filtro reconoce múltiples tipos. El diagrama de secuencia de la siguiente figura muestra la diferencia en la tramitación de un página JSF "regular" y una solicitud AJAX.

En el primer caso todo el árbol completo de JSF será codificado, mientras que en la segunda opción depende del "tamaño" de la región AJAX. Como se puede ver, en el segundo caso el filtro analiza el contenido de la respuesta AJAX antes de enviarlo al cliente

En ambos casos, la información necesaria sobre recursos estáticos o dinámicos que pide la aplicación será registrada por la clase ResourceBuilder. Cuando llega una petición de un recurso, el filtro de RichFaces comprueba la caché de recursos para ese recurso y si está, el recurso se envía al cliente. De lo contrario, el filtro busca el recurso dentro de que estén registrados por el ResourceBuilder. Si el recurso está registrado, el filtro de RichFaces enviará una petición al ResourceBuilder para crear (entregar) el recurso. La figura siguiente muestra la forma de procesar la petición de un recurso

Limitaciones y reglas

  • Cualquier marco AJAX no debe añadir o eliminar, sólo sustituir los elementos de la página. Para actualizaciones con éxito, un elemento con el mismo identificador que en la respuesta debe existir en la página. Si desea añadir un código a una página, es recomendable poner un marcador de posición para él (cualquier elemento vacío). Por la misma razón, se recomienda colocar los mensajes en el componente "AjaxOutput"
  • No utilice para los contenedores self-rendered, ya que este componente es transitorio y no se guarda en el árbol.
  • Las peticiones AJAX se hacen por las funciones de XMLHttpRequest en formato XML, pero este XML omite la mayoría de las validaciones y las correcciones que pudieran hacerse en un navegador. Por lo tanto, crea sólo un código compatible con los estándares de HTML y XHTML, sin omitir los elementos requeridos o atributos. Las correcciones necesarias sobre el XML son automáticamente hechas por el filtro XML en el servidor, pero muchos de los efectos inesperados pueden ser producidos por un código HTML incorrecto.
  • El ViewHandler de RichFaces se pone en frente de la cadena de ViewHandlers de Facelets.
  • Los componentes RichFaces utilizan su propios renders. RichFaces, en la fase de procesamiento de respuesta, hace un recorrido del árbol de componentes y llama a su propio procesador para poner el resultado en Faces Response.

Optimización de peticiones AJAX

A continuación se ofrece una visión de las principales características de las peticiones AJAX.

Re-Rendering

Los atributos AJAX son comunes para los componentes AJAX como <a4j:support>, <a4j:commandButton>, , <a4j:poll>, <a4j:push> y así sucesivamente. Además, la mayoría de componentes RichFaces construidos con soporte AJAX tienen estos atributos para un propósito similar. Los atributos ayudan a exponer sus características. La mayoría de los atributos tienen por defecto valores. Así, se puede comenzar a trabajar con RichFaces sin saber el uso de estos atributos. Sin embargo, su uso permite ajustar el comportamiento que AJAX requiere.

"reRender" es un atributo clave. El atributo permite indicar una zona en una página que debería ser actualizada como respuesta a la interacción AJAX. El valor del atributo "reRender" es un identificador del Componente JSF o una lista de id.

Un ejemplo sencillo se muestra a continuación:

...
<a4j:commandButton value="update" reRender="infoBlock"/>
...
<h:panelGrid id="infoBlock">
...
</h:panelGrid>

Problema más común con el uso de reRender se produce cuando el componente que tiene un atributo "rendered". Tenga en cuenta que JSF no marca el lugar en el navegador DOM cuando el resultado del componente debe ser colocado en el caso de que "rendered" devuelve condición falsa. Por lo tanto, después de que el componente se hizo "rendered" durante la petición AJAX, RichFaces proporciona el código rendered al cliente, pero no actualiza una página, porque el lugar para la actualización es desconocido.

Procesamiento de la cola de peticiones

El atributo "eventsQueue" define el nombre de la cola que se utiliza para ordenar las próximas Peticiones AJAX. De forma predeterminada, RichFaces no encola peticiones AJAX. Si se producen acontecimientos al mismo tiempo, ellos vendrán al servidor de forma simultánea.

Las implementaciones de JSF no garantizan a la petición de que lo primero será servido o pasado a el primer ciclo de vida de JSF. El orden de cómo se modificarán los datos del lado servidor en el caso de solicitudes simultáneas puede ser impredecible. El uso de atributos eventsQueue permite evitar la confusión posible. Se debe definir el nombre de la cola de forma explícita, si espera que el tráfico de AJAX intensiva en su aplicación.

La siguiente solicitud a disposición en la misma cola espera hasta que la previa no se procesa y la respuesta AJAX se devuelve si se define el atributo "eventsQueue". Además, RichFaces empieza a eliminar de la cola peticiones "similares". Las peticiones "similares" son las peticiones producidas por el mismo evento. Por ejemplo, de acuerdo con el siguiente código, sólo la solicitud más reciente será envía al servidor:

... 
<h:inputText value="#{userBean.name}">
<a4j:support event="onkeyup" eventsQueue="foo" reRender="bar" />
</ h: inputText>
...

El atributo "requestDelay" define el tiempo que la solicitud espera en la cola antes de que esté listo para enviar. Cuando el tiempo de retraso es mayor, la solicitud será enviada al servidor o eliminada si ya hay una nueva solicitud "similar" en la cola.

Opciones del procesamiento de datos

RichFaces utiliza el enfoque basado en AJAX para el envió de peticiones. Esto significa que cada vez, que haga clic en un botón de AJAX o <a4j:poll> produce una solicitud asincrónica, los datos del formulario JSF más cercano se envían mediante el objeto XMLHttpRequest. El formulario de datos contiene los valores del elemento de entrada del formulario y la información auxiliar, como el estado de los datos.

Cuando el valor del atributo "AJAXSingle" es "true", ordena incluir sólo un valor del componente (junto con <f:param> o <a4j:actionparam> valores en su caso) al mapa de peticiones. En caso de <a4j:support>, es un valor del componente principal. Un ejemplo se encuentra a continuación:

... 
<h:form>
<h:inputText value="#{person.name}">
<a4j:support event="onkeyup" reRender="test" AJAXSingle="true"/>
</ h: inputText>
<h:inputText value="#{person.middleName}"/>
</ form>
...

En este ejemplo, la solicitud sólo contiene el componente de entrada que hace la generación de petición, no todos los componentes que figuran en un formulario, a causa del valor AJAXSingle = "true".

El componente de AJAX es similar a cualquier otro componente JSF AJAX. Ello permite enviar el formulario. Se pueden utilizar los atributos "action" y "ActionListener"para invocar al método de acción y definir el caso de la acción. El método "action" debe devolver null si desea tener una respuesta AJAX con una actualización de la página parcial.

Este modo regular se llama "AJAX Non Response". En el caso de que la acción no devuelve null, pero el resultado de la acción coincide con una de las normas de navegación, RichFaces comienza a trabajar en el modo "AJAX Non Response". Este modo puede ser útil en dos casos importantes:

  • RichFaces permite organizar un flujo de página dentro del componente <a4j:include>. Este es un Asistente típico de escenario para un comportamiento similar. El contenido está tomado de la regla de navegación de las archivo faces de configuración (normalmente, faces-config.xml). Tenga en cuenta que el contenido del "wizzard" no está aislado del resto de la página. La página incluida no debe tener su propia <f:view> (no importa si utiliza Facelets). Se debe tener un componente AJAX dentro de la <a4j:include> para navegar entre las páginas del asistente.
  • Si desea hacer participar a los validadores y que vaya a la página siguiente sólo si la fase de validación se pasa con éxito, se puede reemplazar <h:commandButton> con <a4j:commandButton> y seleccione el método de "action" que lanza el desplazamiento a la página siguiente. Si el proceso de validación falla, la actualización parcial de la página se producirá y verá un mensaje de error.

Como....

Realizar peticiones AJAX

Hay diferentes maneras de enviar peticiones AJAX desde una página JSF. Por ejemplo, puede usar las etiquetas <a4j:commandButton>, <a4j:poll> o <a4j:support>.

Todas estas etiquetas ocultan las actividades habituales de JavaScript que se requieren para la construcción de un objeto XMLHttpRequest y el envío de una petición AJAX. Además, le permiten decidir qué componentes de su Página de JSF se renderizan como resultado de la respuesta del AJAX (puede incluirse la lista de identificadores de los componentes en el atributo "reRender").

  • Las etiquetas a4j:commandButton y a4j:commandLink se utilizan para enviar una solicitud AJAX en eventos Javascript como "onclick".
  • La etiqueta a4j:poll se utiliza para enviar una petición AJAX periódicamente utilizando un temporizador.
  • La etiqueta a4j:support permite añadir funcionalidad AJAX a componentes de JSF estándar y enviar peticiones AJAX mediante un evento JavaScript: "onkeyup", "onmouseover", etc

Decidir qué enviar

Se puede describir una región de la página que se desea enviar al servidor, de esta manera se puede controlar qué parte de la página JSF se decodifica en el servidor cuando se le envía una petición AJAX.

La manera más sencilla de describir un área en una página JSF es no hacer nada, porque el contenido que se encuentra entre las etiquetas f:view y /f:view se considera por defecto región AJAX. No obstante, pueden definirse múltiples regiones AJAX en la página JSF (incluso pueden ser anidadas) mediante el uso de la etiqueta a4j:region.

Decidir qué modificar

El uso de identificadores en el atributo "reRender" define "zonas AJAX" de actualización para que funcione correctamente.

No obstante, no se puede utilizar este método si la página contiene, por ejemplo, una etiqueta f:verbatim y se desea actualizar su contenido con una respuesta AJAX.

El problema con la etiqueta f:verbatim, como se ha descrito anteriormente, está relacionado con el valor del indicador de transición de los componentes JSF. Si el valor de este flag es true, el componente no debe participar en la operación de guardado o recuperación del estado del proceso.

Con el fin de ofrecer una solución a este tipo de problemas, RichFaces utiliza el concepto de grupo de salida que se define con la etiqueta a4j:outputPanel. Si se pone una etiqueta f:verbatim en el interior de un panel de salida, entonces el contenido de la etiqueta f:verbatim y el contenido de los hijos del grupo podrían ser actualizados mediante una repuesta AJAX. Para ello hay dos formas de controlarlo:

  • Estableciendo el valor del atributo "AJAXRendered" a "true".
  • Estableciendo el valor del atributo "reRender" de un componente Action al valor de un ID del panel de salida.

Decidir qué procesar

El atributo "process" permite definir los identificadores de componentes para ser tratados conjuntamente con los componentes que están marcado como ajaxSingle o envuelto en la región.

Se podría hacer uso del atributo "process" cuando se necesita para procesar sólo dos componentes en las diferentes partes de vista. Imagine que usted necesita para procesar sólo dos campos de entrada, pero no todos los de la vista. Si envuelve la primera entrada a la región o utiliza <a4j:support> con ajaxSingle = "true" anidado la segunda entrada no será procesada. Aquí hay una solución simple:

... 
<h:inputText value="#{bean.name}" id="nombre">
<a4j:support AJAXSingle="true" process="email" event="onblur" reRender="someOut"/>
</ h: inputText>
<h:inputTextarea value="#{bean.description}" id="desc" />
<h:inputText value="#{bean.email}" id="email">
<a4j:support AJAXSingle="true" process="name" event="onblur" reRender="someOut"/>
</ h: inputText>
...

Utilización de filtros

RichFaces utiliza un filtro de corrección de código recibido en una petición AJAX. En el caso de una petición "regular" JSF de un navegador hace la corrección de forma independiente. En caso de una petición AJAX, a fin de evitar la destrucción de diseño es necesario utilizar un filtro, porque un código recibido podría diferir de un código validado por un navegador y el navegador no hacer las oportunas correcciones. Un ejemplo de cómo configurar un filtro en un archivo web.xml de la aplicación se muestra a continuación:

... 
<filter>
<display-name> RichFaces Filter </ display-name>
<filter-name> RichFaces </ filter-name>
<filter-class> org.AJAX4jsf.Filter </ filter-class>
</ filter>
...

Validaciones en RichFaces

Los validadores se describen de la siguiente manera:

  • Validación AJAX. Se describe mediante el uso de la etiqueta <rich:AJAXValidator> y ofrece características AJAX a la implementación de validaciones de JSF. Permite introducir un evento que active la validación. Un ejemplo:
<rich:panel>
   <f:facet name="header">
      <h:outputText value="User Info:" />
   </f:facet>
   <h:panelGrid columns="3">
      <h:outputText value="Name:" />
      <h:inputText value="#{userBean.name}" id="name" required="true">
         <f:validateLength minimum="3" maximum="12"/>
         <rich:AJAXValidator event="onblur"/>
      </h:inputText>
      <rich:message for="name" />
      .
      .
      .
   </h:panelGrid>
</rich:panel>
  • Validación en el Bean. Se utiliza la etiqueta <rich:beanValidator> que permite realizar validaciones basadas en las restricciones impuestas en Hibernate. El componente se define de la misma manera que una validación normal:
<rich:panel>
   <f:facet name="header">
      <h:outputText value="User Info:" />
   </f:facet>
   <h:panelGrid columns="3">
      <h:outputText value="Name:" />
      <h:inputText value="#{userBean.name}" id="name" required="true">
         <f:validateLength minimum="3" maximum="12"/>
         <rich:beanValidator summary="Invalid name"/>
      </h:inputText>
      <rich:message for="name" />
      .
      .
      .
   </h:panelGrid>
</rich:panel>

y tiene su soporte dentro de la clase

package org.richfaces.demo.validation;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Pattern;
import org.hibernate.validator.Max;
import org.hibernate.validator.Min;

public class ValidationBean {
   private String progressString="Fill the form please";

   @NotEmpty
   @Pattern(regex=".*[^\\s].*", message="This string contain only spaces")
   @Length(min=3,max=12)
   private String name;

   public ValidationBean() {

   }

   /* Corresponding Getters and Setters */

   public void success() {
     setProgressString(getProgressString() + "(Strored successfully)");
   }

   public String getProgressString() {
     return progressString;
   }

   public void setProgressString(String progressString) {
     this.progressString = progressString;
   }
}
  • Validaciones GraphValidator. Se utiliza la etiqueta <rich:graphValidator> que básicamente mantiene las características de la validación bean. La diferencia entre ambos componentes es que mientras el validador bean está dirigido a un componente de entrada, el graphvalidator se puede aplicar a un conjunto de componentes. A continuación un ejemplo de la configuración de graphValidator:
<rich:graphValidator>
   <h:panelGrid columns="3">
      <h:outputText value="Name:" />
      <h:inputText value="#{validationBean.name}" id="name">
          <f:validateLength minimum="2" />
      </h:inputText>
      <rich:message for="name" />
      <h:outputText value="Email:" />
      <h:inputText value="#{validationBean.email}" id="email" />
      <rich:message for="email" />
   </h:panelGrid>
</rich:graphValidator>

Actualmente no hay disponible ningún proyecto dentro del repositorio de la Junta de Andalucía que utilice RichFaces, no obstante ya se plantean algunos, que pronto harán uso de esta implementación.

Un área donde AJAX es útil es la validación. Usando AJAX, es posible crear lo que se denomina "validación en directo", es decir, se devuelve al usuario una respuesta sobre el valor introducido dentro de un campo del formulario. De esta manera, no resulta necesario completar el proceso completo del formulario y lanzar todas las validaciones. Esto sin duda influye en una mejor experiencia para el usuario.

Ademas de los componentes de validación asociados a JSF, RichFaces amplia este aspecto para incluir la interacción AJAX dentro de la validación. Para ello proporciona tres tipos de validadores que se definen a continuación

  • <rich:AJAXValidator> permite introducir la característica de AJAX de responder a un evento (click, tabulado, etc..) para introducir la validación
  • <rich:beanValidator> que utiliza el marco de Hibernate Validator para leer las reglas de validación directamente
  • <rich:graphValidator> similar al anterior pero que permite introducir mas de un componente en la validación.

El funcionamiento es sencillo podemos añadir anotaciones de Hibernate Validator a la clase del modelo que queremos validar. rich:beanValidator lee y utiliza éstos para decidir la estrategia de validación. Éstos son algunas de las anotaciones mas importantes

  • @Length(min=, max=): Comprueba si la longitud de la cadena coincide con valores mínimo y máximo
  • @Max(value=): Comprueba si el valor es menor o igual al valor máximo
  • @Min(value=): Comprueba si el valor es superior o igual al valor
  • @NotNull: Comprueba si el valor del campo es nulo
  • @Email: Comprueba si la cadena se ajusta a la especificación de la dirección de correo electrónico
  • @Range(min=, max=): Comprueba si el valor está entre los valores mínimo y máximo (incluido)
  • @Future: Comprueba si la fecha está en futuro
  • @Past: Comprueba si la fecha está en pasado
  • @Pattern(regex="regexp", flag=): Comprueba si el que se corresponda con la expresión regular, habida cuenta de la bandera del partido (ver java.util.regex.Pattern para más información)
  • @Patterns( {@Pattern(...)} ): Al igual que @Pattern, pero para múltiples expresiones regulares

Se pueden crear validadores propios de una manera sencilla. Consulte la documentación Validadores de Hibernate para ver todas las características de este marco.

Otra característica útil que nos gustaría añadir a nuestras entidades es el representado por las anotaciones @PrePersist y @PreUpdate. Si un método es anotado con una de estas anotaciones, será invocado antes de la persistencia de la instancia en la base de datos y antes de su actualización. Aquí está un ejemplo de código añadido para una clase de entidad de la sección anterior:

/**
* This method initializes the values before
* the class is persisted
*/
@PrePersist
public void prePersist() {
  setCreatedOn(new Date());
  setLastUpdatedOn(new Date());
}
/**
* This method initializes the values before
* the class is updated
*/
@PreUpdate
public void preUpdate() {
  setLastUpdatedOn(new Date());
}

Roles de seguridad

 A continuación mostramos un ejemplo para crear un espacio destinado a los administradores de un sistema y para los usuarios de ejecución.

En primer lugar creamos una autenticación básica y añadimos al web.xml:

<security-constraint>
          <web-resource-collection>
               <web-resource-name>Protected Site</web-resource-name>
               <url-pattern>/admin/*</url-pattern>
               <http-method>DELETE</http-method>
               <http-method>GET</http-method>
               <http-method>POST</http-method>
               <http-method>PUT</http-method>
          </web-resource-collection>
          <auth-constraint>
               <!-- Roles that have access -->
               <role-name>admin</role-name>
               <role-name>user</role-name>
          </auth-constraint>
     </security-constraint>
     <!-- BASIC authentication -->
     <login-config>
          <auth-method>BASIC</auth-method>
          <realm-name>Basic Authentication</realm-name>
     </login-config>
     <!-- Define security roles -->
     <security-role>
          <description>admin</description>
          <role-name>admin</role-name>
     </security-role>
     <security-role>
          <description>user</description>
          <role-name>user</role-name>
     </security-role>

y hay que indicarle al servidor los roles definidos, por ejemplo usando Tomcat:

<tomcat-users>
<role rolename="user"/>
<role rolename="admin"/>
<user name="user" password="123" roles="user" />
<user name="admin" password="456" roles="admin" />
</tomcat-users>

y en la página se modifica para introducir el rol a la representación del componente, como por ejemplo:

<h:form rendered="#{rich:isUserInRole('admin')}" >
<rich:editor value="#{editor.pageText}" rendered="#{rich:isUserInRole('admin')}"/>
<h:commandButton value="Save" />
</h:form>

<h:outputText value="#{editor.pageText}" rendered="#{rich:isUserInRole('user')}" />

Ahora es posible identificarse en la aplicación como administrador para ver el editor, mientras que si inicia la sesión como un usuario se ve tan sólo un texto, sin opción de edición.

Uso de mensajes RichFaces y componentes de mensajes en lugar de las estándar

A continuación un ejemplo de mensajes de Richfaces:

<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>

Internacionalización

Los paquetes de idiomas se crean como ficheros del tipo *.propierties y consisten en un fichero que guarda las relaciones ente elementos y su valor. Una clave para un elemento debe ser la misma para todos los paquetes. Los paquetes deben ser cargados dentro del elemento <application> como sigue:

<application>
   <locale-config>
   <default-locale>en</default-locale>
      <supported-locale>en</supported-locale>
      <supported-locale>de</supported-locale>
   </locale-config>
   <message-bundle>demo.message</message-bundle>
</application>

Será necesario definir un método para cambiar de idioma, como el siguiente:

package demo;

import java.util.Locale;
import javax.faces.context.FacesContext;
public class ChangeLocale {

 public String germanAction() {
   FacesContext context = FacesContext.getCurrentInstance();
   context.getViewRoot().setLocale(Locale.GERMAN);
   return null;
 }

 public String englishAction() {
   FacesContext context = FacesContext.getCurrentInstance();
   context.getViewRoot().setLocale(Locale.ENGLISH);
   return null;
 }
}

y finalmente indicarlo en la página de la siguiente manera:

<a4j:loadBundle var="msg" basename="demo.message"/>
<h:outputText id="messageBundle" value="#{msg.greeting}"/>
    <a4j:commandLink value="De" action="#{changeLocale.germanAction}" reRender="messageBundle" />
    <a4j:commandLink value="Eng" action="#{changeLocale.englishAction}" reRender="messageBundle"

Tiempos de carga

Para reducir el esfuerzo de comprimir se puede introducir la siguiente configuración:

<context-param>
        <param-name>org.AJAX4jsf.COMPRESS_SCRIPT</param-name>
        <param-value>true</param-value>
</context-param>

Optimización en caché

Para optimizar los componentes en caché se puede aplicar la siguiente configuración:

<filter>
  <display-name>RichFaces Filter</display-name>
  <filter-name>richfaces</filter-name>
  <filter-class>org.AJAX4jsf.Filter</filter-class>
  <init-param>
      <param-name>enable-cache</param-name>
      <param-value>true</param-value>
  </init-param>
</filter>

Uso de conversores

El control de la localización (l10n) con RichFaces no tiene nada adicional al estándar JSF, controles de entrada y salida, sean AJAX o no, pueden utilizar los convertidores que proporciona la implementación para fechas y moneda.

<a4j:form>
<h:outputText value="#{beanIngresos.cantidad}">
       <f:convertNumber type="currency" currencySymbol="$" />
</h:outputText>
</a4j:form>

Soporte a Facelets

RichFaces da soporte a Facelets sin ningún problema. Con el fin de agregar a su proyecto el uso de Facelets, solamente es necesario definir el manejador de vista de facelets ( FaceletViewHandler) en el archivo faces-confg.xml como con la configuración estándar de Facelets. Sólo tiene que configurar el parámetro de contexto org.ajax4jsf.VIEW_HANDLERS y el filtro de RichFaces lo manejará adecuadamente. Este es el código que tienes que insertar en el archivo web.xml:

<context-param>
<param-name>org.AJAX4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>

Como se puede ver, acabamos de establecer el parámetro de contexto org.ajax4jsf.VIEW_HANDLERS para decirle a RichFaces que utilice el controlador de vista Facelet

Manejo de excepciones

RichFaces permite redefinir los controladores estándar responsables de la tramitación de las diferentes situaciones excepcionales. Y ayuda a definir JavaScript propio, que se ejecuta cuando se producen estas situaciones. Agregue el código siguiente para web.xml:

<context-param> 
  <param-name> org.AJAX4jsf.handleViewExpiredOnClient </ param-name>
  <param-value> true </ param-value>
</ context-param>

Manejando peticiones de error

Para ejecutar su propio código en el cliente en caso de un error durante la petición AJAX, es necesario redefinir el método estándar "A4J.AJAX.onError":

A4J.AJAX.onError = function (req, estado, mensaje) ( 
(window.alert "onError personal controlador" + mensaje);
)

La función se define de esta manera y acepta como parámetros:

  • req - una cadena de parámetros de una petición que llama a un error
  • estado - el número de un error devuelto por el servidor
  • mensaje - un mensaje por defecto para el error dado

Por lo tanto, es posible crear su propio controlador que se llama en los tiempos de espera, los errores de servidor interno,etc ..

Apariencia

En CSS estándar, no se puede definir un valor concreto (por ejemplo, un color o un tamaño de fuente) para "reutilizarlo" en más de un componente. Es necesario copiarlo y pegarlo donde sea necesario. Por lo tanto, si necesita cambiarlos, hay que buscar el valor y reemplazarlo manualmente cada vez que sea necesario. Como puede imaginar, este es un proceso propenso a errores que pueden acarrear muchos problemas e inconsistencias de diseño.

Además, si necesita una interfaz que soporta varios conjuntos de color y se deben ajustar sobre la marcha, necesitas trabajar con varios archivos CSS que tienen las mismas declaraciones pero diferentes colores, además de mantener otras actualizaciones .

La característica skinnability de RichFaces entra aquí para ayudarnos, no es un reemplazo de CSS, pero se integra perfectamente añadiendo más capacidades. La apariencia en RichFaces está diseñada para usarse de forma mixta con:

  • Los parámetros del skin que se definen en el framework de RichFaces.
  • Hojas de estilo predefinidas para los componentes.
  • Clases de estilo de usuario. El esquema de color del componente puede ser aplicado a sus elementos utilizando cualquiera de las tres clases de estilos:
    • Una clase de estilo por defecto se inserta en el framework. Contiene los parámetros de estilo vinculado a algunas constantes de un skin. Se define para cada componente y especifica un nivel de representación predeterminado. Así, una interfaz de aplicación podría ser modificada por el cambio de los valores de los parámetros del skin.
    • Una clase de estilo de la extensión del skin. Este nombre de clase se define para cada elemento componente y se inserta en el framework permite definir una clase con el mismo nombre en sus archivos CSS. Por lo tanto, la aparición de todos los componentes que utilizan esta clase es extendida.
    • Clase de estilo de usuario. Es posible utilizar uno de los parámetros styleClass de los elementos componentes y definir su propia clase en la misma. Como resultado, la aparición de un componente particular, se cambia de acuerdo a un parámetro de estilo CSS que se especifica en la clase.

En resumen, todos los componentes RichFaces dan soporte a la skinnability y significa que sólo cambiando el skin, cambiamos la apariencia de todos los componentes. Eso es muy bueno para dar a nuestra aplicación un aspecto coherente y no repetir siempre los mismos valores de CSS para cada componente.

Personalizar el skin

Un archivo de skin contiene los ajustes básicos (tales como fuentes, colores, etc) que usaremos para todos los componentes, simplemente cambiando los ajustes, podemos personalizar el aspecto básico para el marco de RichFaces. Como debe saber, RichFaces viene con algunos skins integrados (y otros plug 'n' skins adicionales), podemos empezar con los skins integrados para crear un skin personalizado. Los Skins integrados son los siguientes:

  • Plain
  • emeraldTown
  • blueSky
  • wine
  • japanCherry
  • ruby
  • classic
  • deepMarine

Recuerde que el skin utilizado por la aplicación se puede establecer como parámetro de contexto en el archivo web.xml:

<context-param>
    <param-name>org.richfaces.SKIN</param-name>
    <param-value>skinndeseado</param-value>
</context-param>

Usando skins con componentes non-skinnable

La característica skinnability sólo funciona para los componentes de RichFaces, así, los mismos problemas para los que esta característica se ha creado se encuentran el uso de componentes de otro marco de trabajo (que también utiliza los estándares JSF).

Con el fin de poder utilizar los parámetros del skin también para los componentes de no-RichFaces, el marco declara un objeto llamado richSkin que permite el acceso a los valores del skin. Vamos a ver un ejemplo. Por lo tanto, si tenemos un componente div (s:div) y aún desea utilizar el color del borde definido por el skin, podemos utilizar este código:

<s:div
style="border: 10px solid #{richSkin.panelBorderColor}">
<h:outputText value="Example text" />
</s:div>

Controles estándar de personalización

Para los controles estándar XHTML, se tiene la opción de personalizar el estilo de la forma en la que lo hace RichFaces. De hecho, unifica la apariencia de la aplicación al desarrollar los elementos estándar HTML de la misma manera que hace con los otros componentes de la biblioteca. Hay dos niveles de personalización:

  • Estándar: Para personalizar sólo las propiedades básicas (se aplica a IE 6, IE 7 en el modo de BackCompat y Safari)
  • Extendida: Para personalizar más las propiedades con más estilos (que se aplica a MozillaFirefox y Internet Explorer 7 en modo conforme a las normas)

Con el fin de activar los controles estándar de personalización, basta con añadir un nuevo context-param dentro del archivo web.xml, como este:

<context-param>
   <param-name>org.richfaces.CONTROL_SKINNING</param-name>
   <param-value>enable</param-value>
</context-param>

Ejemplos

Página JSP

Esta página de ejemplo, permitirá introducir texto en la etiqueta h:inputText, enviar los datos al servidor, y visualizar la respuesta del servidor como valor de la etiqueta h:outputText sin recargar la página completa. A continuación se muestra el código correspondiente a la página JSP (echo.jsp):

<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
    <%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
    <html>
      <head>
        <title>repeater </title>
      </head>
      <body>
        <f:view>
          <h:form>
              <rich:panel header="Simple Echo">
                <h:inputText size="50" value="#{bean.text}" >
                  <a4j:support event="onkeyup" reRender="rep"/>
                </h:inputText>
                <h:outputText value="#{bean.text}" id="rep"/>
              </rich:panel>
          </h:form>
        </f:view>
      </body>
    </html>

Sólo dos etiquetas se distinguen en esta página JSF. Son rich:panel y a4j:support.

La etiqueta rich:panel permite colocar los elementos de la página en un panel rectangular al que se le puede modificar su estilo. La etiqueta a4j:support con sus correspondientes atributos añade un soporte AJAX a las etiquetas padres h:inputText. Este soporte está se activa mediante una acción JavaScript "onkeyup", de manera que cada vez que se dispare este evento la aplicación enviará una petición al servidor. Esto significa que el campo de texto al que apunta el atributo del managed bean contendrá el valor actualizado del campo de entrada.

El valor del atributo "reRender" de la etiqueta a4j:support define las partes de la página que serán actualizadas. En este caso, sólo se actualizará la etiqueta h:outputText, ya que su ID coincide con el valor del atributo "reRender". Así, para actualizar varios elementos de la página, sólo habría que incluir los identificadores correspondientes dentro de la lista de valores del atributo "reRender".

Managed Bean

Al igual que el ejemplo debe tener una página JSP, deberá disponer de un Managed Bean. El Managed Bean para este ejemplo corresponde con el siguiente código:

package demo;       
        public class Bean {
            private String text;   
                public Bean() {
            }
                public String getText() {
                    return text;
            }
                public void setText(String text) {   
                this.text = text;
            }
        }

Este Managed Bean contiene el atributo que da soporte al texto introducido en la página JSP.

faces-config.xml

Al tener definida una aplicación JSF, se tendrá el fichero de configuración faces-config.xml. Es necesario registrar el managed bean dentro de este fichero:

<?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>bean</managed-bean-name>
        <managed-bean-class>demo.Bean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
          <property-name>text</property-name>
          <value/>
        </managed-property>
      </managed-bean>
    </faces-config>

Habría que destacar que no es necesario configurar nada relacionado con RichFaces dentro de este fichero de configuración.

Web.xml

Por último, sería necesario añadir al proyecto las librerías .jar (véase el apartado modo de empleo) y modificar el fichero de configuración web.xml:

<?xml version="1.0"?>
    <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>a4jEchoText</display-name>
    <context-param>
        <param-name>org.richfaces.SKIN</param-name>
        <param-value>blueSky</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
    </context-param>
    <filter>
        <display-name>RichFaces Filter</display-name>
        <filter-name>richfaces</filter-name>
        <filter-class>org.ajax4jsf.Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>richfaces</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <listener>
        <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
    </listener>   
    <!-- 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>*.jsf</url-pattern>
    </servlet-mapping>
    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>
    </web-app>

Contenidos relacionados

Recursos