Upgrading from Tapestry 3.0
Jakarta > Tapestry
Jakarta
 
Font size:      

Upgrading from Tapestry 3.0

One goal of Tapestry 4.0 is to make upgrading from release 3.0 as painless as possible.

Tapestry 4.0 still supports the Tapestry 3.0 DTDs (with minor exceptions).

Defining Engine Services

Tapestry 3.0 allowed engine services to be defined in the application specification using a <service> element. This is no longer supported in the 4.0 DTD.

Engine services are now defined using HiveMind, in the tapestry.services.ApplicationServices configuration point.

The <service> element in a Tapestry 3.0 DTD is now ignored.

The IEngineService interface has changed in non-backwards compatible ways. If your application created custom engine services, you will have to make changes to your code.

Component Parameters

Tapestry 4.0 has greatly streamlined component parameters.

Parameter Type

In Tapestry 3.0, the <parameter> element included a type attribute. This has been removed in Tapestry 4.0.

The parameter type is now determined from the Java class, by examining the accessor methods for the property.

Tapestry 3.0 required an exact match on values bound to parameters. The bound value had to be assignable to the parameter's type. In Tapestry 4.0, parameters include built-in coercion; Tapestry will attempt to coerce the value extracted from the bound property into the correct type. This is especially useful when using literal bindings for numeric properties. For example, an HTML template may specify a numeric value to an attribute as a simple string:

  <span jwcid="@MyComponent" intParam="50"/>

The type of the parameter is determined from the accessor method:

public abstract class MyComponent . . .

  public abstact int getIntParam();

Tapestry will convert the string value to an integer automatically.

The coercion rules are driven by a number of configuration points and services, starting with the tapestry.coerce.ValueConverter service.

Parameter Direction

In Tapestry 3.0, it was necessary to inform Tapestry of how and when a component parameter property was accessed -- this was parameter direction. Parameter direction is now ignored; Tapestry 4.0 now generates smart, caching accessor methods for parameter properties that work properly in all cases. In effect, all parameters are now of direction auto (but its a smarter, more flexible version of direction auto than was available in Tapestry 3.0).

This may be of concern if your component used the custom parameter direction. In Tapestry 3.0, direction custom meant that your code would directly access the IBinding object for the parameter, and no property for the parameter would be created. In Tapestry 4.0, a property will be created ... even if you continue to use the 3.0 DTD and specify direction custom.

Warning
You should search for all component parameters that use direction custom and update the Java class.

For example, if you had a Tapestry 3.0 specification for a listener parameter:

  <parameter name="listener" direction="custom" type="org.apache.tapestry.IActionListener"/>  

Then your 3.0 source code might look like:

  public abstract IBinding getListenerBinding();
  
  public void someMethod(. . .)
  {
    IBinding binding = getListenerBinding();
    
    if (binding != null)
    {
      IActionListener listener = (IActionListener) binding.getObject("listener", IActionListener.class);
      
      if (listener != null)
        listener.actionTriggered(this, cycle);
    }
    
    . . .      

In Tapestry 4.0, the specification is much simpler:

  <parameter name="listener"/>

As is the Java code:

  public abstract IActionListener getListener();
  
  public void someMethod(. . .)
  {
    IActionListener listener = getListener();
    
    if (listener != null)
      listener.actionTriggered(this, cycle);
  }
  
  . . .

Tapestry takes care of de-referencing the binding (if the parameter is bound), along with type checks or coercions.

Accessing binding objects

In Tapestry 3.0, it was possible to access a IBinding object for a parameter by defining an additional property in your component's Java code:

  public abstract IBinding getListenerBinding();

This is no longer supported; the correct way to obtain a binding object is via the getBinding() method.

Note
Because of the other improvements to parameters, it is virtually never necessary to obtain a binding object.

Default value

In the Tapestry 3.0 DTD, the optional default-value attribute was used to provide an OGNL expression to use for a parameter, if the parameter is not otherwise bound. In the Tapestry 4.0 DTD, the default-value attribute is a binding reference. The following are equivalent:

  <parameter name="foo" type="int" default-value="bar.baz"/>  <!-- 3.0 -->
  
  <parameter name="foo" default-value="ognl:bar.baz"/>        <!-- 4.0 -->

The advantage in 4.0 is that it is easier to specify simple strings as defaults; it is also possible to use other binding prefixes (such as message:, or a user-supplied prefix).

Inherited binding

Tapestry 3.0 included an <inherited-binding> element, this was a way to directly pass the IBinding object for a component parameter to a parameter of a nested component. This is no longer supported in Tapestry 4.0; instead, the property for the component parameter should be bound to the nested component parameter:


  <!-- 3.0 -->
  
  <parameter name="itemCount" type="int"/>

  <component id="nested" type="Nested">
    <inherited-binding name="count" parameter-name="itemCount"/>
  </component>
  
  <!-- 4.0 -->
  
  <parameter name="itemCount"/>
  
  <component id="nested" type="Nested">
    <binding name="count" value="ognl:itemCount"/>
  </component>

Specified Properties

Property specifications in Tapestry 4.0 have been simplified. The specification element has changed from <property-specification> to the simpler, <property>.

In Tapestry 3.0, it was necessary to specify the type of the property; this is no longer necessary or possible. The type attribute has been removed, and the type is determined from the Java code (and defaults to Object if the Java code does not define abstract accessors).

In addition, any abstract properties in the Java code will be converted into transient properties, even if there is no matching <parameter> element. Typically, the <property> element is only used when the property is either not referenced inside Java code (such as a listener method), or when when the property must be persistent.

In the 3.0 DTDs, properties could have an initial value set. The initial-value attribute was an OGNL expression used to initial the property when the page is first constructed, and when the page is detached (at the end of a request cycle). The initial value may instead be specified as the enclosed character data of the <property-specification> element.

Using the 4.0 DTDs, this is still true, but the initial-value attribute (or the enclosed character data) is a binding reference. To get the same behavior as the 3.0 DTD, it must be prefixed with "ognl:".

Managed beans

The <bean> element is used to define managed beans. In Tapestry 3.0, it could contain <set-property> and <set-message-property> elements to configure the properties of the bean.

In Tapestry 4.0, these two elements have been replaced by the <set> element, which uses a binding reference to provide the value.

Abstract classes

In Tapestry 3.0, it was rare, put possible, for your page and component classes to be concrete (not abstract). In Tapestry 4.0, that is no longer possible ... base classes such as BasePage are themselves abstract because key properties, such as messages are now injected into the classes, rather than inherited from base classes.

On upgrading from 3.0 to 4.0 and recompiling, you may see errors about "having to provide an implementation for method ..."; simply add the abstract keyword to your classes. They will work at runtime.