This page shows the source for this entry, with WebCore formatting language tags and attributes highlighted.

Title

Pitfall in the <c>@For</c> component in Tapestry

Description

<n>This article was originally published on the <a href="http://blogs.encodo.ch/news/view_article.php?id=6"><b>Encodo Blogs</b></a>. Browse on over to see more!</n> <hr> Any properties used from a Tapestry template have to be declared in the corresponding Java page class. It is highly recommended to declare these properties as <c>abstract</c>; Tapestry implements them for you, automatically including code that re-initializes each property automatically when a page is re-used from the cache. If you implement the properties yourself in the customary Java getter/setter way, it is up to you to clear them in order to ensure that users can't see one another's data. That said, there are a few bumps in Tapestry's current implementation. For example, the <c>@For</c> component requires a source list and an iteration value from that list. The declaration in HTML looks like this: <code> <tr jwcid="@For" source="ognl:DataObjectList" value="ognl:DataObject" element="tr"> <td> Name </td> </tr> </code> That is, the component iterates the list returned from <c>getDataObjectList()</c> (Tapestry automatically chops off the "get" part when searching for a method) and iterates it, executing the body of the loop for each value. For each iteration, it assigns the current value to the <c>DataObject</c> property, which refers to the iteration element in the body of the loop. The example above prints the name of each data object in the list. The page class in Java looks like this: <code><b>public abstract class</b> EditorPage <b>extends</b> BasePage { <b>public abstract</b> IDataObject getDataObject(); <b>public abstract</b> List<dataobject> getDataObjectList(); }</code> Tapestry will automatically implement appropriate getters, setters and initializers according to the declarations. However, executing the code above results in the following error message: <bq class="error" quote_style="none">Unable to read OGNL expression '<parsed>' of $[Generated page class name]: source is null for getProperty(null, "Name")</bq> What happened? A quick check in the debugger indicates that the list is assigned, contains elements and none of them are <c>null</c>. So why isn't <c>DataObject</c> assigned? If you look more carefully at the declarations in the page class, you'll see that although <c>getDataObjectList()</c> returns a list of <c>DataObjects</c>, <c>getDataObject()</c> returns an <c>[I]DataObject</c>. Tapestry correctly generated getters and settings for these methods, but failed to raise an error when the <c>@For</c> component tried to assign a <c>DataObject</c> from the list to the property of type <c>IDataObject</c>. Instead it silently left it <c>null</c> and the page crashed later with the wrong error message.