Thursday, October 14, 2010

Context and Tapestry 5 compared

This article compares Tapestry 5 to Context. I have chosen Tapestry for the comparison, because I have some experience in it and to me it is a kind of benchmark on modern component based frameworks on Java-world. You may have a different opinion of course.

On the side note, comparison between Context and Wicket might also have been interesting, but since I have no experience in Wicket I am not able to do it.

In overall these two frameworks have very different approaches. Where Tapestry focuses on page pooling and page component reuse, Context chooses an approach where page component are not reused at all.

I would also like to note that this comparison is limited and it is not to start flame war. I try to be objective, however my opinion is of course biased and favors Context.

So, let's begin with similarities:

Dependency injection


Tapestry has it's own dependency mechanism and Context is using Guice. They both have about same power, although I have a feeling that Guice is more flexible than Tapesty IoC. This leads to similar kind of design choices for service layer components and they will probably look about the same.

Next, the differences, and the are a lot of them

Page component handling


Context is taking an approach where, for each new page request, a set of brand new components are created. When the page is closed, those components are thrown away.

In tapestry, very little is "wasted" and page components are reused as much as possible. Now, I do not know what kind of burden for Tapestry it is to create new page components, but I feel it a kind of unnecessary, because in real life applications maybe hundreds of objects are created per request anyway. Just think about how many objects is needed to create a single call through Hibernate, when it actually returns something.

In Context the page components live as long as the page is visible and for page updates there is no need to create new objects. They are reused. This leads to another difference.

Page statefulness


When I began creating Context, I had a very clear vision about that pages should be stateful. And I mean each single page instance should have its own state. I understand that it fights against REST-kind of thinking and so on, but I found it very necessary. This means that each page has a transparent state, that can be used just like that.

This approach has many advantages.

Browser tabs

One thing that has been bothering with other component based frameworks is that they do not play well with browser tabs. Think about a page that is counting how many times a button is pressed in that current page.

If that page is opened in two browser tabs and the count is stored in session, you may end up having a very strange looking behavior if that button is pressed in different browser tabs.

Information hiding

Think about a page that is making a question which is dynamically generated for each page request. Where is the correct answer stored? If the page has no state, the correct answer need to be encoded to the HTML somehow, possibly revealing it. With Context, you can safely leave to answer to the server, and then simply check whether the answer was correct or not.

This can be useful also in situations where there exists an id or other kind of secret that should not revealed at any times. With Context it is easy to create a surrogate ids that are shown in HTML and can be matched to correct ids on server side.

Tapestry seems to have more limited choice of states. It basically has session context that can be used for more permanent storage or in Flash-mode where the object is stored for a short period of time. Tapestry also has a kind of page state, but that is encoded into URLs and forms. If feel that kind of clunky.

Page updates


Context is built from the ground up to be Ajaxed. There does not exist a fallback mode where Javascript is not needed. Tapestry on the other hand can be used via form submits and basic page updates that do not require Javascript. I have had some ideas how to mimic page update via post submits, but nothing concrete exists.

The interesting thing is the Ajax-side. How is that handled from developer perspective?

Tapestry has concept called Zone. Zone is normally a div-element with specific id. From the Java-code it is possible to access that zone and make an update to it. When a request is made a method, mapped in the template files, is called by Tapestry. Then that method must return the zone-access back to Tapestry so that it knows what to update.

How about if multiple zones need to be updated? Well then the page needs to create a multizone-update an gather all the zones that are needed and return them all.

The problem with that approach is that the page component needs to take care of all the updates, and I feel that it limits developer creativeness.

Context is taking a totally different approach. Components are independent. All that needs to be done is to register all components to the page context, which is in most cases done transparently, and then call its refresh()-method. The underlying framework will do the rest.

The preferred way is even to do so that the refresh()-method is not called externally at all. I mean, why should other component be responsible for knowing when the component needs to be refreshed? You simply call some method on the component that has an effect to its state, and then the component can choose itself, whether to refresh or not. Maybe the data was invalid or null and refresh is not needed.

With Context it is easy to create page wide components that can be called from every single other component and ask it do to something.

A very good example can be seen on Context-homepage. On the right hand side there exists a link "Show page comments". If you add a new comment in the opened component, you will get a feedback saying "Thank you for your page comment". That Feedback-component can be called from any other component on the page and simply ask "Please, show this message to the user". The caller does not have to know how it is really done. Also doing the Feedback-component took only about a half an hour to do. And even then most of the time I used trying too make it look good with css and graphics.

At the moment, I do not have enough experience to know how the page comment feature could be done with Tapestry so I can not say whether it is difficult or not.

But, this is enough for now. Maybe later I will continue this comparison. Thank you for reading this blog post.

- Marko Lavikainen

No comments:

Post a Comment