tipos sessionscoped applicationscoped jsf jsf-2 lifecycle view-scope postconstruct

jsf - sessionscoped - ViewScoped bean se está construyendo en cada solicitud... parte 99



jsf session (1)

Esta pregunta ya tiene una respuesta aquí:

ARGH ... Esto parece tener cien respuestas y no he encontrado ninguna que funcione para mí, así que supongo que la volveré a preguntar. Aquí está mi escenario:

Mi sitio tiene técnicamente una sola página cuyos contenidos se intercambian en lugar de tener varias páginas a las que navega. El punto de partida es este pedazo:

<?xml version="1.0" encoding="UTF-8"?> <f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head /> <h:body> <ui:include src="resourceInclude.xhtml" /> <ui:include src="main.xhtml" /> </h:body> </f:view>

El resourceInclude.xhtml incluye mi archivo css:

<?xml version="1.0" encoding="UTF-8"?> <ui:composition xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:outputStylesheet library="css" name="test.css" target="head" /> </ui:composition>

Y main.xhtml es la vista:

<?xml version="1.0" encoding="UTF-8"?> <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"> <h:panelGroup styleClass="test-container" layout="block"> <h:form id="main-form"> <h:panelGroup styleClass="test-header" layout="block"> <h:panelGroup styleClass="navigation" layout="block"> <ul> <li><h:commandLink action="#{viewSelector.setModeHome}"> <h:outputText value="Home" /> </h:commandLink></li> <li><h:commandLink action="#{viewSelector.setModeReports}"> <h:outputText value="ASAP Reports" /> </h:commandLink></li> <li><h:commandLink action="#{viewSelector.setModeSupport}"> <h:outputText value="Technical Support" /> </h:commandLink></li> <li><h:commandLink action="#{viewSelector.setModeHelp}"> <h:outputText value="Help" /> </h:commandLink></li> </ul> </h:panelGroup> </h:panelGroup> <h:panelGroup styleClass="test-content" layout="block"> <ui:include src="#{viewSelector.modeName}-view.xhtml" /> </h:panelGroup> <h:panelGroup styleClass="test-footer" layout="block"> <h:messages /> </h:panelGroup> </h:form> </h:panelGroup> </ui:composition>

Consiste en tres h:panelGroup s. El primero es un conjunto de cuatro enlaces de navegación generales, cada enlace cambia el valor viewSelector.modeName que se utiliza para incluir los contenidos en la segunda h:panelGroup así <ui:include src="#{viewSelector.modeName}-view.xhtml" /> . Lo he despojado de este ejemplo, así que cada vista es básicamente esta:

<?xml version="1.0" encoding="UTF-8"?> <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"> <h:panelGroup styleClass="test-home-view"> <p>home</p> </h:panelGroup> </ui:composition>

La tercera h:panelGroup es un pie de página para todos los mensajes para depurar qué está h:panelGroup .

De todos modos, cada vez que hago clic en uno de los enlaces de navegación, se llama al constructor del viewSelector bean. Así es como se ve mi bean viewSelector:

package org.mitre.asias.aires.controller; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import org.apache.log4j.Logger; @ManagedBean( name="viewSelector" ) @ViewScoped public class ViewSelector { protected static Logger log = Logger.getLogger( ViewSelector.class ); private Mode mode = Mode.HOME; public static final String PORTLET_NAME = "Test"; public static enum Mode { HOME(1, "home"), REPORTS(2, "reports"), SUPPORT(3, "support"), HELP(4, "help"); private int value; private String name; private Mode( int value, String name ) { this.value = value; this.name = name; } public int getValue() { return value; } public String getName() { return name; } } public ViewSelector() { log.trace( "constructing new ViewSelector" ); } public Mode getMode() { log.trace( "getting mode" ); return mode; } public String getModeName() { log.debug( "in getmodename" ); return getMode().getName(); } public String getPortletName() { return PORTLET_NAME; } public boolean isModeReports() { return getMode() == Mode.REPORTS; } public void setMode( Mode mode ) { this.mode = mode; } public void setModeHelp() { setMode( Mode.HELP ); } public void setModeHome() { setMode( mode = Mode.HOME ); } public void setModeReports() { setMode( mode = Mode.REPORTS ); } public void setModeSupport() { setMode( mode = Mode.SUPPORT ); } }

Sé que debo estar haciendo algo de la manera equivocada, o me falta algo central en cuanto a cómo funciona JSF. Cualquier entrada?


El EL en <ui:include src> está causando eso.

Si deshabilitar el ahorro de estado parcial en web.xml según el problema 1492 no es una opción,

<context-param> <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> <param-value>true</param-value> </context-param>

entonces necesitas reemplazar

<ui:include src="#{viewSelector.modeName}-view.xhtml" />

por algo así como

<h:panelGroup rendered="#{viewSelector.mode == ''HOME''}"> <ui:include src="home-view.xhtml" /> </h:panelGroup> <h:panelGroup rendered="#{viewSelector.mode == ''REPORTS''}"> <ui:include src="reports-view.xhtml" /> </h:panelGroup> <h:panelGroup rendered="#{viewSelector.mode == ''SUPPORT''}"> <ui:include src="support-view.xhtml" /> </h:panelGroup> <h:panelGroup rendered="#{viewSelector.mode == ''HELP''}"> <ui:include src="help-view.xhtml" /> </h:panelGroup>

Una pregunta similar se ha hecho al menos una vez antes :)