Hi Andrej, On Wed, 2009-01-28 at 19:36 +0100, Andrej Konkow wrote: > Hi all, > > I have following problem: > I have a jsf-page using a simple requestscoped backingbean, without any > customcomponents etc.. > I am using t:saveState to keep data between the requests. > The backingbean is inheriting from a common base class in which a > HtmlInputDate is being used for an attributetype. > Everything is working fine as long as I have defined the following in my > web.xml: > > <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name> > <param-value>false</param-value> > > When changing this config to "true" I get the following: > > [2009-01-26 20:14:25,968] [http-8080-2] [ERROR] > javax.faces.webapp._ErrorPageWriter - An exception occurred > javax.faces.FacesException: java.io.NotSerializableException: > org.apache.myfaces.custom.date.HtmlInputDate > > I'm not quite sure whether this is a bug or a feature but I was not aware > that backingbeans should implement the Stateholder-interface... > I had a short discussion in: > https://issues.apache.org/jira/browse/MYFACES-2141 >
No, backing beans do not need to implement StateHolder. That is necessary if you create a custom component (which is what I thought you were doing because I didn't read your problem description carefully enough). What you need to do in your case is declare the member you store the component-binding in as "transient". Then when the view is serialized and the backing bean gets serialized with it (because of t:saveState), the java standard serialization does not try to serialize the non-serializable member. When the view is restored on the next postback jsf will reinitialize the binding value so marking this member as transient should be all that you need. Unfortunately in this case, it means modifying the "common base class" you are inheriting from; hope you can do that. If you cannot do that, then you might have to customize the serialization process (create a writeObject method or similar) to first set the binding to null before invoking normal serialization. Effectively you are breaking the rule that "bindings should only be to request-scoped beans" by using t:saveState which makes the bean scope something longer than just "request". Nulling out the binding before serializing the bean fixes this.. > Could anybody please bring light into my thoughts? :-) > > The reason for me to try this change was that pages that work fine in a > normal clickflow throw an exception > when waiting, let's say 90 min. > javax.servlet.ServletException /jsp/app/time/projecttimes.jsfNo saved view > state could be found for the view identifier: /jsp/app/time/projecttimes.jsf Unfortunately, I don't think that using t:saveState will help you here anyway. The problem looks like the http session is timing out (90 minutes) so when the postback occurs, the old saved view is gone. Putting your backing bean into the saved view won't change anything; when the session goes and therefore the saved view is gone, you will always get this error message. This SERIALIZE_STATE_IN_SESSION flag just controls whether the data stored in the session is "compressed" (serialized) or not. Leaving this at the default value (true) is good because it also tests at the end of each request that the view state *can* be serialized. Http-sessions can be serialized in a number of situations: * servlet engines can flush them to disk when memory is low * clustered servers need to serialize sessions to transfer them between machines in the cluster * server hot-restart feature serializes sessions on stop and deserializes them on restart. If you set SERIALIZE_STATE_IN_SESSION to false, then the app appears to work until you try to do one of the above. Then you get a big surprise. It is better to have this set to true so that the program tells you about potential problems earlier. What I often do is embed a simple piece of javascript into pages which sends a "ping" request to the server every minute or so. Then http sessions will never time out while the browser is open. The http-session timeout can then be set to a nice low value, like 10 minutes, which helps ensure that memory is cleaned up when people really do leave the site. Or you could use client-side state saving. Then if the session times out, it doesn't matter (as long as you have no other important data in the session) because the saved view tree (including your bean because of t:saveState) is part of the data posted by the client. Regards, Simon