Random JSF error: no saved view state could be found - jsf

I have a very strange error: No saved view state could be found for the view identifier: /mypage.xhtml
The problem is that it appears randomly, to just ~10% of the users/executions.
Application server: Apache Tomee 1.5.2 stable / 1.6.0-2013.09.20 dev (It happens on both). I use the MyFaces distribution that comes with each of them, so 2.1.10 / 2.1.12, so nothing new added.
Part of web.xml:
<context-param>
<param-name>org.apache.myfaces.USE_ENCRYPTION</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
So, no state view exception shouldn't happen, because state is on client. It was set on server before, but I thought maybe client will fix it, but nothing. There was actually no difference in the occurrence of that error.
Execution flow:
1. Client opens xhtml page (JSF).
2. Client clicks on an command button to do various things, button connected to a public void method of a JSF #ViewScoped ManagedBean.
3. Yes, the method is void because I don't need to return a String to redirect to another page. I need to redirect to /page/id (example: /market/24, /profile/43), therefore methods that return a String as navigation destinations are useless, because I use: FacesContext.getCurrentInstance().getExternalContext().redirect(path);
4. In ~90% of the cases, everything works perfectly and users are redirected to each specific page. In the rest of ~10 (randomly), they get No saved view state could be found for the view identifier: /pagename.xhtml
I would really appreciate some help here, because I have no idea how to get it fixed.
Thanks a lot in advance.
PS. I use PrimeFaces and I also have a couple of my own filters in web.xml, but that shouldn't be a problem, I hope so.
Stack trace for one of the pages:
25-Sep-2013 07:39:26.380 SEVERE [http-bio-80-exec-15] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [Faces Servlet] in context with path [] threw exception [/dashboard/edit-profile.xhtmlNo saved view state could be found for the view identifier: /dashboard/edit-profile.xhtml] with root cause
javax.faces.application.ViewExpiredException: /dashboard/edit-profile.xhtmlNo saved view state could be found for the view identifier: /dashboard/edit-profile.xhtml
at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:132)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:170)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:77)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.pingushare.boundary.filter.ActivateAccountFilter.doFilter(ActivateAccountFilter.java:37)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.pingushare.boundary.filter.SecurityFilter.doFilter(SecurityFilter.java:36)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.pingushare.boundary.filter.ForceFreshPageAndWWWFilter.doFilter(ForceFreshPageAndWWWFilter.java:49)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)

This issue is well understood and it happens because if the server is restarted or the application is redeployed, a new encryption key is generated by default. The solution is generate your own key and set it up in your web.xml file. In that way, MyFaces will use the same key at all times. See http://wiki.apache.org/myfaces/Secure_Your_Application
The description claims that encryption is disabled, and I have checked the code and it is ok, it works as expected (the encryption is effectively disabled). If the encryption is not the problem, my opinion is there is an error in your application logic. Don't call redirect in that way, use the standard form using mypage.xhtml?faces-redirect=true . The problem could be caused by a session expiration (note only view scope beans goes to the client in 2.0/2.1, but session scope beans are expired).

After long discussions on MyFaces and Tomee forums/mailing lists, this is how I managed to eliminate this problem: I switched the JSF implementation in this project to Majorra 2.1.26. The error didn't appear anymore until now.
As this bug didn't make any sense (after checking source of both my project and MyFaces) and couldn't be reproduced, we couldn't actually find a fix for it, but at least it doesn't happen in Majorra, so this could be helpful if someone else gets this error.
Mention: this is not the basic "no saved view state could be found" that many JSF developers get. That's something else hiding somewhere.

Related

View declared in <protected-views> still accessible after manipulating CSRF token

I'm exploring the new features in JSF 2.2 (pretty cool so far) but I still don't understand how Protected Views works, I created a facelet1 with a link to facelet2, like this:
<h:link styleClass="link" value="Go to protected page" id="link1"
outcome="/protected/facelet2.xhtml"></h:link>
and in my faces-config.xml I added this:
<protected-views>
<url-pattern>/protected/facelet2.xhtml</url-pattern>
</protected-views>
Now when I run the page a token is added in the url:
http://localhost:8080/<project>/protected/facelet2.faces?javax.faces.Token=1426608965211
According to the documentation, if the token does not match with the one in the server, the GET request is not processed (is my understanding correct?).
But if I modify the token (using Firebug or the dev tools included in the browser) the request is still processed, even if the token was modified.
Am I doing something wrong?
This is caused because your FacesServlet is apparently mapped on JSF 1.0-style URL pattern of *.faces instead of JSF 2.0-style URL pattern of *.xhtml. The <protected-views><url-pattern> must match the actual URL pattern as you see in browser's address bar.
So, given an actual URL of /protected/facelet2.faces, you need to configure it as below:
<protected-views>
<url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>
However, while at it, I discovered some nasty issues in current Mojarra 2.2.10 implementation:
It does actually not do a prefix/suffix match as per Servlet 12.1 specification (there's even a vague comment in source code indicating that!). It does merely an exact match. This means, you can't use wildcard URL patterns like /protected/*.
When generating the <h:link>, it does not compare the protected view URL pattern to the resolved URL, but to the JSF view ID. And, when checking an incoming request, it does not compare the request URL to the JSF view ID (like as during link generation), but to the <url-pattern>. This thus never matches, totally explaining why you could simply access it without a valid token.
Basically, you need the following configuration if you need to keep the JSF 1.0-style URL pattern of *.faces.
<protected-views>
<url-pattern>/protected/facelet2.xhtml</url-pattern>
<url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>
It'll then properly throw javax.faces.application.ProtectedViewException when being accessed without a valid token. Much better is to just map the FacesServlet explicitly on *.xhtml in web.xml.
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
This way you never need to deal with virtual URLs.
I've reported this to Mojarra guys as issue 3837.
See also:
Sometimes I see JSF URL is *.jsf, sometimes *.xhtml and sometimes /faces/*. Why?

Composite Components in subfolders

I am experiencing a problem with a composite component. I'm not quite sure if it's a bug in one of the used libraries or just my own ignorance of the matter. If I put the component bar.xhtml files in
WebContent/resources/foo/bar.xhtml
everything is working as intended. But if I put them in
WebContent/resources/subfolder/foo/bar.xhtml
they are just not displayed, and I get the message:
The page /login.xhtml declares namespace http://java.sun.com/jsf/composite/subfolder/foo and uses the tag foo:bar , but no TagLibrary associated to namespace.
I suspect it has something to do with the unmapped resource handler from Omnifaces, and is maybe just a parameter I'm not able to figure out. Maybe someone can give me a hint here?
I'm using (amongst others):
Apache MyFaces 2.2.4
Omnifaces 1.8.1
Primefaces 5.0
Tomcat 8.0.12
Edit 2
Moved the answer to a reply
Ok - after sleeping one night over it, I found out that this had nothing to with Omnifaces, but with a change in MyFaces since 2.1.6. Since then, you have to put the following in your web.xml:
<context-param>
<param-name>org.apache.myfaces.STRICT_JSF_2_ALLOW_SLASH_LIBRARY_NAME</param-name>
<param-value>true</param-value>
</context-param>
(found here )

NullPointerException from RestoreViewPhase.notifyAfter

I'm getting the following error whenever I try to view JSF pages that contain forms.
java.lang.NullPointerException
com.sun.faces.lifecycle.RestoreViewPhase.notifyAfter(RestoreViewPhase.java:288)
com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:349)
What does this mean?
This problem started when I tried to use validators on my form fields. So I removed all the validators, but still the problem is not going away.
Thanks for the help.
Could be this logged issue: http://java.net/jira/browse/JAVASERVERFACES-1764
If that is the case then it should be fixed in JSF version 2.1.

ViewExpiredException shown in java.lang.Throwable error-page in web.xml

I'm working on a JSF web application in which I need to bring up a "Session Expired" page if the view expires, but a general technical error page for all others. The application only goes to the technical error page when I trigger the exception. Here's the error-page definitions:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/jsps/utility/sessionExpired.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/jsps/utility/technicalError.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/jsps/utility/technicalError.jsp</location>
</error-page>
I removed the technicalError.jsp error page elements and it worked fine, but when I put them back I can't get to the sessionExpired.jsp page. How do I tell the web container the order to evaluate these tags so that the right page comes up? Thanks.
This is because the ViewExpiredException is been wrapped in a ServletException as per the JSF specification. Here's an extract of chapter 10.2.6.2 of the JSF 1.2 specification:
10.2.6.2 FacesServlet
Call the execute() method of the saved Lifecycle instance, passing the
FacesContext instance for this request as a parameter. If the execute() method
throws a FacesException, re-throw it as a ServletException with the
FacesException as the root cause.
How the error pages are allocated is specified in Servlet API specification. Here's an extract of chapter 9.9.2 of Servlet API specification 2.5:
SRV.9.9.2 Error Pages
If no error-page declaration containing an exception-type fits using the
class-hierarchy match, and the exception thrown is a ServletException or
subclass thereof, the container extracts the wrapped exception, as defined by
the ServletException.getRootCause method. A second pass is made over the error
page declarations, again attempting the match against the error page
declarations, but using the wrapped exception instead.
In class hierarchy, ServletException already matches Throwable, so its root cause won't be extracted for the second pass.
To prove this specified behaviour, replace javax.faces.application.ViewExpiredException by javax.servlet.ServletException as <exception-type> and retry. You'll see the expected error page being displayed.
To solve this, simply remove the error page on java.lang.Throwable or java.lang.Exception. If no one exception specific error page matches, then it will fall back to the one for error code of 500 anyway. So, all you need is this:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/jsps/utility/sessionExpired.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/jsps/utility/technicalError.jsp</location>
</error-page>
Update: as per the (deleted) comment of the OP: to reliably test this you cannot do a throw new ViewExpiredException() in a bean constructor or method or so. It would in turn get wrapped in some EL exception. You can eventually add a debug line printing rootCause in the Filter to see it yourself.
If you're using Eclipse/Tomcat, a quick way to test ViewExpiredException is the following:
Create a JSF page with a simple command button, deploy and run it and open it in webbrowser.
Go back to Eclipse, rightclick Tomcat server and choose Clean Tomcat Work Directory. This will restart Tomcat and trash all serialized sessions (important! just restarting Tomcat is not enough).
Go back to webbrowser and press the command button (without reloading page beforehand!).
As mentioned by BylusC, deployment descriptor must not contain any error-page handler that will catch ViewExpiredException (wrapped inside ServletException) instead of the correct one - error-page for ViewExpiredException.
Do not forget to verify that server's deployment descriptor (e.g. TomEE/conf/web.xml) does not contain java.lang.Throwable or java.lang.Exception error-page definitions. Because these two web.xml are basically merged.
Yes - application's web.xml has precedence over server's web.xml, but if application's web.xml contains
error-page for 500 (/error.xhtml)
and server's web.xml for
500 (/500.html) and for
Throwable (/bigerror.html)
then application context will contain merge of those two:
500 (/error.xhtml)
Throwable (/bigerror.html)
and ViewExpiredExcpetion error handling will not work correctly.

JSF - serving a page without xhtml

I am working on some UI Components that I would like to use entirely instead of writing the XHTML.
I am perfectly happy with XHTML; however, I want to break everything up into modules as well as break the physical connection between a URL and a file in a WAR or on the filesystem. I also want it to be entirely virtual so that I have greater control over security.
Is it possible to do this using a Servlet Filter? I am using Seam 2.2.0.GA and should have access to the FacesContext which means I will have access to the UIViewRoot component as well as render kit.
This is the latest error I'm getting - I am guessing I don't have my components properly configured:
java.lang.NullPointerException
at com.sun.faces.context.FacesContextImpl.getRenderKit(FacesContextImpl.java:258)
at com.sun.faces.renderkit.RenderKitUtils.getResponseStateManager(RenderKitUtils.java:237)
at com.sun.faces.lifecycle.LifecycleImpl.reload(LifecycleImpl.java:331)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:134)
at com.walterjwhite.seamCore.servlet.filter.FacesFilter.doFilter(FacesFilter.java:97)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at com.walterjwhite.webContent.servlet.filter.UploadedFileFilter.doFilter(UploadedFileFilter.java:97)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at com.walterjwhite.seamCore.servlet.filter.HttpRequestMonitoringFilter.doFilter(HttpRequestMonitoringFilter.java:59)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at com.walterjwhite.seamCore.servlet.filter.ContextFilter$1.process(ContextFilter.java:60)
at org.jboss.seam.servlet.ContextualHttpServletRequest.run(ContextualHttpServletRequest.java:53)
at com.walterjwhite.seamCore.servlet.filter.ContextFilter.doFilter(ContextFilter.java:55)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)
at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
at com.walterjwhite.seamCore.servlet.filter.DisableUrlSessionFilter.doFilter(DisableUrlSessionFilter.java:82)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:378)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:865)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)
Walter
You can definitely modify the component tree from a filter. Another technique is to build part of the page as jsf, then bind to a component such as a panel group layout & build the components inside it from a managed bean.
UIComponent parent = ...
for(...) {
parent.getChildren().add(...);
}
The physical connection between URL & file is already broken. You can use a navigation rule to point to anything you want. Not sure what you mean by entirely virtual regarding security.
This is just my opinion, but a dynamic component approach is not as extensible as jsf & metadata.
Is it possible to do this using a Servlet Filter? I am using Seam 2.2.0.GA and should have access to the FacesContext which means I will have access to the UIViewRoot component as well as render kit.
A Filter is probably not a good place to do this. If memory serves, the FacesContext is set up and torn down in the FacesServlet in core JSF (you may know better than me if Seam requires other servlets to do some lifecycle lifting). So, the context will probably not be in scope in the filter.
Providing your own ViewHandler decorator would probably be a better bet. You can extend ViewHandlerWrapper and give it a constructor that takes the decorated ViewHandler from the framework. This can be defined in your faces-config.xml. You'll find more details in the spec.

Resources