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!

Tuesday, June 21, 2005

More Tapestry Annotations

Just added the @Component annotation, which works like the <component> element:

    @Component(type = "Conditional", bindings =
    { "condition=message", "element=div" })
    public abstract IComponent getIfMessage(); 

The syntax is definately one of those "lesser of many evils" decisions. Using an array of strings, rather than a series of @Binding elements, means a lot less typing. I actually did the @Binding route first and it was much more verbose and not any more readable.

With this, the XML is becoming increasingly vestigal. There are still a limited number of things that can be expressed in the XML that can't be done using annotations, including <meta>. In addition, line precise exception reporting is compromised by annotations ... there's no file and line data to report. I may have to kludge together something that simply identifies the class, with no line number information.

The test suite is up to 1298 unit tests.

Update: changed the syntax to name=binding reference.

Also, added a very nifty @Message annotation.


Jamie Orchard-Hays said...

What about using something like

{"condition:message", "element:div"}

for the bindings? This would be much more legible and less error-prone.

Howard said...

Hitting my limit for prefixes, i.e. condition:message is barely ok (but it starts getting confusing what the prefix means), condition:ognl:message is getting worse, condition:hivemind:service:foo.bar.Baz.

I did think about "condition=message" or "condition=ognl:message".

André said...

+1 for a=b

Jonas said...

Annotations are great and all, and annotating the abstract functions in classes that are dynamically extended by Tapestry anyway to eliminate XML makes a lot of sense (@Inject). But @Component feels "unclean" in that it now puts configuration data where it doesn't really belong.

Also it puts you in the awkward situation that you now have multiple ways of doing things which means that you

a) have to keep both up to date in future versions or risk breaking a lot of things

b) have to designate a preferred way, or you'll create lots of cunfusion for people who now don't know which way to go because they fear that one might not be around in the next version of Tapestry

c) It's not clear anymore where a component came from (which might at the least cause naming clashes if two components with the same name are defined). (but somehow in the age of AOP I seem to be the only one troubled by not knowing immediatly where something came from ;-) ).

I'd love to read what you think about this, not alone because I already sense growing confusion in the community on the tight integration of HiveMind and how significant investments in Tapestry 3 will port to Tapestry 4. It would be great if you could address this in a future blog.

PS: It might also be that I totally misunderstand what you're doing here and that I'm all wrong ;-)