Details
Description
When programmatically ending a session by calling HttpSession.invalidate(), we need to support the same behaviour as stock JSF if possible. Currently, calling invalidate() on the session is resulting in the following NullPointerException (very similar to the issue experienced by the customer in the related case):
java.lang.NullPointerException
at org.icefaces.event.WindowAndViewIDSetup$1.encode(WindowAndViewIDSetup.java:66)
at org.icefaces.event.UIOutputWriter.encodeBegin(UIOutputWriter.java:32)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1641)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:164)
at org.icefaces.render.RendererWrapper.encodeChildren(RendererWrapper.java:54)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:849)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1643)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1646)
at org.icefaces.context.DOMPartialViewContext.processPartial(DOMPartialViewContext.java:151)
at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:968)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1643)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:378)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:127)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:117)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:135)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:309)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
at java.lang.Thread.run(Thread.java:637)
java.lang.NullPointerException
at org.icefaces.event.WindowAndViewIDSetup$1.encode(WindowAndViewIDSetup.java:66)
at org.icefaces.event.UIOutputWriter.encodeBegin(UIOutputWriter.java:32)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1641)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:164)
at org.icefaces.render.RendererWrapper.encodeChildren(RendererWrapper.java:54)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:849)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1643)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1646)
at org.icefaces.context.DOMPartialViewContext.processPartial(DOMPartialViewContext.java:151)
at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:968)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1643)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:378)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:127)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:117)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:135)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:309)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
at java.lang.Thread.run(Thread.java:637)
In building and testing an application that invalidates the session through various means, there were some relevant observations:
Stock JSF
When invalidating the session programmatically with stock JSF (no ICEfaces or Ajax), processing continues and new sessions are created as required. For example, if we dump a portion of the stack from an HttpSessionListener.sessionCreated method, we can see that JSF will create new sessions for things that it needs to do.
[#|2010-08-16T16:54:44.312-0700|SEVERE|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=26;_ThreadName=Thread-1;|java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1230)
at org.icefaces.test.invalidate.SessionUtil.sessionCreated(SessionUtil.java:36)
at org.apache.catalina.session.StandardSession.tellNew(StandardSession.java:411)
at org.apache.catalina.session.StandardSession.setId(StandardSession.java:391)
at org.apache.catalina.session.ManagerBase.createSession(ManagerBase.java:889)
at org.apache.catalina.session.StandardManager.createSession(StandardManager.java:326)
at org.apache.catalina.connector.Request.doGetSession(Request.java:2804)
at org.apache.catalina.connector.Request.getSession(Request.java:2528)
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:919)
at com.sun.faces.context.SessionMap.getSession(SessionMap.java:225)
at com.sun.faces.context.SessionMap.put(SessionMap.java:122)
at com.sun.faces.context.SessionMap.put(SessionMap.java:57)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.getResponseEncoding(FaceletViewHandlingStrategy.java:951)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.createResponseWriter(FaceletViewHandlingStrategy.java:860)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:364)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:127)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:117)
Even invalidating the session in the post RenderReponse phase (via a PhaseListener) will cause JSF to create a new session to write the state into. Since the new session is not aligned with the clients session id, the next interaction with the page will throw a ViewExpiredException, which can be configured in the web.xml to redirect to a new page.