Tapestry: first experiences

Together with Fidel, Caimito's new hire in Panama, I started to experiment with the component-based web framework Tapestry. We were inspired by Brian Sam-Bodden's book Beginning POJOs and Brian's personal recommendation of Tapestry.

There are two types of web frameworks: request-based and component-based.

Request-based frameworks like, Struts, WebWorks (now Struts 2), SpringMVC and others expose the HTTP request/response cycle directly and only map that to actions or controllers where you code something to do the work. These frameworks expect you to code the action and provide the view with some other technology. Common view technologies are JSP, Velocity, FreeMarker and others. These view technologies combine HTML tags from a template with values that are injected by the framework and carry your output information.

Component-based frameworks don't expose the HTTP request/response cycle and they don't use a separate view technology. Instead they let you create your application in Java without thinking too much about the web. Sun's JSF (Java Server Faces), Apache MyFaces (an implementation of JSF) and Tapestry are component-based frameworks.

Everything is a component

With Tapestry everything is a component starting with the web page itself. Instead of a lot of XML files Tapestry 4.1 comes with annotation support. Add an extension to support Acegi Security and you can use the following code to create a secured page accessible by authenticated users with the role ROLE_USER only. The HTML comes from a file SomePage.html.

@org.acegisecurity.annotation.Secured("ROLE_USER")
public abstract class SomePage extends BasePage {
}

Links

If you want to link to SomePage, you write:

<a href="#" jwcid="@PageLink" page="SomePage">Some page</a>

Form handling

Let's say you want to code a page with a search form. You create an HTML template called Find.html (formatting details omitted for clarity):

<form jwcid="form@Form" listener="listener:doSumit">
<input jwcid="search@TextField"	value="ognl:idNumber"/>
<input type="submit" jwcid="@Submit" value="ognl:messages.getMessage('submit')"/>
</form>

Tapestry makes use of the fact that web browsers ignore tags and attributes they don't know. jwcid is used to refer to a component and the other non-HTML attributes are passed on to the component referred to by jwcid. This template creates a form with an text input field and a submit button. Further you can see Tapestry's support for internationalization. ognl:messages.getMessage('submit') reads the value for the submit key from a Java resource bundle. So you can create properties files Find.properties (default), Find_es.properties and Find_de.properties to support English (en) and Spanish (es) specifically and leave everything to the values in the default file Find.properties. Quite easy - isn't it?

Next is the code for the Find page:

@org.acegisecurity.annotation.Secured("ROLE_USER")
public abstract class Find extends BasePage implements PageBeginRenderListener {

	public abstract void setIdNumber(String idNumber);
	public abstract String getIdNumber();

	@InjectPage("EditUserStory")
	public abstract EditUserStory getEditUserStory();

	@InjectPage("UserStoryDoNotExist")
	public abstract UserStoryDoNotExist getUserStoryDoNotExist();

	@InjectObject("spring:repository")
	public abstract FileBasedIssueRepository getFileBasedIssueRepository();

[...]
	public IPage doSubmit() {
		if (getIdNumber() != null) {
			Long id = Long.parseLong(getIdNumber());
			UserStory userStory = getFileBasedIssueRepository().find(id);

			if (userStory != null) {
				EditUserStory editUserStory = getEditUserStory();
				editUserStory.setUserStory(userStory);
				return editUserStory;
			}
		}
		return getUserStoryDoNotExist();
	}
}

The @InjectPage annotation lets the Find class know about other pages. With @InjectObject you can inject into your class references to HiveMind services. Tapestry 4.x uses HiveMind and IoC container. With @InjectObject("spring:repository") we inject a Spring bean called repository. So you can see there is an easy way to combine Tapestry and Spring although Tapestry doesn't use Spring.

Further down in the doSubmit method the return value represents the page Tapestry should show to the user. To us as Java developers this is just a page object and has nothing to do with any kind of HTTP redirect. That's nice, because we can stay within the world we know.

Learning curve

One might expect that Tapestry's learning curve is high. But to my surprise it isn't. Fidel had never worked on a web application, but has worked on Swing applications before. It took him 3 days to set up his work environment (Eclipse, Maven), read about Tapestry, check out the samples from Tapestry's tutorial. After that warmup he got productive and created a useable application with business logic and even some nice design in CSS within a week.

So in my conclusion Tapestry is a very productive framework. Of course there is more to explore. On the 3rd day we started to explore how to create custom components and in that area is most of the stuff to learn more about.



Re: Tapestry: first experiences

Nice little write up, glad you guys are getting productive. Just want to remind everyone that Tapestry 5 will be ready for primetime fairly soon. It won't have all the whizbang Ajax features of 4.1 but it does have a simpler coding model, and a lot more power under the hood. &amp;amp;nbsp;

Re: Tapestry: first experiences

Thank you Howard. We've been looking into Tapestry 5 already and even thought about switching to it this week.

Re: Tapestry: first experiences

Also, try:

<pre class="codeSample"><input type="submit&amp;amp;quot; jwcid=&amp;amp;quot;@Submit&amp;amp;quot; value=&amp;amp;quot;message:submit&amp;amp;quot;/> Easier to read, more efficient at runtime.

Re: Tapestry: first experiences

Yes, <input type="submit" jwcid="@Submit" action="listener:doSave" value="message:submit" /> is easier. Thanks

Re: Tapestry: first experiences

My team is also evaluating component-based frameworks. We have a pilot project that uses Apache Wicket. &amp;amp;nbsp; The Wicket community has been growing but it is still smaller than the Tapestry community.&amp;amp;nbsp; It will be interesting to watch these two frameworks evolve.&amp;amp;nbsp; One of the reasons I like Wicket and Tapestry is that both frameworks have first-class Ajax support. Its nice to have first-class Ajax components.

 

Re: Tapestry: first experiences

Excuse me, but i wouldn't say that the Tapestry framework is a 3-day learn. Actually, I strongly disagree with that.

Tapestry include many new concepts compared to some 'classic' web development technologies like plain PHP/ASP coding, even compared to fully OO ASP.Net web development, so there's a need for a 'mind switch'. On the other side, exploring the Tapestry framework itself and the possibilities it offers is a progressive work that takes weeks. After that, there's the custom components development, their templates vs. renderers, then connecting it all together, assets, scripts, etc.

And, for a beginner, some real-life code examples would be helpful, which the official documentation lacks (only some of basic concepts are explained). And there are not too much sources with examples and one needs to dig around the web a bit to find some resources to start with... I'd say that it's also important if you have someone to give you quality references to some good articles or books to start with.

But all that is worthy, in my opinion. After you find some examples and transform your way of thinking to this concept in web application development (i.e. get rid of the old habits with other web languages mentioned), Tapestry is a good and quality concept and also a well developed tool/API to do your job with. But needs months of discovering, learning and adopting all the concepts it offers, and often you find yourself realizing that you just discovered something new which can simplify the the code you wrote just a couple of weeks ago...

Re: Tapestry: first experiences

Tomislav, you are certainly right about the mind switch you mention. That's a challenge for many people. For Fidel it was probably a lot easier, because he had no prior exposure to PHP or Java request-based frameworks and someone (me) with long-term experience at his side.

Add a comment Send a TrackBack