Creator of the Apache Tapestry web application framework and the Apache HiveMind dependency injection container. Howard has been an active member of the Java community since 1997. He specializes in all things Tapestry, including on-site Tapestry training and mentoring, but has lately been spreading out into fun new areas including functional programming (with Clojure), and NodeJS. Howard is a DZone MVB and is not an employee of DZone and has posted 80 posts at DZone. You can read more from them at their website. View Full User Profile

"Simple" JSF 2.0 Component vs. Tapestry

11.03.2008
| 17871 views |
  • submit to reddit

I just saw an amusing example of JSF 2.0 on Jim Driscoll's blog. He's creating a simple output-only component to display some text in yellow, using an inline CSS style. To make things 'simpler' (my quotes) he's using JSF.

Here's his JSF page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ez="http://java.sun.com/jsf/composite/simpleout">
<h:head>
    <title>Yellow Text Example</title>
</h:head>
<h:body>
        <h1>Editable Text Example</h1>
        <h:form id="form1">
                <ez:out value="Test Value"/>
            <p><h:commandButton value="reload"/></p>
            <h:messages/>
        </h:form>
</h:body>
</html>

Not too bad ... the relevant part is <ez:out value="Test Value">, that's the reference to his Out component inside his simpleout library. JSF puts a lot of interpretation into the namespace URLs.

On the other hand, the implementation of this simple component seems a bit out of hand:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:composite="http://java.sun.com/jsf/composite">
<head>
<title>This will not be present in rendered output</title>
</head>
<body>

<composite:interface name="yellowOut"
                     displayName="Very Basic Output Component"
                     preferred="true"
                     expert="false"
                     shortDescription="A basic example">
    <composite:attribute name="value" required="false"/>
</composite:interface>

<composite:implementation>
    <h:outputText value="#{compositeComponent.attrs.value}" style="background-color: yellow"/>
</composite:implementation>
</body>
</html>

You can kind of vaguely see, inside all that clutter, what the component is doing. I'm personally troubled by name="yellowOut" ... is the component's name "out" or "yellowOut"? Also, compared to the Tapestry version coming up, you can see that a few nods to visual builder tools are included.

So, what does the Tapestry equivalent look like?

Well, our page template would look something like*:

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
  <title>Yellow Text Example (Tapestry)</title>
</head>
<body>
  <h1>Yellow Text Example</h1>
  <t:form t:id="form1">
    <t:out value="Test Value"/>
   <p><input type="submit" value="reload"/></p>
  </t:form>
</body>
</html>

The Tapestry namespace identifies elements and attributes that are not truly HTML, but controlled by Tapestry. This includes built-in Tapestry components such as Form as well as user-defined components such as Out.

The Out component itself is in two parts: a Java class to define the parameters (and, in a real world example, provide other logic and properties) and a matching template to perform output**. First the class:

package org.example.myapp.components;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.annotations.*;

public class Out
{
  @Property
  @Parameter(defaultPrefix = BindingConstants.LITERAL)
  private String value;
}

The @Parameter annotation on the value field marks the field as a parameter. The defaultPrefix attribute is configured to indicate that, by default, the binding expression (the value attribute inside the page template) should be interpreted as a literal string (as opposed to the normal default, a property expression).

The @Property annotation directs Tapestry to provide a getter and setter method for the field, so that it can be accessed from the template.

<span style="background-color: yellow">${value}</span>

Again, this is a trivial example. We didn't even have to define the Tapestry namespace for this template. The ${value} is an expansion which outputs the value property of the Out component instance, which itself is the literal string ("Test Value") bound to the Out component's value parameter.

Let's add a little improvement: If the value is null or empty, don't even render the <span> tag. This is accomplished in one of two ways.

First, we can change the template slightly, to turn the <span> tag into an If component that renders a span tag:

<span t:type="if" t:test="value" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" style="background-color: yellow;">${value}</span>

The If component evaluates its test parameter and if true, renders its tag (the <span> in this case), its non-Tapestry attributes (style) and its body (${value}).

