JSF会话故障转移和部分状态保存

在JSF 2.0.9上运行,Weblogic 10.3.4。 我们现在正在生产环境中运行JSF,但遇到了会话复制和故障转移的一些问题。 我们正在为我们的bean使用viewcope,并确保它们是Serializable / transient,并且瞬态变量实际上是无状态的。 但是会话故障转移不起作用。 我已经做了大量的测试,并设法通过在web.xml中设置以下参数来使其工作

 javax.faces.STATE_SAVING_METHOD client   javax.faces.PARTIAL_STATE_SAVING false  

如果我将STATE_SAVING_METHOD设置为server我会在故障转移时获得一个viewexpiredexception。 如果我将PARTIAL_STATE_SAVING设置为clienttruePARTIAL_STATE_SAVING出现以下错误:

 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) 

所以我的问题是:

  • STATE_SAVING_METHODclientPARTIAL_STATE_SAVINGfalse是我要让故障转移工作的唯一方法吗?
  • 客户/假组合的成本是多少。 这个内存/ cpu是否广泛?
  • 这是一个错误,如果是这样,它在2.1或2.2中解决了吗?

提前致谢。

我终于得到了这个工作,但不是没有一些额外的位和bobs。 首先,我将以下内容添加到web.xml中(肯定是拼写错误的拼写错误):

   com.sun.faces.enableAgressiveSessionDirtying true  

客户端保存现在是服务器,部分状态保存仍然是假的(真的根本不起作用)

其次,在实现HttpSessionAttributeListener之后,我发现在会话中保存状态的com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap只添加了一次,并且再也没有删除/添加/替换。 因此,虽然它在本地会话中进行了更新,但这些更改从未复制到第二个jvm。 Weblogic文档声明必须在会话属性上调用setAttribute才能使复制正常工作。 为解决这个问题,我创建了一个阶段监听器,如下所示

 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. } } 

这只是在每次请求后替换属性并确保它复制。 另外一点,我使用以下内容限制存储在视图中的数据:

  com.sun.faces.numberOfViewsInSession 3   com.sun.faces.numberOfLogicalViews 1  

希望这可以帮助任何有同样问题的人。

会话复制应由负载均衡器处理,因为JSF应用程序只知道部署到的节点上的上下文。 因此,将STATE_SAVING_METHOD设置为客户端服务器无关紧要。

听起来像你有一个不正确的负载均衡器配置。 如果您使用Apache HTTP Server作为代理,请参阅以下链接以获取有关会话粘性的更多信息:

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

我建议设置ProxySet stickysession = ROUTEID ,看看是否能解决问题。