Listener del ciclo de vida de JSF, en JSF2 y con el soporte de FacesTrace (Primefaces)

1
21706

Listener del ciclo de vida de JSF, en JSF2 y con el soporte de FacesTrace (Primefaces).

0. Índice de contenidos.


1. Introducción

En este tutorial vamos a analizar las opciones que tenemos disponibles en JSF2 para engancharnos al ciclo de vida de una petición JSF y «seguirle los pasos».

Cualquiera que haya trabajado con JSF habrá tenido algún problema que otro a causa de su ciclo de vida y, sobre todo, de nuestro desconocimiento inicial. Sobre todo problemas de invocaciones a métodos get
que pueden derivar en problemas de rendimiento, ¿cuántas veces se invocan a los setters y los getters? o quizás problemas con los eventos de cambios de valor y la rerenderización de la página.

Para no perdernos entre las distintas fases del ciclo de vida sin entender qué se hace en cada una de ellas es imprescindible trabajar, al principio, con un listener que, al menos, nos de soporte a la
trazabilidad de su ejecución.

En este tutorial vamos a ver dos opciones:

  • hacer uso de un listener propio,
  • configurar un componente de Primefaces,
    aunque en realidad se puede configurar fuera del entorno de la librería, que nos da un nivel de información mayor.


2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 17′ (2.93 GHz Intel Core 2 Duo, 4GB DDR3 SDRAM).
  • Sistema Operativo: Mac OS X Snow Leopard 10.6.1
  • JSF2 (Mojarra 2.0.3)
  • Primefaces 2.2


3. Listener del ciclo de vida de JSF.

La primera aproximación es sencilla y se basa en crear un listener propio y configurarlo.

La clase debe implementar la interfaz PhaseListener, indicar en qué fase del ciclo de vida de JSF queremos que se ejecute y programar qué hacer antes y despúes de la ejecución de una fase, en nuestro
caso pintar una traza:

package com.autentia.training.jsf.listener;

import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LifeCycleListener implements PhaseListener {
	
	private static final long serialVersionUID = -2504278325379445246L;

	private static final Log log = LogFactory.getLog(LifeCycleListener.class);
	
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }

    public void beforePhase(PhaseEvent event) {
    	if (log.isTraceEnabled()){
    		log.trace("BeforePhase: " + event.getPhaseId());
    	}
    }

    public void afterPhase(PhaseEvent event) {
    	if (log.isTraceEnabled()){
    		log.trace("AfterPhase: " + event.getPhaseId());
    	}
    }

}

Una vez tenemos la clase, sólo tenemos que añadirla al fichero faces-config.xml como sigue:

...
	<lifecycle>
	    <phase-listener>com.autentia.training.jsf.listener.LifeCycleListener</phase-listener>
	</lifecycle>

</faces-config>

Con ello, por cada petición JSF tendremos una salida similar a la siguiente:

Nos podemos hacer a la idea de que la petición anterior ha pasado por todas las fases del ciclo de vida, con lo que se ha submitido el formulario:

  • 1: recomponiendo el árbol de componentes,
  • 2: asignando los valores de la request y convirtiendo a objeto los posibles valores que no son tipos básicos,
  • 3: validando los componentes que implementan la interfaz EditablevalueHolder,
  • 4: asignando los valores de los componentes al modelo,
  • 5: ejecutando los eventos de acción que enganchan con el gestor de navegación y
  • 6: renderizando el árbol de componentes con la respuesta al cliente, convirtiendo los objetos a tipo básico.

todo ello, sin ningún error, puesto que ha pasado por todas las fases.

En la siguiente traza podemos ver cómo se ha producido un error de validación puesto que ha saltado de la fase 3 a la 6, sin ejecutar ni la 4 ni la 5.

Lo interesante es, en realidad, que escribamos trazas en los métodos de nuestra lógica de control y lógica de negocio, de modo que tracemos la ejecución y tengamos información entre la entrada y salida de una fase.


4. FacesTrace: con el soporte de Primefaces.

