That's an interesting interaction between @Persist and @InitialValue. After the loss of session, the instance variable should return to its true default, null (when there isn't an @InitialValue). I think I would need to see more of your code, to see where you are setting the value for the property. If you are doing so inside finishLoad() then the behavior is correct, but less than desirable (see Sam's notes about problems with mutable values). The documentation does state that setting an initial value inside finishLoad() causes the value to be retained (not, for example, copied), and this does cause hiccups with mutable values such as a Map. @InitialValue is different; as you saw, the binding reference is re-evaluated at the end of each request (which results in a new instance of the Map, which is what I believe you wanted).
On 12/7/06, Sam Gendler <[EMAIL PROTECTED]> wrote:
In general, however, you are advsied not to store mutable objects into the session. The mechanism used to persist into the session should be opaque to the programmer, and it is likely that a persistence mechanism will only actually store an object if it has changed since the last time it was stored. Admittedly, this will work just fine if you are running on a single host, but it isn't guaranteed to do so. As soon as you start distributing your sessions around a cluster, however, you will run into real difficulties, because changes to the session are only replicated if the reference to a persistent entity has changed. Since your reference is to a mutable object, it is possible to modify the object (by adding or removing a key or value) without modifying the reference to it. This would cause the map to fail to be propagated to the cluster. For session distribution, there is a nice fix for this problem you can use. There is an interface you can implement (the name of which escapes me) which will allow the session to ask the object whether it needs to be distributed. But there is also a base class you can extend called org.apache.tapestry.BaseSessionStoreOptimized. If you look at the javadoc for that object, you'll see the interface name I was speaking of. BaseSessionStoreOptimized provides a method you can call whenever you modify your mutable object which will cause the object to correctly notify the session manager that it needs to be redistributed. Now, I have absolutely no idea if the @Persist annotation is smart enough to check for the existence of the interface in question and test for modifications as appropriate, but it might be. But at least you now know why you should avoid mutable objects in the session. Maybe the tap devs can fix the annotation if it doesn't already do this. --sam On 12/7/06, Dan Adams <[EMAIL PROTECTED]> wrote: > So I added an @InitialValue which calls a method to create the initial > map and this seems to have fixed it. After reading the enhancement > source I found out something tricky about this. > > SpecifiedPropertyWorker.addReinitializer gets called if you don't set an > initial value and it basically does (for property 'foo'): > > in finishLoad(): > foo$default = foo; > > in pageDetached(): > foo = foo$default; > > now, in my class in finishLoad I was doing essentially: > foo = new HashMap(); > > So on the first call to the page this would set the default value of the > property to that specific object. So if you reset your session you would > get the same object back when it initialized it to the default value. > > However, when you use @InitialValue the enhancement adds the following: > > finishLoad(): > foo$initialValueBinding = foo$initialValueBinding.createBinding(this); > foo = (evaluate the binding); > > pageDetached(): > foo = (evaluate the binding); > > So it appears that if you are going to @Persist an object and need the > initial value to not be null you should be sure to use @InitialValue or > otherwise you could end up with some weirdness. In my case it works if > you test it naively but fortunately my test cases were robust enough to > catch it. > > On Thu, 2006-12-07 at 10:58 -0500, Dan Adams wrote: > > I need a sanity check. :) So I have the following map of maps which I > > need to persist in the user session: > > > > @Persist > > public abstract Map<String, Map<String, Object>> getPageParameters(); > > public abstract void setPageParameters(Map<String, Map<String, Object>> > > params); > > > > Everything seems to work fine except that if I clear my session by > > deleting my cookies and come back to the page getPageParameters() > > returns the same map rather than null. I mean, it should return null > > right? I'm running this in Jetty in case it matters. > > > -- > Dan Adams > Senior Software Engineer > Interactive Factory > 617.235.5857 > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
-- Howard M. Lewis Ship TWD Consulting, Inc. Independent J2EE / Open-Source Java Consultant Creator and PMC Chair, Apache Tapestry Creator, Apache HiveMind Professional Tapestry training, mentoring, support and project work. http://howardlewisship.com