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!

Monday, July 24, 2006

Tapestry 5 Updates

Even during OSCON, I've been churning out code for Tapestry 5.

The new Tapestry IoC container is rapidly coming together. The idea of replacing XML with Java classes (and naming conventions and annotations) is working out wonderfully. I'm busy putting together a version of configurations about now.

What I'm finding, as I code and also predict how the final Tapestry code will use the container, is some steep improvements.

In Tapestry IoC, injection isn't into your beans via property setters or constructors, the way it is in HiveMind and Spring. Instead, injection is via parameters to your builder methods. Injection via method parameters will also occur into decorator methods (the replacement for service interceptor factories) and into contribution methods (which contribute values into service configurations).

For example, in Tapestry IoC:

package org.example.myapp.services;

import org.apache.tapestry.ioc.annotations.Id;

@Id("myapp")
public class MyAppModule
{
  public Indexer buildIndexer()
  {
    return new IndexerImpl();
  }
}
The above defines a service "myapp.Indexer" as an instance of IndexerImpl. The equivalent in HiveMind would be :
<module id="myapp" version="1.0.0" package="org.example.myapp.services">
  <service-point id="Indexer">
    <create-instance class="IndexerImpl"/>
  </service-point>
</module>
That's already an improvement. By the time you start talking about dependencies, things get even better:
  public Indexer buildIndexer(String serviceId, Log serviceLog, 
    @InjectService("JobScheduler") JobScheduler scheduler, 
    @InjectService("FileSystem") FileSystem fileSystem)
  {
    IndexerImpl indexer = new IndexerImpl(serviceLog, fileSystem);
      
    scheduler.scheduleDailyJob(serviceId, indexer);

    return indexer;
  }

What's worthy of note here is how dependencies get injected in (as method parameters), and that lifecycle concerns about the IndexerImpl are separate from its implementation. We don't have to inject the scheduler into IndexerImpl in order for the Indexer to be scheduled by the scheduler ... that concern can be implemented only in the builder method.

To accomplish that kind of separation in either HiveMind or Spring would require quite a bit of hackery; say, creating a new, specialized kind of ServiceImplementationFactory (in HiveMind) that understood about talking to the scheduler. Lots of work for something that can be expressed so easily in a short, simple, testable Java method.

I think that we'll see this approach bear fruit in the form of fewer services to accomplish the same goals. It will allow for non-service objects to easily receive injected services ... such objects can be created "on the side" by builder methods (or contributor methods).

This is the theme for all of Tapestry 5: Simpler, easier, faster, more understandable, more powerful. Avoid XML. Improve productivity. Make the framework adapt to your classes and your methods, rather than the other way around.

22 comments:

Anonymous said...

Could you please give some example of the contribution methods? I'm interested in it.

Assume the service will be reused by two applications. In first application it will have some property value 8. In second application it will have property value of 9. How does the service (and its builder) look like? And how do the two applications contribute the values?

Anonymous said...

Howard, I'm glad you're making good progress on Tapestry 5. But, as it happens, there's no concrete tool support for T5 planned. And even today there's almost none for T4.

Do you know what this means in the eyes of a 300k+ employees corporation... ? No tooling, no adoption.

That's not my personal opinion, but that's how it is. And my heart bleeds...

Anonymous said...

Any ballpark estimate on when Tapestry 5 will be out? ;-)

Sounds like nice improvements (especially speed). I hate ripping up applications to port between Tapestry major revs though :-P

Howard said...

Tapestry 5 is too formative now to set an end date. All kinds of factors, including any consulting engagements I take over the next months, can affect how much time I can work on it. It will hopefully soon reach a state where others can help fill it out, but right now too much of the design exists only in my head.

In terms of tooling ... there's two responses to that.

1) If you build it they will come.

2) Who needs tooling?

I'm sorry that my response is so glib. I've never been too concerned with tooling, and Tapestry 1 - 4 was not built with tooling in mind. Tapestry 5 is a whole different story, but even more so than Tapestry 4, tooling will not be necessary.

I expect to have a true preview mode in Tapestry 5.

I will certainly have a much better productivity story, including automatic class reloading for pages and components.


As a reminder: Rails, the biggest success story I can name, has no tooling at all. Tooling is no replacement for productivity.

Anonymous said...

Howard,why not use javacc to analysis the html template?

Anonymous said...

Can tapestry core only have interfaces and extensions.Then we can contribute some plugins,the plugin can be descripted with annotations

Eric said...

Hi Howard,

Do you plan to release your IoC container independently of Tapestry? Maybe as a replacement for Hivemind?

As I can see right now in the packages names, it is subordinate to Tapestry, at least for the Id annotation declaration,...

Eric said...

Hi Howard,

Do you plan to release Tapestry's IoC container as an independant project? Or maybe an evolution for Hivemind ?

As far as I can see, from the packages names, it is right now subordinated to Tapestry.

Anonymous said...

Hi Howard

Why reinvent the wheel? There is HiveMind, the Pico container and the Nano container. Why not adopt one of those to allow your developers to reuse the knowledge they acquired?

Reinventing critical parts of Tapestry means we're constantly learning a new framework, there is no accumulation of knowledge in the public domain, ie, forums, tutorials and homepages.

I would like to leave this link as food for thought:
http://www.artima.com/forums/flat.jsp?forum=276&thread=169588

Howard said...

The online docs for Tapestry 5 include a discussion of why there's a need for a new IoC container.

It wasn't an easy decision.

It is the right decision.