Alternately, we can leave the template alone and abort the component's render in the Java class:

  boolean beforeRenderTemplate()
  {
    return ! (value == null || value.equals(""));  
  }

This is a Tapestry render phase method, a kind of optional callback method that can control how the component is rendered. We return true to render normally, and false to skip the template rendering. Tapestry invokes this method at the right time based on a naming convention, though an annotation can be used if that is more to your taste.

This is a good example of how Tapestry really cuts to the chase relative to other frameworks. Both the usage of the component and its definition are simple, concise and readable. Further, Tapestry components can scale up nicely, adding sub-components in the template, and more properties and logic in the Java class. Finally, we can also see a hint of how Tapestry relieves you of a lot of low-level drudgery, such as using the @Property annotation rather than writing those methods by hand (Tapestry has a wide ranging set of such meta-programming tools built in).

* I'm not sure why the original version used a form, but I've dutifully recreated that here.

** For a component this simple I'd normally not bother with a template and do it all in code.

 

From http://tapestryjava.blogspot.com/
Published at DZone with permission of Howard Lewis Ship, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Otengi Miloskov replied on Mon, 2008/11/03 - 5:33am

Tapestry 5 is awesome. Tapestry 5 with Spring 2.5 and Hibernate makes the perfect combo. This should be the standard stack web framework for Java.

vincent cobra replied on Mon, 2008/11/03 - 7:30am

Tapestry5 looks awesome. I've been looking at it for the last 4 years but never had the chance to use it in production. Time to time I visit the Tapestry blog and the Tapestry5 website, and I like what I see. Next time, I'll think about Wicket, I'll give another try to Tapestry first.

Tapestry5 is a great improvement avor previous versions and it's easier to get started with. I see more people using Tapestry and Wicket in the entreprise, at some places where you would expect to see some Struts 1.x or Struts 2.x fanatics(no offense).

Many people now wonder what to use Wicket, Tapestry, JSF, Seam, Stripes, etc. My opinions are biased, but the only solutions I consider for non trivial applications are Tapestry and Wicket nowadays, maybe JBoss Seam later using Wicket or Tacos integration.

My experiences with Struts x.x(cough) and JSF(cough, cough) were not good even if the project was considered a success. You build an application that you don't feel or want to maintain as soon as it's in production.

GWT looks cool but is not a solution for typical web applications(no integration of lots of legacy code or services). You want the desktop look and feel and behaviour, but you pay the price that some might not be aware of(RPC for non trivial tasks, limited set of Java packages provided by the JRE emulation, and so on...).

 Keep up the good work, nice effort for Tapestry5 by the way.

Alex Objelean replied on Mon, 2008/11/03 - 7:25am in response to: Otengi Miloskov

I didn't found Tapestry 5 to be such a awesome as you say. It is still beta, it lacks good documentation, it's ajax implementation doesn't allow multiple ajax updates. I would recommend you to try wicket instead.

vincent cobra replied on Mon, 2008/11/03 - 7:35am

As you say Tapestry is still beta but yet it looks promising and far from being usable. I only had good experiences with Wicket(All my last projects were written with it). Trying out Tapestry and give feedback can only make it better for the stable release, if it makes sense to some people to try out beta frameworks.

Jose Maria Arranz replied on Mon, 2008/11/03 - 10:14am

ItsNat alternative (AJAX based or classic navigation):

HTML:

<html> <head></head>

 <body>

<h1>Yellow Text Example</h1>  

<span id="out">Test Value</span>

<p><input type="submit" value="reload"/></p> 

</body>

 </html>

Java:

ItsNatHTMLDocument itsNatDoc = ...;

HTMLDocument doc = itsNatDoc.getHTMLDocument();

Element outElem = doc.getElementById("out");

Text text = (Text)outElem.getFirstChild();

text.setData("New Value");

outElem.setAttribute("style","color:yellow");

 

Bruno Borges replied on Mon, 2008/11/03 - 3:07pm

