You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Cherry Development <av...@cherrydev.com> on 2003/11/13 10:24:50 UTC
(LONG) Over-persistent/Under-persistent pages
***PRE-AMBLE***
This is a long post. It will probably be of most interest to those who
have used other web development frameworks most similar to WebObjects
in the past. Without any doubt, all of the problems I'm having I could
work around by fundamentally shifting the way that I build web
applications to explicitly store more state inside my Visit. I feel,
though, that information specific to the interaction between two pages
should not be stored there, but only information specific to the user
session as a whole. I am, without a doubt, trying to use Tapestry in a
manner that is not common. I'd like to think, though, that by
discussing the problems I'm having in the context of HOW I am trying to
use Tapestry, more flexible ways of using it can be found.
******
I feel like I must be terribly confused about something...
I have a page with a persistent property on it that gets altered when
the page is rendered.
If I move to another page, then move back to that first page, I get an
error:
Page recorder for page <...> is locked after a commit(), but received a
change to property <...> of component <...>
Now, I've done my reading on how page recorders work and I understand
when an error of this kind SHOULD happen.
But after figuring out why it's happening me, I've now come to the
realization that I might not understand at all how pages with
persistent properties are supposed to be used.
What I assumed was, more or less, that if a page with persistent
properties was not used in subsequent requests, the page no longer
'held on' to those properties, even when used in the same session. I
assumed that if you wanted to hang on to that particular state to
perhaps use again, get a reference to its page recorder and use it to
rollback() the page when you need it like that again.
What I realized in the investigation of this problem, though, is that
within a session, there can really only be one 'virtual' instance of
that page. What I mean by a 'virtual' instance is an
instance+pageRecorder. Each page basically becomes a singleton within
the scope of a session. Also, if you want to make changes to the page
after its been used once, you have to explicitly unlock the page
recorder.
As I've mentioned before, I came to Tapestry from writing WebObjects
applications. If you wanted a page, you'd instantiate one. There was
no concept of persistent properties as they are in Tapestry. If you
wanted to hang on to the state of that page to use it again in a later
request, you simply made a reference to the page and later fed it to
the cycle when you wanted to use it again, since it wouldn't be changed
unless it became involved in a cycle.
I guess what I want is something in between Tapestry's not-persistent
properties, and its fully-persistent properties. I want properties
that will stick around to be used in an action listener with that page
(not necessarily dynamic ones involved in a rewind) but I don't want
them there the next time I do a cycle.getPage() or use a PageLink.
Example:
I have two pages.
One lists a bunch of items in a foreach and has action links on these
items to do various things. Say one of these things would potentially
delete the object. Call this page A.
I have a confirmation page. It is meant to be generic, not tied to a
particular use. Call it page C. I have a special action listener that
is created with parameters naming the page that called it, the state of
the page when it was called, and the name of a callback listener to
invoke if the user clicks the 'Confirm' button. Call this action
listener L. This action listener gets the confirmation page and sets
it up, storing this information in persistent properties.
The user clicks the 'confirm' button, and the 'confirm' action listener
on looks up the page that called C (A), restores its state to what it
was when L was called and invokes the callback that was specified.
At least this is what I thought should happen originally. As I'm sure
any Tapestry vet would know, there's no need to store the state of A as
it was when it calls L, so long as the relevant properties are marked
as persistent. Ahh, but as you'll remember, I used a foreach to
identify which 'delete' button had been clicked on. These means that
the most important property (the one referencing which item was
'current' when the delete button was clicked) was a so-called 'dynamic'
property. One whos value changes during page rendering. A dynamic
property cannot be persistent because the next time the page gets
rendered, the page recorder will prevent it from being changed, and
give me the error I got above.
A bizarre, but possibly useful way I think of to get around this is as
follows:
Do not make the dynamic property in the foreach persistent.
Have the listener L serialize the state of page A when it is called
(when the dynamic property is still set to the 'correct' value) and
save it. When we want to return to the page to make the callback,
deserialize the page and feed it to the cycle. We've now effectively
cloned the page. Will it get properly returned to the page pool (and
possibly culled) at the end of the cycle? Looks like this wouldn't
work, since a cycle only cleans up after pages that it, itself loaded.
Another, more general tactic:
Allow an instance of a page to be detached from the pool. It no longer
gets re-set to its 'pristine' state and will not be returned to the
pool at the end of a cycle. It could be tucked away inside of an
action listener, or in the visit, wherever you want it, and could later
be fed back to a Cycle to be rendered. Therefore, an action listener
could notify the cycle somehow that it wants exclusive access to a page
and its exact state and beyond that point, the cycle wouldn't touch it,
nor return it to the page pool.
A peak at the source code shows that this could perhaps be easily done
with a change to RequestCycle. Urg. Okay, _loadedPages is a private
Map, so I can't access it from a subclass without using nasty, nasty
reflection tricks. Maybe I'll try this out, though. Give my modified
sub-class an orphanPage(IPage page) method.
If you've read this far, I thank you. :) You now share my bumpy
learning experience. If you have questions as to why I wish to go
about things in the manner I've written of, please ask and I'll do my
best to try to explain them. Perhaps I may discover a new methodology
that seems as natural to me as the one I currently use. Maybe
vice-versa.
Thanks,
Avi
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
Re: (LONG) Over-persistent/Under-persistent pages
Posted by "Ido M. Tamir" <ta...@imp.univie.ac.at>.
On Thursday 13 Nov 2003 10:24 am, Cherry Development wrote:
> ***PRE-AMBLE***
> This is a long post.
to long for me, I hope I understood something from your problem
maybe the threads:
page vs. visit?
and
(newb) how NOT to persist TextField value?
are of help.
best wishes
Ido
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org