Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Monday, April 11, 2005

Property Persistence on the Client

Over the weekend, in between NoFluffJustStuff sessions, I was busy working on adding the 'client' strategy for persistent page properties. In Tapestry 3.0 and earlier, there was a single strategy: persistent page properties are stored into the HttpSession.

Starting in Picasso (4.0), you can specify that a persistent property is stored on the client instead of in the session (on the server). It looks like this:

<property name="foo" persist="client"/>

Once this is in place, and once a change occurs to the foo property, all links and forms in the application will generate additional query parameters (or hidden fields) to track the value of foo. Actually, it uses a single query parameter per page to store all client persisted properties on that page.

It may still need some tweaking; already I can see that the URLs can get very long, very quickly. For example, after setting a couple of properties on a couple of pages of the Workbench:

http://localhost:8080/Palette.direct?component=%24Border.pageLink&session=T&sp=SChart&
state:Fields=H4sIAAAAAAAAAFvzloG1XI6BgYGRgUE8OSczNa8kLDEnMyWxJDM%2FzzUvMSknNaW4iEEwK7E
sUS8nMS9dzyk%2FPyc1Me%2BsQlHD1Tm%2F3jExMEYxsJYl5pSmVhQwAADTbn6TTwAAAA%3D%3D&state:Pale
tte=H4sIAAAAAAAAAFvzloG1nJuBgYGRgYGlOL%2BopLiIQSe%2FKF0vsSAxOSNVrySxILW4pKhSLzk%2Fr6Qo
M0mvIDEntaQkVS8YqNY3PyW1qyv4%2BsQ1f%2FczMTBUFDEoImlNzs%2FNzc8r1stJzEvXS80rzdVzBRI%2FbV
d5bjYMq2JiYPRhYM30S8xNLWEQ8slKLEvUB6nUDwZak5duXVFQwsDq4%2Bjk6gMAGprRD6MAAAA%3D

Given the practical limit of 4000 characters in a URL (don't ask me for references on that), this could be a problem.

The strategies are defined by a configuration point which is, of course, extensible. I expect to add more strategies. For example, a strategy that stores data on the client only until the there is a server-side session, then stores data on the server instead. Or, with some minor tweaks to the APIs, a strategy that store persistent property data, but only inside forms, not inside link URLs.

Drew Davidson has kludged into Tapestry 3.0 some other lifecycle options; he has pages that keep their state as long as the direct service is used, but when the page service is used (to leave a group of related pages), the persistent state for those pages is discarded.

I've been thinking of another option, where different versions of a page's state are stored on the server, and a token comes up in the request to indicate which state is used. This could go a long way towards automatically handling the browser-back button problem ... browser back to an earlier state, and continue working from that state. Actually, properly handling the browser-back button (and perhaps that duplicate form submit scenario) may take a mix of techniques.

4 comments:

Jonathan Millett said...

Bravo! I've been thinking about this for six months, but couldn't do it myself :-)

Any thoughts on persisting client state in cookies? I can see some benefits: a) cleaner url b) separation of global vs page data c) shared state between all client frames/windows. It might be possible even to implement shared state between a group of pages that share common extra path info in the url.

+1 on the server token. It is the most powerful of all. Even though it requires a session, it would surely be useful in many cases.

Unknown said...

Cookies are another possibility. That wouldn't even require code changes; there's already notifications to the page recorders and from there to persistent property strategy services to do this kind of thing. The same technique (same code even) could be used. It would be wedded to the Servlet Tapestry, since Portlet API provides no access to read or update cookies.

That's the fun part of HiveMind; the configuration is open and we'll probably start seeing small plugin libraries to support this kind of thing.

Jeremy / 傑洛米 said...

This can be solved by "client:page" strategy in T4, but what's the equivalent implementation in T5?

Unknown said...

As of Tapestry 5.0.5, you can use "client" strategy (equivalent to T4's "client:app" strategy). Over time, we'll reintroduce the other variants.