Hi,
Based on some of the queries that we are getting and the experience that we have gained inhouse, I have started writing this list of common Tapestry pitfalls. I am hoping that it would come handy to newbies who are trying to get to grips with the framework.
Problem: Use of 'in' bindings in a Direct listener
Symptom: The binding does not have the expected value when required, but rather the value it has been initialized to.
Description: Bindings of type 'in' are initialized at the beginning of the render cycle. There are a number of events that occur in the component before that, specifically the listeners invoked by a Direct link. If you need to use those bindings before that, either make them of type 'custom' (see docs pls) or use getBinding("...").getObject() (or another binding method) to get the binding value. Please keep in mind that Forms use the Direct service by default, rather than the Action service. Hence, the above applies fully to listeners invoked by a form, such as formSubmit() for example.
Problem: Not resetting persistent, transient, or dynamic properties at page detach
Symptom: If two users connect simultaneously, the second sees the page state of the first (sessions get intermixed).
Description: ALL properties that change during the request within the page/component must be reset to their default values at page detach to ensure that a new request would start from a "clean state". This is necessary, because requests from different sessions may use the same page/component object (all such objects are pooled). Please note that requests from the same session would have the page's persistent properties restored at the beginning of the request (see docs on fireObservedChange()), so this reset does not lead to loss of information from their point of view. In order to reset the properties, use detach() or initialize() in a page. In a component, you need to subscribe as a PageDetachListener to the page in finishLoad(), and reset the values in pageDetach() (this may get simplified soon).
Problem: Different property intialization at page construction and page detachment.
Symptom: The page works if run without caching (the development mode), but fails at the second or later render when run without caching (the default mode).
Description: There are two distinct places where the properties of a page may be initialized (see above) -- the bean constructor and the detach() method. That initialization must be identical -- there should not be a difference between a newly created instance and one taken from the pool. To avoid differencies between those two initializations, it is best to use a single method that is called from both places. AbstractPage provides the protected initialize() method that is called from both the constructor and detach() with this goal in mind. For those reasons, it is the best place for initializing the page properties. A similar approach should be used in components as well.
Problem: Resetting of 'custom' bindings in detach()/initialize()
Symptom: Null pointer exception (NPE) when the same page is rendered more than once with caching enabled.
Description: Custom bindings are typically contained in properties with names 'propertyBinding' with accessors setPropertyBinding() and getPropertyBinding(). Those binding properties MUST NOT be reinitialized in detach() similarly to other properties. They are set only once at page loading and remain constant for the full lifetime of the page.
There are obviously a number of others, but I need to finish for now. Please feel free to add -- I think it would be a good idea to have a library of those in the documentation. May be move this to the Wiki (when it comes up?)
Best regards,
-mb
Do you Yahoo!?
Yahoo! Web Hosting - Let the expert host your site
