Session TimeOut en RichFaces, con el soporte de Jboss Seam.

3
17177

Session TimeOut en RichFaces, con el soporte de Jboss Seam.

0. índice de contenidos.


1. Introducción

Cuando te mueves entre tanta tecnología y, en el caso concreto del contenido de este tutorial, entre tanta librería de componentes JSF, siempre tiendes a buscar lo bueno de una en las demás y viceversa,
en ver cómo el resto intenta solucionar las carencias de las otras.
Por el tutorial Configuración de la desconexión de usuarios con ICEFaces,
de mi compi Juan, ya sabemos que con ICEfaces podemos configurar una ventana modal que informe al usuario de la pérdida de sesión con el servidor, de hecho viene configurada por defecto y hasta cierta
versión no era parametrizable.

Ahora que nos movemos entre los componentes visuales de la libería RichFaces,
nos encantaría tener una «feature» similar o, al menos, algún tipo de facilidades para implementarla.

En este tutorial vamos a ver como delegar el control de la pérdida de sesión del lado del cliente para informar de la misma de una manera visualmente atractiva, analizando antes el soporte al
manejo de excepciones del que disponemos haciendo uso del framework Jboss Seam.


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
  • Jboss Seam 2.2.0.GA.
  • RichFaces 3.3.3.CR1
  • Maven 2.2.1.
  • Eclipse 3.5: Ganymede, con IAM (plugin para Maven).
  • Apache Tomcat 6.0.20 con la jdk 1.5.


3. Gestión de excepciones en Jboss Seam.

Con Jboss Seam se puede llevar a cabo una gestión de excepciones de forma declarativa, de modo que frente a una excepción predefinida se dirija al usuario a una página concreta con un mensaje
personalizado.

La declaración de las excepciones se lleva a cabo en el fichero pages.xml, como el faces-navigation.xml que podemos tener con JSF en el que se declaran las reglas de navegación, y la mejora frente a otro tipo de manejo de excepciones (como la que podemos tener a nivel de web.xml) es que los
mensajes se pueden obtener internacionalizados y permite terminar con el ámbito conversacional de los componentes de Seam.

A continuación mostramos los ejemplos típicos que nos servirían para controlar la autenticación y autorización de los usuarios de nuestra aplicación.

    <exception class="org.jboss.seam.security.NotLoggedInException">
        <redirect view-id="/login.jspx">
            <message>#{messages['error.notLogged']}</message>
        </redirect>
    </exception>
    
    <exception class="org.jboss.seam.security.AuthorizationException">
        <end-conversation />
        <redirect view-id="/error.jspx">
            <message>#{messages['error.unauthorized']}</message>
        </redirect>
    </exception>

Para gestionar la pérdida de sesión, en la que JSF nos devuelve la típica excepción de ViewExpiredException podemos añadir la siguiente declaración:

    <exception class="javax.faces.application.ViewExpiredException">
        <redirect view-id="/error.jspx">
            <message>Unexpected error: javax.faces.application.ViewExpiredException</message>
        </redirect>
    </exception>

Como última declaración se suele incluir una captura genérica como sigue:

    <exception>
        <redirect view-id="/error.jspx">
            <message>Unexpected error: #{handledException.message}</message>
        </redirect>
    </exception>

Interesante y útil, si no fuese porque en la interfaz de usuario estamos haciendo uso extensivo de componentes con funcionalidades Ajax, y cuando se produce una petición en segundo plano
y hay una pérdida de sesión no se redirige la petición. ¿La solución?, a continuación.


4. Implementando la solución en RichFaces.

Nuestro problema es simple, cuando expira la sesión, los componentes Ajax dejan de funcionar pero no se informa al usuario debidamente, con lo que parece una pérdida de funcionalidad.
Para solucionarlo vamos a manejar el estado de la conexión en el cliente, de este modo, cuando se pierda mostraremos una ventana modal con una redirección a la página de login.

RichFaces dispone del siguiente parámetro de contexto en el que se define si el manejo de la caducidad de la vista será gestionado en el cliente o no.

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

Una vez configurado, vamos a crear una plantilla que podremos incluir en cualquiera de nuestros layouts con el siguiente código:

<ui:composition 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:s="http://jboss.com/products/seam/taglib"
                xmlns:rich="http://richfaces.org/rich"
				xmlns:a4j="http://richfaces.org/a4j">
				
    <!-- definición del comportamiento en javascript tras la perdida de sesión -->
	<a4j:region>
		<script language="javascript">
			// añadimos una función de callback que será invocada 
			// cuando se produzca el evento de sesión caducada
			A4J.AJAX.onExpired = function(loc, expiredMsg){
				// obtenemos el componente que implementa la ventana modal para mostrarlo
				$('sessionTimeOutWindow').component.show();
			}
		</script>
	</a4j:region>

	<!-- la ventana modal -->                                                         
	<rich:modalPanel id="sessionTimeOutWindow" styleClass="confirm" width="375" height="160"
                     resizeable="false">
        <f:facet name="header">
            <h:outputText value="#{messages['error.sessionTimeOut.header']}" />
        </f:facet>
        <h:panelGrid styleClass="confirmContent" rowclasses="wXXL, ">
            <h:panelGrid columns="2">
                <h:outputText styleClass="textMessage" value="#{messages['error.sessionTimeOut.text']}" />
            </h:panelGrid>
            <s:div styleClass="buttons">
                <input  id="confirmBackToLogin" type="button" value="#{messages['error.sessionTimeOut.button']}"
                        onclick="window.location='#{facesContext.externalContext.requestContextPath}/login.jsf';" />
            </s:div>
        </h:panelGrid>
	</rich:modalPanel>
	
</ui:composition>

El resultado será similar al siguiente:

Si el evento que se produce en el cliente, no implica una petición Ajax, entrarán en juego las reglas definidas en el pages.xml.


5. Referencias.


6. Conclusiones.

Es muy importante que el usuario tenga conciencia de lo que está ocurriendo en cada momento y si existe algún error mostrarle el mismo de la mejor forma posible, decorándolo,
puesto que la gestión de errores forma parte de la propia aplicación. Un error no controlado, mostrando la pila de la excepción al usuario da muy mala imagen, la pila,
mejor en el fichero de logs del servidor.

Intentamos implementar, con distinta tecnología, soluciones análogas con la experiencia que tenemos de otras librerías de componentes visuales JSF.

Un saludo.

Jose

jmsanchez@autentia.com

3 COMENTARIOS

  1. Saludos José Manuel,
    Habría posibilidad de Cerrar una conversación, y abrir la misma en un mismo método?
    Como cerrando una carga de datos para re-iniciar otra en el mismo jsp, con SEAM

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