I think HiveMind will evolve to match Tapestry 5 IoC in many ways, but legacy support for HiveMind will be nearly as crippling as legacy support for Tapestry 4. Again, people with an investment in Spring or HiveMind will find it even easier to bridge from Tapestry IoC to other containers. Unlike the Spring/HiveMind divide, the Tapestry IoC container is compellingly different, and superior, from a programming model.

Henrik Vendelbo said...

I think it's an admirable decision to restructure Tap5 that way. I just hope that you maintain the support for .page files, and perhaps even extend their features.

The ability to tailor an application without changing any code is one of the top pro's of Tapestry imo.

Howard said...

I'm not ruling out 100% external configuration files. But they'll only go in if there is utility to it. The reality is that the XML files are expected to be used only by Java developers ... why not let them accomplish the same thing in Java code, rather than in an XML file? Given that Tapestry 5 will pick up such changes as easily as HTML or XML file changes in Tapestry 4 (in fact, far more efficiently and performantly), there is not as compelling a reason to keep these seperate, and there's big advantages, in terms of organization and productivity, to keeping it all one place.

Anonymous said...

Wishlist for T5:

- Get rid of all the XML and use Java instead. Nice to see that you're aiming for that.

- Make pages/components more similar to services:
* contructor injection and autowiring
* no need for inheritance
* no abstract classes
Instead of using abstract properties, reset all properties by default when the page is returned to the pool. If someone wants a property to be persistent, they can use some annotation to keep it from being reset.

- Better documentation

- Integrate something like Trails CRUD functionality - it's gonna impress potential new users.

Anonymous said...

I have had a hard time doing test-driven development with tapestry in the past, particularly when trying to confirm that the rendered html was correct. Will T5 improve testability? I would love to see some examples of test-driven applications and test driven components.

Anonymous said...

This IoC approach for Tapestry seems well thought-out. With services performing on a generally atomic level, I envision application pages/components being extensions of the Tapestry core (with all the goodies of decorators, additional services, etc. being injected as needed). Perhaps the module id's for pages could serve as default directory mappings????

With this in mind, I have reservations about module builders classes wrt app pages. Will this require explicit & separate builder methods for each page/component in a given application/library?

Howard said...

One of the challenges of open source software is that so much of it is public before it is fully baked. On top of that is my own lack of discipline, in that I like to talk about interesting things I've accomplished moments after I create them. Perhaps from a marketting perspective, it's good in terms of keeping interest in Tapestry 5 up long before its ready for adoption, though the down side is I'm already hearing grumblings from people who are nervous about the upgrade or otherwise feel I'm stealing Tapestry 4's thunder.

That being said, Tapestry 5 will in many ways be similar to Tapestry 4.

As with Tapestry 4, Services and Pages/Components are distinct in Tapestry 5.

The IoC container will provide the hidden machinery that instruments raw classes and later instantiates them, as well as manages page instance pools.

Unlike, say, Wicket, Tapestry 5 will continue the tradition of managing the lifecycle of pages and components, rather than putting that in user code.

Unlike Tapestry 4, all that occurs "on the other side of the fence", inside the invisible Tapestry internals, rather than in inherited methods from a base class. Tapestry 5 maintains a very clear separation between the public APIs (mostly annotations) and the internals (which are always in package named internal).

Howard said...

Testing

Tapestry 5 will be much easier to unit test.

The page and component classes (really, the exact same thing) will be pure POJOs. No abstract trickery of any kind.

I have some rough ideas for a kind of "Component Testbench" that would allow you to validate how a component renders. We'll see if that can come together.

Beyond unit testing, the story doesn't change much between Tapestry 4 and 5. You'll likely use Selenium, or something similar, to integration test the entire application. I often create test pages to test complex components outside the context of the application logic.

Please take Tapestry 5 design decisions to the developer mailing list. This is not a satisfactory forum for discussions.

Jan de Jonge said...

Howard,

I've followed your disscusions about Tapestry 5 very closely and see a couple of limitations and pitfalls. I'm waiting until you release the sources. I would then grab it, refactor it and make an even better framework out of it. Could you please tell me when the sources would go public?

Jan

Anonymous said...

No Howard, your response to tooling was too glib...
http://www.jroller.com/page/glongman/20060826

Now even that tiny hope has gone. It's a pity you're not looking even a single second beyond your own nose.
You're leaving us with 0 arguments to feed the managers of the world. That's why T won't get the propaganda it deserves, and why some day soon it will dissapear in the history sink. I'll start familiarizing myself with JSF, when that crappy Struts 1.01 (!) application I was assigned to leaves me some spare time...

End Of Communication

Josh said...

Hi Howard, I'm a HUGE fan of Tapestry and want to reiterate what a wonderful job you and the team you've built have done.

But...when you say the lifecycle of the components will continue to be managed, does that mean there will be no faculty for instantiating a component dynamically through code? For example, tapestry doesn't provide a mutable component hierarchy -- individual nodes are modifiable, but not the tree itself.. This makes any kind of page with content not known initially or (if nothing else, not loaded initially, as might be te case with a gui that has many navigation cases like say an ajax-heavy page) very difficult. Either way, best of luck and congratulations on yet another milestone!

*AnGeLo* said...

It's just me that dont like the @Id annotation?

Id is so general name. "Id of what"? EJB3? Hibernate? Tapestry? Of course in the first 2 the @Id is in the field or method level annotation , but i see in the near future a lot of frameworks with he ows @Id annotation make us developers confuse!!!

I just dont like the @Name of the Seam ("@Name for what?" another developer how don't kwon Seam ask for me)...

Anonymous said...

Will Tapestry 5 have something similar like Spring Webflow and AOP/AspectJ stuff? If yes, we would not have to use Spring at all.