And this is how it looks like with Apache Wicket:
public class YellowLabel extends Label { public YellowLabel(String id, String value) { super(id, value); add(new AttributeAppender("style", new Model("color:yellow"), " ")); }
And to use it:
HTML: #span wicket:id="label"# Text goes here #/span# Java: add(new YellowLabel("label", user.getName()));
:-)
Bruno Borges

Fab Mars replied on Tue, 2008/11/04 - 12:42pm

Yes Tapestry looks cool.

I don't really see the point in comparingXML and Java code tough. We all know that the once-praised XML documents are well known for taking more chars than the use of a couple of annotations.

Tell me, these annotations, aren't they substitutes for some...code ? I hope these annotations would allow to solve all the cases of component creations. Plain html components are something. Components with lots of Ajax/JS are something else. Well, imo this is not comparable. Maybe it's time for JSF people to create a set of annotations though.

 But, is it REALLY important that a component takes more or less lines ot code? We're using a set of ready to use components with JSF (RichFaces or Tomahawk or ADF will make your day). In my whole JSF experience I was forced to create only TWO JSF components (besides facelets compositions). And I didn't think it was that hard even in JSF 1.2. Writing a few lines more or less hasn't much impacted on our planning in the end.

 

Anyway, sure there are superb newer frameworks. Everyone's also talking about Wicket, just as everyone was talkign abouot JSF 4 years ago. Who knows what will happen within the next 4 years? Anyway there are new ideas, concepts, simplifications, with all these frameworks and this is great! Let's just admit every of these framemworks has advantages and limitations and only real projects can enlighten them correctly. Imo it's just unfair to always focus on the weak ponts of the 'other' frameworks than the one you support.

Howard Lewis Ship replied on Tue, 2008/11/04 - 3:24pm

I see component creation as something you do frequently in a project, to avoid ugly repetition or intra-application inconsistency.  In T5, it's the kind of thing you crank out all the time, because it's usually just a line or two of Java code.

Creating reusable components is something you do a bit less often, but is still a snap. Most commonly, I like to encapsulate custom JavaScript/Ajax inside components.

 At the core of this discussion is a question of agility.  I strongly feel Tapestry leads in this respect, due to the simplicity and conciseness of the template, coupled with other features of the framework:

  • No base classes to get in the way of testing (a problem in T4 eliminated in T5)
  • Excellent, excellent exception reporting with an emphasis on messages describing how to fix the problem
  • Live class reloading, so you can make changes and see the result instantly

 

 

Ivan Lazarte replied on Wed, 2008/11/05 - 2:58pm

Tapestry 5 looks great but I refuse to check it out until it has the courage to release.  I'm kinda sick of JSF at this point and welcome something a lot closer to the html.  If it's true you can't fire off multiple async requests then that kinda sucks and would probably be showstopper for me; one of the reasons I like how T5 looks is that it seems closer to the HTML/CSS which I'm pretty sure is the direction I want to move in (at least for my personal projects).

Howard Lewis Ship replied on Wed, 2008/11/05 - 4:18pm

Ivan, can you wait a few more days :-)  Trust me, I'm quite courageous ... but an RC is going to set a lot of APIs in stone forever, and it would be nice to make them "just right". I'm finishing up final bugs fixes and trying to address documentation issues. 

Kito Mann replied on Sat, 2008/11/08 - 8:33pm

Ivan,

I just wanted to point out that with Facelets (and consequently) JSF 2, you have full support for HTML-style templates, similar to what Tapestry offers. The example referenced in this article refers to the standard tag-based syntax.

---

Kito D. Mann -- Author, JavaServer Faces in Action
http://twitter.com/kito99
http://www.virtua.com - JSF/Java EE consulting, training, and mentoring
http://www.JSFCentral.com - JavaServer Faces FAQ, news, and info

Public JSF Course in NYC: http://www.regonline.com/jsf-course
 

Kenneth Wheeler replied on Fri, 2009/11/20 - 4:38am

I agree with what you said about "Simple" JSF 2.0 Component vs. Tapestry . Get Tall "Simple" JSF 2.0 Component vs. Tapestry . How to Grow Taller Naturally "Simple" JSF 2.0 Component vs. Tapestry . Growing Taller Secrets

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.