JavaBeans Properties

For Tapestry, the central concept for JavaBeans are properties. The JavaBeans framework allows Tapestry to treat any object as a collection of named properties. Tapestry frequently reads, and occasionally writes, values from or to these named properties.

A property is not the same as an attribute ... though, most often, each property is backed up by an attribute. To Tapestry, and the Reflection API, a property is a set of public methods on the object. Accessing a property involves invoking one of these methods.

Example 2.1. JavaBeans getter method

public type getName()
{
  ...
}

Example 2.2. JavaBeans setter method

public void setName(type value)
{
  ...
}

A property may be read-only or write-only (that is, it may implement just one of the two methods). The type may be a scalar type (boolean, int, etc.) or any Java class.

Note the naming; the first letter of the property name is capitalized after get or set. JavaBeans properties are case sensitive with respect to the method names and the property names. A special case exists when the name is an acronyn; this is recognized by two or more upper-case letters in a row (after get or set); in this case, the property name does not have the first letter convert to lower-case.

As a special case, a boolean property may use an alternate name for the getter method:

Example 2.3. JavaBeans getter method (boolean)

public boolean isName()
{
  ...
}

Although the normal implementation is to get or set an instance variable, more complicated options are possible. One pattern is lazy evaluation, where an expensive calculation is put off until the actual value is needed, for example:

Example 2.4. Lazy evaulation of JavaBeans property


public List userNames = null;

/**
 *  Returns a List of user names obtained from the database.
 *
 **/

public List getUserNames()
{
  if (userNames == null)
    userNames = fetchUserNamesFromDatabase();

  return userNames;
}

Here, the first time the method is invoked, the expensive database fetch occurs. The value returned from the database is then cached for later invocations.

Another common pattern is a synthesized property. Here, there is no real attribute at all, the value is always computed on the fly. A frequent use of this is to avoid tripping over null pointers.

Example 2.5. Synthesized JavaBeans Property

/**
 *  Returns the name of the company's account representative, if
 *  if the company has one, or null otherwise.
 *
 **/

public String getAccountRepName()
{
  AccountRep rep = company.getAccountRep();

  if (rep == null)
    return null;
  
  return rep.getName();
}

This example creates a synthetic property, accountRepName.