Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Wednesday, June 15, 2005

Annotations + Bytecode Generation == Mixins

I'm beginning to use the new Tapestry annotations as part of my current paying gig and I'm very much liking what I see. Starting from the basic Tapestry assumption that classes are abstract and need to be extended at runtime to be concrete actually opens up a goodly number of new techniques.

For example, I have a series of pages that all help edit a large shared object, a RegistrationData instance, stored as an application state object.

Before annotations, I would have had to duplicate the following on each page's specification and Java source:

  <inject property="data" type="state" object="registration-data"/>

  public abstract RegistrationData getData();

But with annotations, the XML part goes away:

  @InjectState("registration-data")
  public abstract RegistrationData getData();

But does even this have to be inside my page class? I have a number of pages that all need the same injected state object, so I can put this into an interface:

public interface RegistrationWizardPage {

  @InjectState("registration-data")
  RegistrationData getData();
}

Now we're on to something; each page extends this interface (but is still abstract) and, in effect, this interface is acting as a mixin. Implementing the interface adds the abstract getData() method and annotation and, thanks to Tapestry's runtime bytecode enhancements, the implementation of getData().

In the past, I've talked about getting away from abstract classes in Tapestry. Now I'm not so sure; the combination of abstract classes and annotations seems awfully potent.

Side note: the Tapestry test suite is well over 1200 individual tests now.

No comments: