Search code examples
javajsfwebsphere-libertycicsstate-saving

JSF Servlet Exception: No view save state when application session jumps between servers


I have a web app running on in a CICS environment on Liberty servers. For workload management, the application session is set up to shift between 3 different servers, which occurs randomly during a given session. Implementing this, I am currently receiving the following error:

Error 500: javax.servlet.ServletException: /{page_name}.xhtml - No saved view 
state could be found for the view identifier: /{page_name}.xhtml

The error happens at random, but it appears that it only occurs when the application session has hopped to a different server. I verified this by shutting down two servers, and saw that a session would run without any problems after that. My application has security and requires login credentials when a session starts, and I believe this is somehow affecting the rendering of pages when it jumps servers, as if the credentials are not jumping with the session. I did some research and attempted to switch the state_saving method from server to client by adding the following context param to the applications web.xml:

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>        
    <param-value>client</param-value>
</context-param>

Unfortunately, the issue still persists. Any suggestions would be much appreciated. If any more information or a larger stack trace is needed, please comment below!

EDIT: Stacked Trace:

[2/12/19 15:25:53:672 CST] 00000056 com.ibm.ws.webcontainer.webapp                               
E SRVE0315E: An exception occurred: java.lang.Throwable: 
javax.servlet.ServletException: /pltdisable.xhtml - No saved view state 
could be found for the view identifier: /pltdisable.xhtml
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:5006)
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.handleRequest(DynamicVirtualHost.java:314)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:995)
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.run(DynamicVirtualHost.java:279)
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink$TaskWrapper.run(HttpDispatcherLink.java:1009)
at com.ibm.cics.wlp.impl.CICSHttpRunnable.run(CICSHttpRunnable.java:244)
at com.ibm.cics.wlp.impl.CICSTaskWrapper.runWork(CICSTaskWrapper.java:762)
at com.ibm.cics.wlp.impl.CICSTaskWrapper.run(CICSTaskWrapper.java:415)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1160)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at com.ibm.cics.wlp.threading.CICSThread.run(CICSThread.java:245)
at com.ibm.cics.wlp.threading.CICSPooledThreadFactory.joinAsThreadInternal(CICSPooledThreadFactory.java:409)
at com.ibm.cics.wlp.threading.CICSPooledThreadFactory.joinAsThread(CICSPooledThreadFactory.java:335)
at com.ibm.cics.server.internal.ThreadJoiner.main(ThreadJoiner.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.cics.server.Wrapper.call_main(Wrapper.java:893)
at com.ibm.cics.server.Wrapper.callOSGiClass(Wrapper.java:2816)
at com.ibm.cics.server.Wrapper.invokeJvmServerOSGiClass(Wrapper.java:2683)
at com.ibm.cics.server.Wrapper.jvmServerOSGiEntry(Wrapper.java:2612)
at com.ibm.cics.osgi.impl.Controller.runService(Controller.java:1413)
at com.ibm.cics.osgi.impl.Controller.acceptRequest(Controller.java:322)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.cics.router.Router.route(Router.java:1317)
Caused by: javax.servlet.ServletException: /pltdisable.xhtml - No saved view 
state could be found for the view identifier: /pltdisable.xhtml
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:214)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1255)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:743)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:440)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1155)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:4962)
... 28 more

Solution

  • Given your scenario, it's likely that the No saved view state error occurs when a request is routed to a different server than the one on which its session began, and that new server cannot process the view state it's passed.

    This happens because MyFaces has view state encryption enabled by default - and by default, the secret keys for that encryption are generated randomly at startup. So given a completely default configuration, different servers in a cluster won't be able to share encrypted view states, because each server will have been initialized with a different random secret key. In order to share encrypted view states between servers, those servers need to have been configured to use the same secret keys. Those can be set via these web config parameters:

    <!-- Defines the secret (Base64 encoded) used to initialize the secret key
         for encryption algorithm. The size of it depends on the algorithm used for encryption -->
    <context-param>
        <param-name>org.apache.myfaces.SECRET</param-name>
        <param-value>your_secret_key</param-value>
    </context-param>
    
    <!-- Define the initialization code (Bas64 encoded) that are used to initialize the secret key used
         on the Message Authentication Code algorithm. The size of it depends on the algorithm used for mac calculation -->
    <context-param>
        <param-name>org.apache.myfaces.MAC_SECRET</param-name>
        <param-value>your_mac_secret_key</param-value>
    </context-param>
    

    The MyFaces wiki details security configuration. The default security parameter settings - in addition to your secret keys - are sufficient for a secure deployment.