Your browser may have trouble rendering this page. See supported browsers for more information.

|<<>>|237 of 273 Show listMobile Mode

Pitfall in the @For component in Tapestry

Published by marco on

This article was originally published on the Encodo Blogs. Browse on over to see more!


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 abstract; 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 @For component requires a source list and an iteration value from that list.

The declaration in HTML looks like this:

  <tr jwcid="@For" 
       source="ognl:DataObjectList" 
       value="ognl:DataObject"
       element="tr">
    <td>
      <span jwcid="@Insert" value="ognl:DataObject.Name">Name</span>
    </td>
  </tr> 

That is, the component iterates the list returned from getDataObjectList() (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 DataObject 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:

public abstract class EditorPage extends BasePage {
  public abstract IDataObject getDataObject();
  public abstract List<DataObject> getDataObjectList();
}

Tapestry will automatically implement appropriate getters, setters and initializers according to the declarations. However, executing the code above results in the following error message:

Unable to read OGNL expression ‘<parsed OGNL expression>’ of $[Generated page class name]: source is null for getProperty(null, “Name”)

What happened? A quick check in the debugger indicates that the list is assigned, contains elements and none of them are null. So why isn’t DataObject assigned? If you look more carefully at the declarations in the page class, you’ll see that although getDataObjectList() returns a list of DataObjects, getDataObject() returns an [I]DataObject.

Tapestry correctly generated getters and settings for these methods, but failed to raise an error when the @For component tried to assign a DataObject from the list to the property of type IDataObject. Instead it silently left it null and the page crashed later with the wrong error message.