2012-08-23 38 views
10

Corriendo en JSF 2.0.9, Weblogic 10.3.4. Ahora estamos ejecutando JSF en nuestro entorno de producción, pero hemos tenido algunos problemas con la replicación de sesión y la conmutación por error. Estamos utilizando ViewScope para nuestros beans y me he asegurado de que sean serializables/transitorios y de que las variables transitorias sean efectivamente apátridas. Sin embargo, la conmutación fallida de la sesión no funciona. He hecho pruebas exhaustivas y gestionado para que funcione mediante el establecimiento de los siguientes parametros en web.xmlSesión de JSF Falló y ahorro de estado parcial

<context-param> 
     <param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
     <param-value>client</param-value> 
    </context-param> 


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

Si fijo STATE_SAVING_METHOD a server me sale una excepción viewexpired de conmutación por error. Si fijo a client con PARTIAL_STATE_SAVING a true me sale el siguiente error:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 
    at java.util.ArrayList.RangeCheck(ArrayList.java:547) 
    at java.util.ArrayList.get(ArrayList.java:322) 
    at javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:165) 
    at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1433) 
    at com.sun.faces.application.view.StateManagementStrategyImpl$1.visit(StateManagementStrategyImpl.java:265) 
    at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1507) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1521) 
    at com.sun.faces.component.visit.VisitUtils.doFullNonIteratingVisit(VisitUtils.java:75) 
    at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:282) 
    at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:181) 
    at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123) 
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:448) 
    at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:148) 
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:187) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:111) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:508) 
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) 
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) 
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:301) 
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:27) 
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57) 
    at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27) 
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57) 
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3730) 
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3696) 
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) 
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120) 
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2273) 
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179) 
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1490) 
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256) 
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:221) 

Así que mis preguntas son las siguientes:

  • Es STATE_SAVING_METHOD - client & PARTIAL_STATE_SAVING - false la única forma de que vaya a obtener failover para trabajar?
  • ¿Cuál es el costo de la combinación cliente/falso. ¿Es esta memoria/CPU extensa?
  • ¿Es esto un error y si es así se resuelve en 2.1 o 2.2?

Gracias de antemano.

Respuesta

12

Finalmente conseguí que funcionara pero no sin algunos bits y bobs extra. En primer lugar he añadido lo siguiente al web.xml (sí agresivo está mal escrito):

<context-param> 
     <param-name>com.sun.faces.enableAgressiveSessionDirtying</param-name> 
     <param-value>true</param-value> 
    </context-param> 

El ahorro cliente es ahora el servidor y el ahorro de estado parcial es falsa todavía (verdadero simplemente no funciona)

En segundo lugar después de implementar un HttpSessionAttributeListener descubrí que el com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap que contiene el estado en la sesión solo se agregó una vez y nunca se quitó/agregó/reemplazó nuevamente. Por lo tanto, aunque se estaba actualizando en la sesión local, estos cambios nunca se replicaron en un segundo jvm. Los documentos de Weblogic indican que debe llamarse a setAttribute en los atributos de la sesión para que la replicación funcione. Para solucionar este creé un oyente fase del siguiente modo:

public class ViewPhaseListener implements PhaseListener { 

    public void afterPhase(PhaseEvent phaseEvent) 
    { 

    } 

    public void beforePhase(PhaseEvent phaseEvent) 
    { 
     HttpServletRequest request = ((HttpServletRequest) phaseEvent.getFacesContext().getExternalContext().getRequest()); 
     HttpSession session = request.getSession(); 

     session.setAttribute("com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap", session.getAttribute("com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap")); 

    } 

    public PhaseId getPhaseId() 
    { 
     return PhaseId.RENDER_RESPONSE; 
      //To change body of implemented methods use File | Settings | File Templates. 
    } 
} 

Esto simplemente reemplaza el atributo después de cada petición y asegura que se replica.Como un punto adicional estoy limitando los datos almacenados en las vistas con lo siguiente:

<context-param> 
     <param-name>com.sun.faces.numberOfViewsInSession</param-name> 
     <param-value>3</param-value> 
    </context-param> 

    <context-param> 
     <param-name>com.sun.faces.numberOfLogicalViews</param-name> 
     <param-value>1</param-value> 
    </context-param> 

Espero que esto ayude a cualquier persona con los mismos problemas.

0

La replicación de la sesión debe ser manejada por el equilibrador de carga, ya que la aplicación JSF solo conoce el contexto en el nodo en el que se implementa. Como tal, no debería importar si configuras el STATE_SAVING_METHOD al cliente o servidor.

Me parece que tiene una configuración incorrecta del equilibrador de carga. Si está utilizando Apache HTTP Server como su proxy consulte el siguiente enlace para obtener más información sobre la sesión de pegajosidad:

http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html

recomendaría el establecimiento ProxySet stickysession = ROUTEID y ver si se soluciona el problema.

+0

Tenemos IIS. La replicación de la sesión es manejada por weblogic y no por el equilibrador de carga. Sticky Sessions está activado, pero este no es el problema. El problema es la falla de la sesión para conmutar correctamente a un nuevo jvm. – andyfinch

+0

Si ha configurado una sesión fija en el servidor weblogic, el servidor weblogic creará una cookie con la información de sesión del usuario solo en ese nodo. Supongo que esta cookie no se transmite al segundo nodo cuando se produce una conmutación por error, ya que la instancia weblogic solo es consciente de sí misma. Es por eso que dije que debería probar y activar las sesiones adhesivas en Load Balancer porque el equilibrador de carga puede pasar la cookie al segundo nodo. –

+0

Gracias, pero creo que no estaba claro en mi pregunta inicial. La replicación de la sesión está ocurriendo pero no correctamente con las sesiones de JSF. Solo parte de nuestra aplicación usa JSF en las sesiones mo y non jsf se replican bien. – andyfinch

Cuestiones relacionadas