Creating custom components with Tapestry 5
August 27th, 2007 by Michael Sparer | Published in Tapestry
As far as I’m concerned, I consider creating custom, reusable components as the supreme discipline of every web-framework. I remember fiddling about a custom tabbed panel in JSF some years ago … those were the days when it wasn’t easy to find JSF third-party components. I also remember that it took me ages to add some sort of AJAX behaviour, and I can’t really remember if I finally succeeded
But times have changed, creating custom components is part of every almost every framework’s ref-docs and it is … or should be … easy to create them. Ideally just with combining already existing components to new ones.
As already mentioned in my previous post, I’m playing around with Tapestry 5 these days. So I decided to create my own component, a guestbook component. The guestbook should be as generic as possible, meaning that all kinds of Java beans should be valid entries. I.e. you should not be dependent on some fixed values such as name, e-mail and the message … well that really called for a BeanEditForm to enter the values … and I thought about using some kind of Grid to display the guestbook entries.
As a complete newbie in creating tapestry components, the first way to go was the Tapestry wiki’s howto page for T5. There, Eric Vullings’s short introduction about creating custom components merely gave me a quick overview over the rendering phases to override/implement when creating a component.
Then I took a cursory glance at the BeanEditForm’s and Grid’s source code to see how the components work and how they could be extended/used for my custom guestbook component. I quickly realised that it takes a bit more than a cursory glance to get the hang of the Grid (including the GridRows, GridColumns and GridPager components) but it needs less effort to figure out how the BeanEditForm works.
I decided to take the BeanEditForm straight away as part of my component and to adapt some of the Grid’s functionality to display the entries. I soon found myself copying most of the Grid’s code …. that was the right time to stop and to think about my approach once again. I was already down in adding my own coercer to the AppModule which was a lot of fun but nevertheless copying code can’t be the solution
.
So I (ab)used the Grid for my custom needs. To keep it short (sorry for those of you who didn’t get in touch with the Grid so far
), I let my Guestbook implement the GridModelProvider interface, subclassed GridRows in order to be able to use the a different template-html without losing the GridRows’s functionality and did the same with the GridPager component.
There it was, the Guestbook – a BeanEditForm above with GridRows and a GridPager below. All it needed now was to override the onSubmit method (or to use the @OnEvent(value = “submit”) annotation) to do with the new entry whatever I wanted.
But after all, it just didn’t feel right to abuse the Grid and to call that my “custom component”. I think I’ll never use it in a real-life application, but I got a good insight into how components work in Tapestry5 by playing with those two. Here my two pennies worth on the whole stuff:
The ‘mighty’ components in Tapestry5 seem to be hard to extend – maybe it is better to use them as they are, without trying to combine them to form a new component (which might be what the developers wanted). I believe that it wouldn’t be too difficult to create mighty components on your own, if you already created some small components. There were two little things I noticed during dealing with the GridPager component:
- The GridPager component shouldn’t be limited to the Grid. In its current state it requires a GridDataSource object, which actually is the only link to the Grid. Basically it’s just a matter of a different naming. Thus creating a super-interface of GridDataSource (e.g. DataSource with the method getNrOfItems():int) would make the GridPager reusable for other components without having the Grid-stuff in it.
- The CSS-class shouldn’t be hard-coded. Overriding the css would be a possibility, but it would look much neater to pass it as a parameter.
Well, that’s all for today. I’d love to hear about your experience with creating your custom components. So if you have something to say, or questions, just leave a comment below!
Unfortunately I did not find the time to look a bit more into Maven. Now even Tapestry creator Howard Lewis Ship swears like a trooper in his recent blog entry
. I’ll definitely have to take a more thorough look into Maven …