Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: 1.8.2
-
Fix Version/s: 1.8.2a, 1.8.2-EE-GA_P02
-
Component/s: Framework
-
Labels:None
-
Environment:ICEFaces FileUpload + Spring Webflow
Description
Using FileUpload in a Spring application fails during the FileUpload itself with an error indicating the software can't restore the view, whatever the view is.
It turns out that ICEFaces state saving is not actually invoked in Spring applications. Looking at the code in Spring, Spring doesn't delegate state saving calls to the delegate instance unless the request is deemed not to be a Spring request, and this is established by checking if there is a RequestContext object ThreadLocal defined, and this is setup in the resume or start method of FlowExecutorImpl.
Here's a stack trace showing the execution path to the point where the RequestContext is established as a ThreadLocal. The entry point to the Spring Webflow applications is through the MainServlet and then goes back into the Spring framework via the SwfLifecycleExecutor.
at org.springframework.webflow.execution.RequestContextHolder.setRequestContext(RequestContextHolder.java:40)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:218)
at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:140)
at com.icesoft.faces.webapp.http.core.FlowExecutorUtil.launchExecution(FlowExecutorUtil.java:90)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.launchExecution(SwfLifecycleExecutor.java:134)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.apply(SwfLifecycleExecutor.java:57)
at com.icesoft.faces.context.View$2$1.respond(View.java:48)
at com.icesoft.faces.webapp.http.servlet.ServletRequestResponse.respondWith(ServletRequestResponse.java:201)
at com.icesoft.faces.context.View$2.serve(View.java:77)
at com.icesoft.faces.context.View.servePage(View.java:149)
at com.icesoft.faces.webapp.http.core.MultiViewServer.service(MultiViewServer.java:79)
at com.icesoft.faces.webapp.http.common.ServerProxy.service(ServerProxy.java:11)
at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet$4.service(MainSessionBoundServlet.java:149)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:60)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:148)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:359)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
For the sake of interest, views are rendered by the SpringFramework treating the JSF Views as a certain type of renderable.
at com.icesoft.faces.facelets.D2DFaceletViewHandler.renderResponse(D2DFaceletViewHandler.java:284)
at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:159)
at org.springframework.faces.webflow.FlowViewHandler.renderView(FlowViewHandler.java:92)
at org.springframework.faces.webflow.JsfView.render(JsfView.java:94)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:245)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:204)
at org.springframework.webflow.engine.Flow.resume(Flow.java:545)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:262)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:163)
at com.icesoft.faces.webapp.http.core.FlowExecutorUtil.resumeExecution(FlowExecutorUtil.java:86)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.resumeExecution(SwfLifecycleExecutor.java:129)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.apply(SwfLifecycleExecutor.java:55)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.renderCycle(ReceiveSendUpdates.java:132)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.service(ReceiveSendUpdates.java:74)
at com.icesoft.faces.webapp.http.core.RequestVerifier.service(RequestVerifier.java:31)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:60)
at com.icesoft.faces.webapp.http.servlet.SessionVerifier.service(SessionVerifier.java:26)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:148)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
When a FileUpload request is processed a lifecycle event is generated by the upload process in order to update the Upload progress page. Since the PathDispatcher matches the path of the FileUploadServlet execution goes down that route and doesn't have the Spring path portions in it, therefore a Spring webflow isn't resumed. Since the Spring Webflow isn't resumed, the StateSaving code executed when running the lifecycle is delegated to our StateSaving implementation which is looking for a viewRoot in the State Maps in the session.
at com.icesoft.faces.webapp.http.core.UploadServer$2.servlet(UploadServer.java:127)
at com.icesoft.faces.webapp.http.servlet.ServletRequestResponse.detectEnvironment(ServletRequestResponse.java:262)
at com.icesoft.faces.webapp.http.core.UploadServer.service(UploadServer.java:69)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:60)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:148)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:359)
Since we haven't been involved in saving the state at any time in the past, there isn't any copy of the ViewRoot in the Session when this attempt is made, hence the error.
It turns out that ICEFaces state saving is not actually invoked in Spring applications. Looking at the code in Spring, Spring doesn't delegate state saving calls to the delegate instance unless the request is deemed not to be a Spring request, and this is established by checking if there is a RequestContext object ThreadLocal defined, and this is setup in the resume or start method of FlowExecutorImpl.
Here's a stack trace showing the execution path to the point where the RequestContext is established as a ThreadLocal. The entry point to the Spring Webflow applications is through the MainServlet and then goes back into the Spring framework via the SwfLifecycleExecutor.
at org.springframework.webflow.execution.RequestContextHolder.setRequestContext(RequestContextHolder.java:40)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:218)
at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:140)
at com.icesoft.faces.webapp.http.core.FlowExecutorUtil.launchExecution(FlowExecutorUtil.java:90)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.launchExecution(SwfLifecycleExecutor.java:134)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.apply(SwfLifecycleExecutor.java:57)
at com.icesoft.faces.context.View$2$1.respond(View.java:48)
at com.icesoft.faces.webapp.http.servlet.ServletRequestResponse.respondWith(ServletRequestResponse.java:201)
at com.icesoft.faces.context.View$2.serve(View.java:77)
at com.icesoft.faces.context.View.servePage(View.java:149)
at com.icesoft.faces.webapp.http.core.MultiViewServer.service(MultiViewServer.java:79)
at com.icesoft.faces.webapp.http.common.ServerProxy.service(ServerProxy.java:11)
at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet$4.service(MainSessionBoundServlet.java:149)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:60)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:148)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:359)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
For the sake of interest, views are rendered by the SpringFramework treating the JSF Views as a certain type of renderable.
at com.icesoft.faces.facelets.D2DFaceletViewHandler.renderResponse(D2DFaceletViewHandler.java:284)
at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:159)
at org.springframework.faces.webflow.FlowViewHandler.renderView(FlowViewHandler.java:92)
at org.springframework.faces.webflow.JsfView.render(JsfView.java:94)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:245)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:204)
at org.springframework.webflow.engine.Flow.resume(Flow.java:545)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:262)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:163)
at com.icesoft.faces.webapp.http.core.FlowExecutorUtil.resumeExecution(FlowExecutorUtil.java:86)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.resumeExecution(SwfLifecycleExecutor.java:129)
at com.icesoft.faces.webapp.http.core.SwfLifecycleExecutor.apply(SwfLifecycleExecutor.java:55)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.renderCycle(ReceiveSendUpdates.java:132)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.service(ReceiveSendUpdates.java:74)
at com.icesoft.faces.webapp.http.core.RequestVerifier.service(RequestVerifier.java:31)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:60)
at com.icesoft.faces.webapp.http.servlet.SessionVerifier.service(SessionVerifier.java:26)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:148)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
When a FileUpload request is processed a lifecycle event is generated by the upload process in order to update the Upload progress page. Since the PathDispatcher matches the path of the FileUploadServlet execution goes down that route and doesn't have the Spring path portions in it, therefore a Spring webflow isn't resumed. Since the Spring Webflow isn't resumed, the StateSaving code executed when running the lifecycle is delegated to our StateSaving implementation which is looking for a viewRoot in the State Maps in the session.
at com.icesoft.faces.webapp.http.core.UploadServer$2.servlet(UploadServer.java:127)
at com.icesoft.faces.webapp.http.servlet.ServletRequestResponse.detectEnvironment(ServletRequestResponse.java:262)
at com.icesoft.faces.webapp.http.core.UploadServer.service(UploadServer.java:69)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:60)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:148)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:359)
Since we haven't been involved in saving the state at any time in the past, there isn't any copy of the ViewRoot in the Session when this attempt is made, hence the error.
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion