1

I am in the process of upgrading the JSF implementation in an existing project, that uses MyFaces 1.1, to version 2.1. I mainly follow the instructions given in Migrating from JSF 1.2 to JSF 2.0.

Since I plan to upgrade just JSF for now and postpone switching from JSP to Facelets and updating component libraries to a later time, I have for now just done the following steps:

  • Update the MyFaces libraries by updating the version of my myfaces-api and myfaces-impl artifacts from <version>1.1.5</version> to <version>2.1.18</version> in my maven pom.xml
  • Update the faces-config.xml to comply with JSF 2.1 from <faces-config> to

    <faces-config
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
        version="2.1">
    
  • Update the web.xml to

    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">
    

Now, when I try to open the application in a browser I get the normal starting page displayed correctly, but when I click any link, I get the following error:

javax.faces.application.ViewExpiredException: /pages/View.jsf - No saved view state could be found for the view identifier: /pages/View.jsf
    at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:171)
    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.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:141)
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:281)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    ...

I didn't get this error when using the application with MyFaces 1.1, it has to be connected to the few changes I made right?

I tried the following to alliviate the problem:

  • verify that the javax.faces.STATE_SAVING_METHOD parameter is set to server in my web.xml (according to ViewExpiredException: No saved view state could be found: on submitting a form in JSF)
  • add the org.apache.myfaces.SERIALIZE_STATE_IN_SESSION parameter to my web.xml (after reading here that MyFaces 2.1 defaults this parameter to true in contrast to later Mojarra 2.1 and later MyFaces versions):

    <context-param>
        <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
        <param-value>false</param-value>
    </context-param>
    
  • set the javax.faces.DEFAULT_SUFFIX parameter to .jsp since I thought the FacesServlet might look for *.xhtml templates instead now for JSF 2.x:

    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.jsp</param-value>
    </context-param>
    
  • set the org.apache.myfaces.USE_ENCRYPTION parameter to false since it seems to default to true in MyFaces 2.1 (according to Secure Your Application and the first answer in Random JSF error: no saved view state could be found implies that re-issuing encryption keys could cause the problem):

    <context-param>
        <param-name>org.apache.myfaces.USE_ENCRYPTION</param-name>
        <param-value>false</param-value>
    </context-param>
    
  • make sure that the FacesServlet is defined in the web.xml and that URLs ending with .jsf are mapped to it:

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    

None of the steps above solved the error, so I am a little lost as to where it stems from - especially since I didn't touch the templates themselves, yet, just the configuration files.


Edit: I just discovered ViewExpiredException on every navigation after migrating from JSF 1.2 to JSF 2.0 Perhaps switching the JSF implementation would work, but the second answer in that post states that this particular bug in MyFaces is fixed in versions 2.0.7 and 2.1.1, so I expect it would be fixed in 2.1.18, too (which I try to upgrade to). The other reason why I hesitate on switching to Mojarra is that our project uses the GPL 3.0 license which - according to https://www.gnu.org/licenses/license-list.en.html - is not legally compatible to the CDDL license used by Mojarra, if I am not mistaken.

Edit 2: currently, the webapp also uses Ajax4JSF, and from Migrating JSF 1.1 with Ajax4jsf 1.x to JSF 2 I get that I need to replace the a4j tags with the f:ajax tag in my JSP files for JSF2.

On the other hand, JSF 1.2- >2.0 :viewId parameter for save view state is null reads like the f:ajax tag from JSF2 can't be used with JSP, or does this only apply to very old versions of JSP, like JSP 1.x (which is what I get from the "Old JSP is not fully supported by JSF 2" in why <f:ajax> tags doesnt work in JSP with JSF2.0)?

Is it right that since in my web.xml I have <web-app version=2.5 and because I deploy the webapp on a Tomcat 7 servlet container that I indeed am using JSP 2.2 (according to https://wiki.apache.org/tomcat/TomcatVersions), which should allow the use of the f:ajax tag from JSF2?

Could this cause the error I am experiencing?

Edit 3: I added the whole stack trace to the post and just realised that it contains indeed a reference to the ajax4jsf library, in form of the line

at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:281) (see whole stack trace above).

Could the incompatibility of JSF2 with the ajax4jsf library indeed cause the error? It is invoked by the servlet, though, and not by our application, so I do not understand how to fix this problem.

Any help with this would be greatly appreciated!

Community
  • 1
  • 1
scholt
  • 147
  • 2
  • 16
  • You have set the javax.faces.DEFAULT_SUFFIX to .jsp which means the view files will be .jsp files. But the error says "javax.faces.application.ViewExpiredException: /pages/View.jsf " which is .jsf file. shouldn't it be View.jsp file ? – OTM Apr 05 '17 at 08:22
  • Also you need to have the below Faces Servlet javax.faces.webapp.FacesServlet Faces Servlet *.jsp in web.xml – OTM Apr 05 '17 at 08:24
  • Thank you for your response. AFAIK the `url-pattern` which is mapped to a specific servlet in the `web.xml` doesn't have to do anything with the filenames of the templates. The difference is described very good in http://stackoverflow.com/questions/7914660/what-is-the-difference-between-creating-jsf-pages-with-jsp-or-xhtml-or-jsf-ex. So I do believe that `DEFAULT_SUFFIX` refers to the actual file extension expeted while `url-pattern` just defines which servlet is responsible for which requests (which is defined in my web.xml, too; I added this to the main post). – scholt Apr 05 '17 at 11:54
  • I looked at the bug report for myfaces and I don't think it's related to this issue. If it's a simple drop-and-go operation for you to replace myfaces with mojarra I'd do that since it isolates myfaces. In the event that you're running these tests on a cluster, we did encounter this issue when we ported and changed from client-side to server-side on a round-robin cluster which we solved by configuring sticky sessions in the load balancing switch. – axemoi Apr 05 '17 at 13:05
  • @axemoi Thanks for your response. We currently run the application on a single server, so no need for load balancing or other cluster related actions in our case. I do not understand your suggestion about replacing MyFaces with Mojarra, though. Didn't you say you don't believe the error has anything to do with the reported MyFaces bug? Or did you only suggest it to verify this suspicion? Anyway, I will try it and report back. – scholt Apr 05 '17 at 14:52
  • No, I meant I don't think the myfaces bug was related to the question to which it was posted nor this particular issue, though I could be wrong. The bug report was an NPE in restore view when the view had expired. In your case (as the original post) the view isn't getting saved in the first place. In the case of that post both the author and answerer switched to Mojarra, solving their problems. I could be wrong though. Either way good luck, I remember we had a lot of these growing pains during our migrate. – axemoi Apr 05 '17 at 15:57
  • The issue "javax.faces.application.ViewExpiredException: /pages/View.jsf" is primarily that JSF is not able to find/locate the stored view state for the view id "/pages/View.jsf" in the session map so that it can be restored. The view id happens to be "/pages/View.jsf". Do you have the physical file named "/pages/View.jsf"?. Also you need to set org.apache.myfaces.SERIALIZE_STATE_IN_SESSION to "true" enable the state serialization on session. – OTM Apr 05 '17 at 16:04
  • @OTM No, I don't have a physical file named "/pages/View.jsf". Are you saying that the following quote from the post I linked above is wrong? Or did I just misunderstand it? Quote: "**The *.jsf is just one of widely used URL patterns of the FacesServlet mapping in web.xml. Other ones are *.faces and /faces/*, but those are from back in the JSF 1.0/1.1 ages. They all do not represent the concrete file extension/path, but just a virtual file extension/path and is to be specified in URLs only like so http://example.com/contextname/page.jsf.**" – scholt Apr 06 '17 at 08:47
  • Also, the same combination of template name ("View.jsp") and actually called URL ("/pages/View.jsf") works when I downgrade back to JSF1.1 (and has been working for years this way). Doesn't this imply that the file extension of the template is not the cause for this error? (Also: I changed SERIALIZE_STATE_IN_SESSION to "true", but it didn't have any effect.) – scholt Apr 06 '17 at 08:51
  • @scholt Your understanding is correct. Without going in depth, the FacesServlet will figure it out based on your mapping. It'll look for a corresponding xhtml first, then a JSP. As for the serialization, if you're using view scoped I think you can get away with that parameter value being false but you'll want your beans to implement Serializable. When true they're always going to be serialized, when false it's up to the container if and when they get serialized. I saw a post recently indicating that JSF 2.3 will default the value to true. – axemoi Apr 06 '17 at 14:14
  • @axemoi Thanks for your answer. So at least I can remove the file extension of the templates from the list of potential culprits? I tried replacing MyFaces with Mojarra in my `pom.xml`, but this let to other errors (`java.lang.NoClassDefFoundError: javax/faces/application/FacesAnnotationHandler`, I guess there is some conflict with some other libraries used in the project?) Problem here really is that even if I should get the webapp to work with Mojarra, I won't be able to use it eventually because of the licence incompatibilities mentioned above. – scholt Apr 06 '17 at 14:40
  • I think that setting the "javax.faces.STATE_SAVING_METHOD" config param to "client" will solve the problem. But this may not be a good solution as it will store the whole component tree at the client side and increases the network traffic. You can give it a try to see if it works fine. – OTM Apr 06 '17 at 15:00
  • Secondly, you can try with "javax.faces.DEFAULT_SUFFIX" set to ".jsp" and "javax.faces.STATE_SAVING_METHOD" set to "server" and "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION" to "true", because from the myFaces source code it looks like from the error that Myfaces is not converting the view id(from the URL) to View.jsp(physical file) while looking for the view state in the session. – OTM Apr 06 '17 at 15:01
  • @scholt you may want to check with someone else on the license. The language in the code headers is "either the GPLv2 or CDDL" and the mojarra license contains both; I'm not a lawyer though so take that with a grain of salt. Since it's not quick task to replace myfaces it may not be worth your time, however OTM's suggestion of forcing the servlet to serialize the view state and ensuring that your bean is serializable is sound. Also I know in 1.x to mimic view scoped we were using myfaces save state tags, were you using those? – axemoi Apr 06 '17 at 15:11
  • @OTM Thanks for the advice. Unfortunately, I aldready had those three parameters (`DEFAULT_SUFFIC`, `STATE_SAVING_METHOD` and `SERIALIZE_STATE_IN_SESSION`) set to the values stated by you, but it didn't have any effect on the error. Similarily, changing `STATE_SAVING_METHOD` to `client` does not work either, I still get the same `ViewExpiredException`. – scholt Apr 10 '17 at 07:29
  • @axemoi Are you referring to the Tomahawk `t:saveState` tag? I can't find any of those in our source code, but we use the "Jenia Dynamic" tag library, from which we have some `jd:hideableArea` tags with an attribute with the same name and value `view`, e.g. ``. Would I have to change these in order to get our web application to run under JSF2.1? They do not appear in the view I am trying to call, though (`pages/View.jsf` or the corresponding `View.jsp` file) – scholt Apr 10 '17 at 07:43
  • @axemoi about what you wrote in comment #10: I was under the impression that `ViewScoped` wasn't available before JSF2. If that's the case our Beans will most likely not be `ViewScoped` since the application still uses JSF1.1 in its current form. I also checked the `faces-config.xml` just to be sure, but sure enough none of managed beans defined there is in the scope `View`. Especially all Beans used in `Main.jsp` via `include`s are configured with `request` or `session` in `faces-config.xml`. – scholt Apr 10 '17 at 11:11
  • @scholt you're absolutely correct. We emulated viewscope with a myfaces `saveState` tag. Most of our beans were `request` scoped beans. In order to persist data through a multi-step entry (edit, confirm, submit) cycle we marked our beans as `Serializable` and then used the `saveState` tag on the jsp page to serialize the bean's data between calls. I figured I'd throw it out there in the event you were using a similar mechanism in your 1.x pages. – axemoi Apr 10 '17 at 12:40
  • @axemoi So does that mean the application won't work under JSF2 until I get rid of all those `saveState` attributes? I somehow suspect that any changes in the sourcecode itself don't have much effect right now because somehow the correct template (`View.jsp` (not `Main.jsp` as I wrongly wrote in my last comment)) can't be found in the first place. Even deliberately adding syntactical errors to `View.jsp` does not have any effect on the error message I get. – scholt Apr 10 '17 at 12:55
  • My last comment isn't true, adding errors _does_ have an effect. Deliberately adding syntactical errors to `View.jsp` gives a different error message: _/pages/View.jsp (line: 100, column: 20) The end tag " – scholt Apr 10 '17 at 13:04
  • I can't say if it'll work, we pulled out myfaces so therefore we had no choice but to change all our beans. I've been assuming that View.jsp is your first page. If that's true then based on your description it sounds like it's failing on the restore view phase; namely it's not finding the view in the `ViewMap`. Wish I could help more, but I've listed the things I can recall from our upgrade process. – axemoi Apr 10 '17 at 13:05
  • @axemoi Thanks again for taking the time to give me advice. Yes, `View.jsp` is the first page. It does get rendered initially and contains a small login form. The error occurs when submitting the login form via a `commandButton`. The stack trace also explicetly tells me that the error occurs when the `RestoreViewExecutor` calls the `execute` method. So it really looks like the template/view is found for the inital rendering but not for subsequent (restoring) calls to that view. I'm mostly wondering if some behaviour specifically tied to this situation changed between JSF1.1 and JSF2.1. – scholt Apr 10 '17 at 13:11
  • Just for specificity, your template is found every time. The issue is that the view (component tree) isn't found during postback (commandButtons). This is behavior that's similar to what you'd find if the user's session had expired – axemoi Apr 10 '17 at 14:09
  • When setting the state saving method to client, the html hidden field javax.faces.ViewState should contain the whole serialized view state on browser page. Do you see it? – OTM Apr 10 '17 at 19:22
  • @OTM when setting `STATE_SAVING_METHOD` to `server`, the hidden ViewState input field has the value `rO0ABXQAATE=`, which I assume is just the identifier for the viewstate saved on the server, right? When setting the saving method to `client`, the field has a much longer value that won't fit into the character limits of this comment, starting with `rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJ1cQB+AAAAAAACc3IAO29yZy5hamF4NGpzZi5hcHBsaWNhdGlvbi5BamF4U3RhdGVNYW5hZ2VyJFRyZWVTdHJ1Y3R1cm...`. So, yes, it looks like the whole viewstate is properly saved in the client, doesn't it? – scholt Apr 11 '17 at 08:04
  • @scolt Yes, both are correct. It looks like the view state is indeed getting created fine. So, it leads to the conclusion that the issue is only on the restoring the view state. Can you please check the session timeout configuration as this error will be thrown when the session is expired also ? – OTM Apr 11 '17 at 16:48
  • @OTM the `session-timeout` in `web.xml` is set to 30, which I assume means "30 minutes"? – scholt Apr 11 '17 at 17:12
  • Yeah.. any specific error message on postback when the state saving is client ? – OTM Apr 11 '17 at 17:32
  • No, apart from the `ViewExpiredException` I don't get any other error message. The whole stacktrace remains the same, no matter if I set the saving to `client` or `server`. – scholt Apr 11 '17 at 18:28
  • Are you getting the javax.faces.ViewState in the request parameter map on submit ? – OTM Apr 11 '17 at 21:17
  • @OTM Thanks again for trying to help me, but trying to get MyFaces 2.1 to work has already led to so much frustration that I instead tried to update to MyFaces 2.2 today. This posed some other problems, too, but those proved to be me more manable than this `ViewExpiredException`. I finally got the application to work with MyFaces 2.2 and now can start work on JSP->Facelet transition and upgrading/replacing outdated taglibs! Thanks again for taking the time! :) – scholt Apr 12 '17 at 14:23
  • NP. That sounds good ! – OTM Apr 12 '17 at 16:09
  • Comments is not the right place for solutions. Please consider summarizing these comments into an answer. – Matt Apr 27 '17 at 12:21
  • @Matt using MyFaces 2.2 instead of 2.1 circumvents the problem and helps me in my situation, but it does not really answer my question. Should it still be formulated as an answer or should I delete the whole question? – scholt Apr 28 '17 at 08:50

0 Answers0