Reputation: 21
I have a page that uses rich:fileUpload for uploading files. For smaller files this works ok, however for larger files (+80MB) I usually get a ViewExpiredException. I already tried to search for a solution, but I didn't find anything that solved this.
The pagebean:
@Component
@Scope("request")
public class Bean {
...
}
The jspx:
<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root omit-xml-declaration="true"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
xmlns:rich="http://richfaces.ajax4jsf.org/rich"
xmlns:ui="http://java.sun.com/jsf/facelets" version="2.0">
<rich:panel styleClass="formPanel">
<h:form id="docForm">
<ui:param name="doc" value="#{pb.newDoc}" />
<h:panelGrid columns="2" columnClasses="formTableLabel, formTableField">
...
<h:outputLabel for="fileUpload" value="#{labels['file']}*" />
<h:panelGroup>
<rich:fileUpload required="true" ajaxSingle="true"
fileUploadListener="#{pb.uploadDocument}" id="fileUpload"
autoclear="false" immediateUpload="true" noDuplicate="true"
addControlLabel="#{labels['browse']}">
<a4j:support event="onclear" reRender="fileUpload" ajaxSingle="true"
oncomplete="$('docForm:fileUpload').component.currentInput.enable()"/>
</rich:fileUpload>
<h:message for="fileUpload" styleClass="errorMessage"
showDetail="false" showSummary="true" />
</h:panelGroup>
...
The web.xml:
...
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>facelets.SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.BUFFER_SIZE</param-name>
<param-value>500000</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.LoadScriptStrategy</param-name>
<param-value>ALL</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.LoadStyleStrategy</param-name>
<param-value>ALL</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jspx</param-value>
</context-param>
<context-param>
<description>
Context parameter specifically for facelets, lists available tag libraries.
</description>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
/WEB-INF/taglibs/authorization.taglib.xml;
/WEB-INF/taglibs/taskscreen.taglib.xml
</param-value>
</context-param>
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/config/faces-config.xml</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
<init-param>
<param-name>forceparser</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Pretty Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>FacesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<welcome-file-list>
<welcome-file>start/start.jspx</welcome-file>
</welcome-file-list>
<error-page>
<error-code>500</error-code>
<location>/error.jspx</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/access-denied.jspx</location>
</error-page>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/expired.jsf</location>
</error-page>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
...
The stacktrace:
SEVERE: JSF1054: (Phase ID: RESTORE_VIEW 1, View ID: ) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@22075431]
2012-09-13 16:43:46,945 [qtp130437654-18] ERROR org.ajax4jsf.webapp.BaseXMLFilter doXmlFilter - Exception in the filter chain
javax.servlet.ServletException: viewId:/data/includes/doc.jspx - View /data/includes/doc.jspx could not be restored.
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:270)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:521)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1207)
at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206)
at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:367)
at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1178)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:433)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:118)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:490)
at org.eclipse.jetty.server.session.SessionHandler.handle(SessionHandler.java:179)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:928)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:370)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:862)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:116)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:331)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:115)
at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:64)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1178)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:278)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:110)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1178)
at com.doc.filter.IEFilter.doFilter(IEFilter.java:33)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1178)
at com.doc.portal.filter.ExceptionRedirectFilter.doFilter(ExceptionRedirectFilter.java:28)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1178)
at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:110)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1178)
at com.doc.filter.UTF8Filter.doFilter(UTF8Filter.java:20)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1178)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:433)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:118)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:456)
at org.eclipse.jetty.server.session.SessionHandler.handle(SessionHandler.java:179)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:928)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:370)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:862)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:116)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:115)
at org.eclipse.jetty.server.Server.handle(Server.java:330)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:557)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.content(HttpConnection.java:947)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:736)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:203)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:413)
at org.eclipse.jetty.server.bio.SocketConnector$Connection.run(SocketConnector.java:229)
at org.eclipse.jetty.server.ssl.SslSocketConnector$SslConnection.run(SslSocketConnector.java:648)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:435)
at java.lang.Thread.run(Thread.java:662)
Caused by: javax.faces.application.ViewExpiredException: viewId:/data/includes/doc.jspx - View /data/includes/doc.jspx could not be restored.
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:189)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:102)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
... 75 more
Anybody got any ideas how to fix this? Thx.
Upvotes: 2
Views: 1336
Reputation: 10463
This may not be what you want to hear, but standard HTTP protocol just doesn't work well with uploading of large files. Typically in a peer to peer socket application, client and server can both maintain connection health and keep everything alive during large transfers. With HTTP and the web however, the only thing stateful that the client typically has are its cookies. The client cannot know if its cookies are still valid (CORRECTION: Unless they are explicitly set to expire at a specific date) until gives them to the server and gets a response back with the results.
So because of this, the server needs to impose a timeline on the life of a session, and after that time has passed, it will toss the stateful information for the session. Compound this by the fact that typical internet connections tend to have a somewhat slower upload speed than download speed, and it is not unusual for the session to become invalidated while waiting for a large file to upload.
You have three options:
You increase the session timeout expiration period on the server. Perhaps this will give you enough time.
You utilize a rich client interface (Flash, Applet, Silverlight, etc...) and you utilize this rich client by uploading your file through this on your webpage instead. The benefit here is that you can break your large file up into manageable binary chunks and send them to the server with your session cookie one at a time. Each of these successful chunk requests will have the effect of keeping your session alive throughout the transfer. Your server after receiving the final chunk can reassemble your large file and persist it.
Do basically the same thing as #2 except utilize the power of HTML5 and JS. The following is an open source Javascript library that utilizes HTML5 technology to also break up large files into chunks and assist in reassembling them on the server. http://steffentchr.dk/post/7454042318/resumable-js Some of the cons of this approach is that since it is using HTML5, it will only work on modern browsers, so support for older browsers like IE7 is questionable.
Another note on point 3 is that it isn't outside the realm of possibility to include this Javascript code inside of a custom or composite JSF component that will allow you a more streamlined interface between client and server.
Also, see the following question: Upload of very large files
Upvotes: 3