FacesTrace en un proyecto incubado por la gente de Primefaces que se distribuye como un módulo individual, con lo cuál, susceptible de ser añadido a cualquier proyecto JSF.

Consiste en un componente visual que nos muestra las fases del ciclo de vida por las que ha pasado la petición y el tiempo consumido en cada una de ellas.
Además, nos muestra la información típica del componente de facelets <ui:debug /> sobre las variables y su ámbito y, en la parte inferior, todos los nodos del árbol de componentes JSF.


4.1. Configuración.

Lo primero que necesitamos es añadir la librería. Si tenemos el soporte de Maven basta con incluir la dependencia en el pom.xml del proyecto web:

		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>facestrace</artifactId>
			<version>1.1.0</version>
		</dependency>	

Con ello debería estar habilitado el soporte para el componente, puesto que el jar contiene su propio faces-config.xml y se autoconfigura.

Si el url-pattern del servlet de JSF, lo tenéis configurado con algo distinto al mapeo por defecto, necesitaréis asignar, además el mapeo por defecto:

	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
	</servlet-mapping>

La necesidad viene dada porque el componente hace uso de una serie de recursos (css y js) que mapea a través de un filtro y usa el sufijo por defecto en el enlace: traceResource.jsf.

No deja de ser un pequeño inconveniente y hay que tener en cuentra que este tipo de técnicas sólo las vamos a usar en la fase de desarrollo.


4.2. Uso.

Para mostrar el componente visual, basta con pasar como parámetro a cualquier petición ?trace=true. El componente se mostrará en la parte superior de la pantalla.

Aunque también se puede incluir el componente manualmente, por ejemplo, en la página de la plantilla de facelets (layout.xhtml) para que afecte a todas las vistas y se muestre siempre visible en la posición
que necesitemos (como hacíamos antes con el componente <ui:debug /> de facelets.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html   xmlns="http://www.w3.org/1999/xhtml"
		...
		xmlns:p="http://primefaces.prime.com.tr/ui"
		xmlns:ft="http://primefaces.prime.com.tr/facestrace">
		
    ...
    <ft:trace />
    ...

En la interfaz se mostrará un componente como el que se muestra en la imagen:



4.3. Configurar un Appender de Log4j.

El componente te permite, además, mostrar los logs trazados por log4j directamente en pantalla, configurando un Appender. Para ello basta con incluir unas líneas como siguen en la configuración (log4j.properties):


  log4j.rootLogger=INFO, stdout, facestrace
  ...
  log4j.appender.facestrace=org.primefaces.facestrace.logging.FacesTraceAppender

Con ello, el componente visual mostrará los logs con el nivel de traza que hayamos definido.




5. Referencias.


6. Conclusiones.

Acabamos de ver en otro tutorial
la posibilidad de cambiar el nivel de trazas en caliente con el soporte de Spring
, junto con el uso del appender de facestrace podemos obtener bastante control sobre la trazabilidad de nuestra aplicación.

Espero que os haya sido de utilidad, y recordad que en Autentia nos dedicamos a la consultoría, al soporte al desarrollo y a la formación. Si en tu proyecto
tienes alguna necesidad en este sentido siempre puedes ponerte en contacto con nosotros.

Un saludo.

Jose

jmsanchez@autentia.com

1 COMENTARIO

  1. Tengo un pequeño problema, quiero validar para aplicar un dependiendo de si recibo por parametro en mi taglib el metodo.

    la cosa es que queda algo asi
    c:set test=\\\»#{cc.attrs.metodo != null}\\\»>
    f:ajax />
    /c:set>

    pero al parecer las etiquetas c, que vienen de http://java.sun.com/jsp/jstl/core siempre se ejecutan primero que todo, por lo tanto el resultado me esta dando falso, no se si exista otra etiqueta que me ayude a validar esto. O que exista una manera de settear estos valores antes de ejecutar mi test, o mandar a ejecutar de nuevo esa fraccion del codigo, no entiendo como funciona el f:event 🙁
    soy principiante y malo en ingles.

    Gracias

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad