6 Replies Latest reply on Feb 14, 2009 9:52 AM by Nick Belaevski

    The session is valid, but javax.faces.application.ViewExpire

    Hu Ecko Newbie

      Environment: tomcat6.0.18
      Technologies: JSF + Facelets + Richfaces/Ajax4Jsf + Spring + Ibatis

      There is a strange problem in my web application, the problem is:

      There is not session timeout, but the "javax.faces.application.ViewExpiredException" often be thrown when using this web application in internet environment, however in the intranet anything is well, I don't know why.

      Except for session timeout, whether there are any other cases that cause this exception?

      1. When not session timeout, the exception stack look like this: [I don't know why the exception is thrown]

      2009-02-10 15:17:09,546 ERROR [org.ajax4jsf.webapp.BaseXMLFilter] - Exception in the filter chain
      javax.servlet.ServletException: viewId:/html/sale/so/search_so_list.jsf - View /html/sale/so/search_so_list.jsf could not be restored.
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:270)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
      at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
      at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
      at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at com.shinwa.faces.common.AuthorizationFilter.doFilter(AuthorizationFilter.java:103)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
      at java.lang.Thread.run(Thread.java:619)
      Caused by: javax.faces.application.ViewExpiredException: viewId:/html/sale/so/search_so_list.jsf - View /html/sale/so/search_so_list.jsf could not be restored.
      at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:185)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
      at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:103)
      at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)

      2. When session timeout, the exception stack look like this:

      2009-02-10 15:03:09,546 com.sun.faces.lifecycle.Phase doPhase
      严�: JSF1054: (Phase ID: RESTORE_VIEW 1, View ID: ) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@1f3b536]
      2009-02-11 21:17:09,546 ERROR [org.ajax4jsf.webapp.BaseXMLFilter] - Exception in the filter chain
      javax.servlet.ServletException: viewId:/html/sale/so/search_so_list.jsf - View /html/sale/so/search_so_list.jsf could not be restored.
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:270)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
      at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
      at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
      at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at com.shinwa.faces.common.AuthorizationFilter.doFilter(AuthorizationFilter.java:103)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
      at java.lang.Thread.run(Thread.java:619)
      Caused by: javax.faces.application.ViewExpiredException: viewId:/html/sale/so/search_so_list.jsf - View /html/sale/so/search_so_list.jsf could not be restored.
      at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:185)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
      at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:103)
      at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)


      3. The application uses SERVER state saveing method, and uses com.sun.facelets.FaceletViewHandler, the web.xml file detail is as follow:

      <context-param>
      <param-name>com.sun.faces.verifyObjects</param-name>
      <param-value>false</param-value>
      </context-param>
      <context-param>
      <param-name>com.sun.faces.validateXml</param-name>
      <param-value>false</param-value>
      </context-param>
      <context-param>
      <param-name>javax.faces.CONFIG_FILES</param-name>
      <param-value>/WEB-INF/faces-config-beans.xml,/WEB-INF/faces-config-navigation.xml,/WEB-INF/faces-config-miscellaneous.xml</param-value>
      </context-param>
      <context-param>
      <param-name>webAppRootKey</param-name>
      <param-value>WAAJ.root</param-value>
      </context-param>
      <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/config/appContext.xml,/WEB-INF/config/dataAccessContext.xml</param-value>
      </context-param>
      <context-param>
      <param-name>log4jConfigLocation</param-name>
      <param-value>/WEB-INF/config/log4j.xml</param-value>
      </context-param>
      <context-param>
      <param-name>org.richfaces.SKIN</param-name>
      <param-value>blueSky</param-value>
      </context-param>
      <context-param>
      <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
      <param-value>com.sun.facelets.FaceletViewHandler</param-value>
      </context-param>
      <context-param>
      <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
      <param-value>.xhtml</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.STATE_SAVING_METHOD</param-name>
      <param-value>server</param-value>
      </context-param>
      <context-param>
      <param-name>facelets.BUFFER_SIZE</param-name>
      <param-value>500000</param-value>
      </context-param>

      <display-name>Ajax4jsf Filter</display-name>
      <filter-name>ajax4jsf</filter-name>
      <filter-class>org.ajax4jsf.Filter</filter-class>
      <init-param>
      <param-name>createTempFiles</param-name>
      <param-value>false</param-value>
      </init-param>
      <init-param>
      <param-name>maxRequestSize</param-name>
      <param-value>20000000</param-value>
      </init-param>
      <init-param>
      <param-name>forceparser</param-name>
      <param-value>false</param-value>
      </init-param>

      <filter-mapping>
      <filter-name>ajax4jsf</filter-name>
      <servlet-name>Faces Servlet</servlet-name>
      REQUEST
      FORWARD
      INCLUDE
      </filter-mapping>

      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>


      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>


      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
      <load-on-startup>1</load-on-startup>

      <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>*.jsf</url-pattern>
      </servlet-mapping>
      <session-config>
      <session-timeout>30</session-timeout>
      </session-config>
      <welcome-file-list>
      <welcome-file>/index.jsp</welcome-file>
      </welcome-file-list>
      <error-page>
      <exception-type>javax.faces.application.ViewExpiredException</exception-type>
      /errorPages/ViewExpired.jsp
      </error-page>
      <error-page>
      <error-code>403</error-code>
      /errorPages/403.jsp
      </error-page>
      <error-page>
      <error-code>404</error-code>
      /errorPages/404.jsp
      </error-page>
      <error-page>
      <error-code>408</error-code>
      /errorPages/ViewExpired.jsp
      </error-page>
      <error-page>
      <error-code>500</error-code>
      /errorPages/500.jsp
      </error-page>
      <security-constraint>
      <web-resource-collection>
      <web-resource-name>All Pages</web-resource-name>
      <url-pattern>/html/*</url-pattern>
      <url-pattern>/errorPages/*</url-pattern>
      <http-method>POST</http-method>
      <http-method>GET</http-method>
      </web-resource-collection>
      <auth-constraint>
      <role-name>PUBLIC</role-name>
      </auth-constraint>
      </security-constraint>
      <login-config>
      <auth-method>FORM</auth-method>
      <realm-name>WAAJ DataSource Realm</realm-name>
      <form-login-config>
      <form-login-page>/login.jsp</form-login-page>
      <form-error-page>/errorPages/canotauth.jsp</form-error-page>
      </form-login-config>
      </login-config>
      <security-role>
      <role-name>PUBLIC</role-name>
      </security-role>
      <resource-ref>
      <res-ref-name>jdbc/WAAJdb</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
      </resource-ref>

        • 1. Re: The session is valid, but javax.faces.application.ViewEx
          Ilya Shaikovsky Master

          Is you server environment clustered?

          • 2. Re: The session is valid, but javax.faces.application.ViewEx
            Hu Ecko Newbie

            No, just only one web container.

            PS:

            the web application have a function to fetch the email by
            <a4j:poll interval="300000" reRender="mailPanel"
            eventsQueue="eventsQueue" ignoreDupResponses="true" ajaxSingle="true" bypassUpdates="true"/>


            May a4j:poll be a possible to cause the ViewExpiredException?


            Thank you!

            • 3. Re: The session is valid, but javax.faces.application.ViewEx
              Hu Ecko Newbie

              This a4j:poll is located in a template page, so that all page can use this function.

              • 4. Re: The session is valid, but javax.faces.application.ViewEx
                Hu Ecko Newbie

                Now, JSF is able to save up to 15 page states in session. Would this tow context parameter(com.sun.faces.numberOfViewsInSession, com.sun.faces.numberOfLogicalViews), which the default value is 15, be relate to?


                com.sun.faces.numberOfViewsInSession ------ Defaults to 15. This parameter defines the maximum number of JSF views stored in the session for per logical view. The map used to store the views uses an LRU algorithm to keep the map from growing beyond the configured value.


                com.sun.faces.numberOfLogicalViews - Defaults to 15. This parameter defines the maximum number of logical views to store per session. The map used to store the logical views uses an LRU algorighm to keep the map from growing beyone the configured value.

                • 5. Re: The session is valid, but javax.faces.application.ViewEx
                  Hu Ecko Newbie

                  Abstract from FAQs about Mojarra (Sun's JSF implementation):

                  * com.sun.faces.numberOfViewsInSession - Defaults to 15. This parameter defines the maximum number of JSF views stored in the session for per logical view. The map used to store the views uses an LRU algorithm to keep the map from growing beyond the configured value.
                  * com.sun.faces.numberOfLogicalViews - Defaults to 15. This parameter defines the maximum number of logical views to store per session. The map used to store the logical views uses an LRU algorighm to keep the map from growing beyone the configured value.

                  A comment on the numberOfXXX parameters. Logical views are best defined as top level view that may have one or more actual views inside of it. A new logical view entry will be created any time a GET occurs (a new request, a frameset, two browser windows...). The value of this logical entry is another Map that will be used to store the view information (i.e. the structure and state). As a user progresses through an application using standard JSF navigation mechanisms, additional view state will be added to the Map associated with a single logical view.

                  As an example, using the jsf-guessNumber application.

                  * First request results in a state marker value of j_id1:j_id2. j_id1 represents the logical view, and j_id2 represents the actual view state.
                  * Next, enter a guess. The new state marker value is j_id1:j_id3 - again j_id1 being the logical view, and j_id3 being the actual view. So at this point, the Map associated with logical view j_id1 has two entries, j_id2, and i_id3.
                  * Next, click the Back button, and the new marker is j_id1:j_id4.
                  * Now, issue a request to the context root of the application and notice that the state marker has now changed to j_id5:j_id6. As stated above, each GET will cause a new logical entry to be created. At this point, there are two logical Maps, j_id1 and j_id5. Logical Map j_id1, has three entries, j_id2, j_id3, and j_id4. Logical Map j_id5, has a single entry, j_id6.


                  The follow content is my understanding:

                  It means that a new actual view state will be created when POST request, and a new logical view entry will be create when GET request.

                  A logical view entry will store more than one actual view state, so we should increase the value of com.sun.faces.numberOfViewsInSession when there would be many POST request(AJAX request implemented by richfaces/ajax4jsf) in one form.

                  For example , for our web application, in one form, there are many ajax request for retrieve data for many fields, so these ajax requests will cause many POST requests and results in many view state to be created.
                  And in one form, there saves a view state id by , this id represent a view state stored in session. Because many new view states were created before and the map used to stored view states uses an LRU algorithm, the view state specified by the view state id would be so likely to be removed from session. So when the user fill in all data completely and submit the form, system can not restore the view state specified by the submitted id at last, and then throw ViewExpiredException.

                  If there are some mistake, please point out for me

                  thank you very much!

                  • 6. Re: The session is valid, but javax.faces.application.ViewEx
                    Nick Belaevski Master

                    Hello,

                    So let me simplify this:

                    numberOfViewsInSession defines how many different pages (e.g. XHTML files) can store its state, e.g. if you have numberOfViewsInSession=2 and state is stored for view1.xhtml and view2.xhtml, then state for view3.xhtml will replace the one for view1.xhtml or view2.xhtml when requested.

                    numberOfLogicalViews defines how many different state for the same page (logical view - it can be different for the same XHTML/JSP page depending on bean values etc.) can be stored.

                    One important thing to know - AJAX requests all share the same logical view state. If you inspect page contents using Firebug or DOM inspector you'll see that value of javax.faces.ViewState stays the same before and after AJAX request. As far as I know JSF 2.0 developers are working on incremental state saving that will address this issue.

                    Back to a4j:poll - you can easily check that it doesn't overcome numberOfLogicalViews limit by itself. Just set it to 1, wait for several polls, then press h:commandButton:

                    <h:form>
                     <a4j:status startText="...start..." />
                     <a4j:poll interval="1000" />
                    
                     <h:commandButton />
                     </h:form>
                    - works ok for me. To make sure application obeys this parameter you can open another view in the same session - you'll see ViewExpiredException coming because new logical view has been created.