
JSF Trinidad: como usar distintas sesiones en distintas pestañas.
Hemos desarrollado una aplicación en JSF, usando Trinidad como implementación, que hace uso de bean de sesión para mantener el estado del usuario logado en la aplicación así como sus parámetros de configuración. Si abrimos una nueva pestaña en el mismo navegador web o otra instancia del mismo navegador y accedemos a la aplicación estaremos accediendo en la misma sesión.
¿Cual es la problemática?
Supongamos que la aplicación usa una serie de datos por año, de forma que el año a través del cual esta navegando la persona usuaria se guarda en un bean de sesión. Si este usuario quisiera navegar a través de otro año a la vez la única opción sería acceder a la aplicación usando otro navegador distintos.
¿Cual es la solución?
La solución esta relacionada con los distintos scopes disponibles en Apache JSF Trinidad. Podemos usar cualquiera de los tres scopes por defecto que tiene JSF:
– applicationScope
– sessionScope
-requestScope
Pero ninguno de ellos resuelve nuestro problema, puesto que queremos un scope que mantenga la información entre páginas, pero que sea diferente en cada una de las pestañas del navegador que abramos (siendo la misma sesión para ambas pestañas).
Ante este problema podemos optar por dos soluciones posibles:
- Cambiar el scope del bean que almacene los datos del año a request y modificar todas las peticiones que se hagan de este bean para añadir como un parámetro de entrada el año en cuestión al que queremos acceder.
- Usar un scope presente en Apache JSF Trinidad que se denomina pageFlow.
La primera solución es altamente intrusiva por lo que no recomiendo su uso, pasaremos a analizar la segunda solución.
Análisis de la solución
La primera aproximación a la solución sería sustituir en el fichero de configuración del bean el scope correspondiente a pageFlow. Pero en la documentación oficial nos indican que no es posible insertar “page flow” como <managed-bean-scope>.
Supongamos que el bean que se almacena en la sesión es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 | package es.mergetag.pageFlow; public class ConfiguracionSesion { private Year year = null; public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } } |
y dentro de este objeto hay un objeto año que representa al año por el cual el usuario se encuentra navegando en este momento y por lo tanto también se almacena en la sesión junto con el objeto de configuración de la sesión.
1 2 3 4 5 | package es.mergetag.pageFlow; public class Year { //content of data year } |
Por lo tanto en algún punto de la aplicación podemos necesitar un archivo de configuración que haga uso de este bean:
<managed-bean>
<managed-bean-name>configuracionBean</managed-bean-name>
<managed-bean-class>es.mergetag.pageFlow.ConfiguracionSesion</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>year</property-name>
<value>#{year}</value>
</managed-property>
</managed-bean>
De forma que al tener el bean configuracionBean guardado en la sesión, el año también se encuentra almacenado en la sesión. Si quisieramos cambiar el ámbito del bean podíamos tratar de modificarlo usando: <managed-bean-scope>pageFlow</managed-bean-scope>. Sin embargo esta es una limitación de este scope según se indica en la documentación oficial de Apache JSF Trinidad.
Desarrollo de la solución
Tenemos que lograr que cuando desde cualquier otra parte de la aplicación se acceda a la variable año dentro del bean de Configuración que tienen ambito de sesión, extraiga el año del pageFlow. Una solución completamente transparente sería modificar los métodos get y set dentro del bean de configuración:
1 2 3 4 5 6 7 8 9 10 11 | public void setYear(Year year){ this.setYear(year); } public Year getYear(){ return this.year; } |
pasando a ser
1 2 3 4 5 6 7 8 9 10 11 | public void setYear(Year year){ RequestContext requestContext = RequestContext.getCurrentInstance(); requestContext.getPageFlowScope().put("year", year); } public Year getYear(){ RequestContext requestContext = RequestContext.getCurrentInstance(); this.year = requestContext.getPageFlowScope().get("year"); } |
Conclusión.
De esta forma, solo hemos tocado el JavaBean que queríamos llevar al ámbito pageFlow manteniendo el resto de la aplicación intacta y consiguiendo de este modo que un usuario pueda manejar distintas versiones del mismo bean en distintas pestañas de un mismo navegador.
Tener en cuenta que se indica en la documentación oficial que pageFlow se encuentra en estado experimental.
————————————————————————————————————————————————
Enlaces de interés:
Web Apache JSF Trinidad: http://myfaces.apache.org/trinidad/
Documentación oficial acerca de pageFlow: http://myfaces.apache.org/trinidad/devguide/communicatingBetweenPages.html