Persistant Page State and Page Pooling

The Home page of this application uses a persistant page property, a List that contains Doubles, the items in the list.

Persistent page state is one of the most important concepts in Tapestry. Each page in the application (and in fact, even components within the page) may have some properties that should persist between requests. This can be values such as the user's name and address, or (in this case) the list of numbers enterred so far.

In traditional JavaServer Pages or servlet applications, a good chunk of code must be written to manage this. The values must be encoded in cookies, as hidden form fields, as named attributes of the HttpSession, or stored into a server-side flat file or database. Each servlet (or JSP) is directly responsible for managing access to these values which leads to many half realized, ad- hoc solutions and an avalanche of bugs, and even security holes.

With Tapestry, the framework takes care of these persistence issues. When a persistent property of a page is changed the accessor method also invokes the method fireObservedChange(). This method informs a special object, the page's recorder, about the property and its new value.

When the page is next used, the value is restored automatically. This may not seem natural; an obvious question is: why wasn't the page in the same state? Then answer is that that page instance is shared, and may be used by a different client in the interrum.

Within the Tapestry framework, all of these pages, components, specifications and templates are converted into Java objects. Assembling a page is somewhat expensive: it involves reading all those specifications and templates , creating and initializating component objects, creating binding objects for the components, and organizing the components into a hierarchy.

Creating a page object for just one request cycle only to discard it is simply unacceptible. Pages should be kept around as long as they are needed; they should be re-used in subsequent request cycles, both for the same client session, or for other sessions.

The Tapestry framework accomplishes this by pooling instances of page objects; there could concievably be a handful of different instances being shared by thousands of client sessions. This is a kind of shell game that is important to maintain scalability.

What this means for the developer is some minor extra work. On each request cycle, a different instance of the page object may be used to handle the request. This means that data can't simply be stored in the instance variables of the page between request cycles.

Tapestry isolates the persistent state of a page from the actual page objects. The state is stored seperately, making use of the page recorder objects. When needed, a page can be created or reclaimed from the page pool and have all of its persistant properties set by the page recorder.

The developer has three responsibilities when coding a page with persistant state: