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

Reply via email to