Joshua Java

A glimpse of Wicket 1.4 and Tapestry 5

Posted on: September 11, 2008

It has been a long time since Struts first showed up and filled in the Java web framework space. Many people nowadays are still using Struts which mainly because of legacy and investments reasons. But more people are moving away towards component based frameworks these days. JSF has got to be the most popular component framework out there, considering it is supported by many vendors and being itself as a standard from JCP. I’m not going to talk about JSF nor the up and coming release of JSF 2.0, instead I’m going to write about the other two popular component based web framework fostered by Apache: Wicket and Tapestry 5

In the near future there will be two interesting component framework that will be released by Apache Foundation: Wicket 1.4 and Tapestry 5 which I will elaborate in a very short few moment. Alot of people out there are asking, which one is better out of these two? First of all, we need to be on the same platform before continuing any further. This blog entry is not intended to be a web framework bashing discussion, but just to give insights for people who are curious about the difference between these two frameworks. The features that I will discuss will only be limited to the usage of the two frameworks.

Build Tool

This might not be important for some people, but you might take it into consideration. Both frameworks uses maven as its build tool. Maven really helps your development stage especially when getting the latest release of the framework. This is extremely important considering both frameworks are in heavy development and they have SNAPSHOTS on the maven repository. Okay now that you know that both frameworks uses maven as its build tool, let’s get deeper and see how do we use these frameworks.

Configuration

Both frameworks believes that configurations should take small portion in xml, infact web.xml is the only xml file you will require to write down your configurations. You won’t find any other xml configuration for setting which page to render after one action is called, etc. Both frameworks took the same philosophy that web framework should be responsible for generating the URL and knowing which page to be rendered afterwards, instead of throwing the responsibility to the developers by telling them to configure it themselves on the xml configuration.

Wicket
Below are the configuration for setting up Wicket application inside web.xml

<web-app>
    <display-name>wicket</display-name>
	<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <filter>
        <filter-name>wicket</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
<param-name>applicationClassName</param-name>
<param-value>agilist.lab.WicketApplication</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>wicket</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

As I said, most of the configurations is located inside a Java class, which in this sample is named WicketApplication. WicketApplication is a Java class that defines your web application. What’s written here are your configurations regarding your web application. Some project might have several of these Java class differentiated by the filter mapping url pattern.

Here is a snippet of how your WicketApplication class would look like:

public class WicketApplication extends WebApplication{
	public WicketApplication(){}

    	public void init(){
        		super.init();
    	}

	public Class<HomePage> getHomePage() {
		return HomePage.class;
	}
}

WicketApplication extends itself from WebApplication which purpose is to serve pages over the HTTP protocol. The getHomePage() method is to return, sort of like index.html of that application.

Tapestry 5
Let’s take a look at Tapestry 5 configuration. The same as Wicket, web.xml is the only XML file that is needed for configuring your Tapestry 5 application.

<web-app>
    <display-name>tapestry5</display-name>
    <context-param>
<param-name>tapestry.app-package</param-name>
<param-value>agilist.lab</param-value>
    </context-param>
    <filter>
        <filter-name>app</filter-name>
        <filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>app</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

In web.xml you will tell tapestry where to find your pages, components and mixins by putting the tapestry.app-package configuration inside the context param element. With these configuration, all your pages, components and mixins would live under these packages:

  • Components: agilist.lab.components
  • Pages: agilist.lab.pages
  • Mixins: agilist.lab.mixins

Tapestry 5 also has a Java class for configuring your webapps, just like Wicket does. The class name is picked up from the filter name and then appended by Module. So based on our previous configuration the class name would be AppModule, and here is how AppModule would look like:

public class AppModule
{
    public static void bind(ServiceBinder binder)
    {
        binder.bind(Member.class);
    }

    public static void contributeApplicationDefaults(
            MappedConfiguration<String, String> configuration)
    {
        configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en");
        configuration.add(SymbolConstants.PRODUCTION_MODE, "false");
    }
}

This is as simple as it would get and I won’t go into much detail about the configuration here.

And basically that’s all there is to it about the configuration for the two frameworks. I think both framework did a great job regarding configuration. Though Tapestry 5 took it into another level where some of the configuration is based on convention. And of course by placing the configurations in Java file you won’t have to worry about type safety anymore.

Controller/Page Class

In Wicket and Tapestry, what you call as a controller in action based framework, is called as a Page class. Both Wicket and Tapestry 5 took the same approach that the corresponding Page class would live side by side under the same package with the template itself. So if I have an AddMemberPage.java, my template name would be AddMemberPage.html for Wicket and AddMemberPage.tml for Tapestry. Take a look at the project structure to get the idea what I’m talking about here. The templates detail will be explained later, and here’s how your Page class would look like:

Wicket
Here is how the project structure of Wicket would look like. Since Wicket is using maven, so it gets the main structure from maven.

Now let’s take a look at the Page class of Wicket:

public class AddMemberPage extends BasePage {
    private static final Logger logger = LoggerFactory.getLogger(AddMemberPage.class);

    private Member member;

    public AddMemberPage() {
        add(new AddMemberForm("addMemberForm", new CompoundPropertyModel( new Member() )));
    }

    public class AddMemberForm extends Form {
	public AddMemberForm(String id, final CompoundPropertyModel model) {
	    	super(id, model);

	    	member = (Member)model.getObject();

	        add(new TextField("name"));

	        add(new Button("save"){
			public void onSubmit(){
                    			logger.info("Member name: {}", member.getName());
	    	    	}
	        });
	 }
    }
}

And here is the BasePage class or known as the Parent class where it is used for templating which will be explained later.

public class BasePage extends WebPage{
    public BasePage() {
        add(new PageLink("homeLink", HomePage.class)
             .add(new Label("homeLabel", new ResourceModel("home"))));

        add(new BookmarkablePageLink("addMemberLink", AddMemberPage.class)
            .add( new Label("addMemberLabel", new ResourceModel( "member.add" ) ) )
        );
    }
}

WebPage is wicket’s base class that defines a web page. The subclass of WebPage simply returns the HTML page of corresponding class.

Tapestry 5
Here is how the project structure of Tapestry 5 would look like. Since Tapestry 5 is using maven, so it gets the main structure from maven.

Let’s take a look an inner depth of how would Tapestry 5 Page class would look like:

public class Add {
    @Inject private Logger logger;

    @Inject @Property @Parameter private Member member;

    void onSelectedFromSave(){
        logger.info("Member name: {}", member.getName());
    }
}

The same as wicket, you must also define a Layout class that will be used for templating as explained later. The difference from Wicket about templating in Tapestry 5 it took the notion of composition instead of inherintance. This is how your Layout class would look like:

public class Layout {
}

And because Layout will be used as a component, so this class must live under the components package. Unlike Wicket, in Tapestry 5 you don’t need to declare what component should be displayed in the template.

Wicket Page class is much longer than Tapestry 5, but once you get used to it, it’s quite fun. And if you have noticed, the Page class in Wicket looks like Swing controller. Swing programmers will find this programming style very amusing since it is quite similar so they won’t find any trouble since some of the components name are the same with AWT/Swing components. While Tapestry 5 approach are more like JSF style where there is a method for event handler for each component.

Templates

Templates in Wicket and Tapestry 5 are using plain HTML. You won’t require any special taglib to work on your templates. Web designer in your project will find this very entertaining, because you are not introducing anything new to them. To get the idea of how Wicket and Tapestry templates look like, Here are a a snapshot of a template of the two:

Wicket
Wicket took the notion of Page inheritance in templating. In wicket there will be a parent Page which will be the main or overall layouts that will be used/extended by many other child fragments. Here’s how it looks to get the overall idea of it:

<html>
<head>
</head>
<body>
<div  id="wrap">
<div id="header">
            <a  href="#" wicket:id="homeLink"><span wicket:id="homeLabel" /></a>
            <a href="#" wicket:id="addMemberLink"><span wicket:id="addMemberLabel" /></a></div>
<div  id="content">
            <wicket:child /></div>
<div  id="footer">
            Copyright</div>
</div>
</body>
</html>

This is the corresponding html layout of BasePage as I have told previously. In wicket, the templates will be inherited by other page known as the child page where it is marked with wicket:child.

Here is an example of the layout that is extended by this template, which is the AddMemberPage:

<html>
<head></head>
<body>
    <wicket:extend>
    <form wicket:id="addMemberForm">
<table>
<tr>
<td>Name</td>
<td><input type="text" wicket:id="name"/></td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="submit" wicket:id="save" /></td>
</tr>
</table>
</form>
    </wicket:extend>
</body>
</html>

Wicket components is marked by the wicket:id which is populated from Java source. If you see the previous point on the Page class, this is done via the add() method. The basically saying, that I would like to extend whatever is outside of this tag from my parent page. So as you can see, wicket:extend would strip out anything that is around it and only adds anything that is inside it to the parent page and wicket will insert a child artifact inside wicket:child. This is very helpful for web designer when they want to go prototyping the web page one-by-one.

Tapestry5
In Tapestry 5 templates are not inherited, but instead it is a composition. This is the main difference between Tapestry 5 and Wicket in the area of templating.
Here is how your layout would look like in Tapestry 5:

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
</head>
<body>
<div  id="wrap">
<div id="header">
            <a t:type="PageLink" page="home">${message:home}</a>
            <a t:type="PageLink" page="member/Add">${message:member.add}</a></div>
<div  id="content">
            <t:body /></div>
<div  id="footer">
            Copyright</div>
</div>
</body>
</html>

The t:body is used to identify where within a component’s template, its body (from the container’s template) is to be rendered. A page that would use this component as follow:

<t:layout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<table>
    <t:form>
<tr>
<td>Name</td>
<td><input t:type="TextField" t:id="name" t:size="30" t:value="prop:member.name"/></td>
</tr>
<tr>
<td></td>
<td><input t:type="Submit" t:id="save" value="save" /></td>
</tr>
</t:form></table>
</t:layout>

Spring integration

Integration with Spring is fairly easy both with Wicket and Tapestry. Spring integration is so seamless with these two frameworks.

Wicket
Let’s go back to the WicketApplication class again and let’s add one line inside the init() method for configuring Spring inside Wicket:

        addComponentInstantiationListener(new SpringComponentInjector(this));

Which will make it look like this:

public class WicketApplication extends WebApplication{
	public WicketApplication(){}

    	public void init(){
        		super.init();

		addComponentInstantiationListener(new SpringComponentInjector(this));
    	}

	public Class<HomePage> getHomePage() {
		return HomePage.class;
	}
}

Now we can use our Spring bean from inside our Page class by annotating it with @SpringBean as such:

public class AddMemberPage extends BasePage {
    private static final Logger logger = LoggerFactory.getLogger(AddMemberPage.class);

    private Member member;

    private @SpringBean MemberService service;

    public AddMemberPage() {
        add(new AddMemberForm("addMemberForm", new CompoundPropertyModel( new Member() )));
    }

    public class AddMemberForm extends Form {
	public AddMemberForm(String id, final CompoundPropertyModel model) {
	    	super(id, model);

	    	member = (Member)model.getObject();

	        add(new TextField("name"));

	        add(new Button("save"){
		public void onSubmit(){
                    		logger.info("Member name: {}", member.getName());
                    		service.add(member);
	    	    }
	        });
	}
     }
}

Tapestry 5
In Tapestry 5, Spring bean is recognized and can be called Seamlessly and Injected by Tapestry 5 IoC as if it is T5 component. To integrate Spring in T5, you would need to change one line from web.xml by changing the app filter to use TapestrySpringFilter like this:

 <filter>
    <filter-name>app</filter-name>
    <filter-class>org.apache.tapestry5.spring.TapestrySpringFilter</filter-class>
  </filter>

Now you can inject your Spring bean into your page class simply by using the @Inject annotation as such:

public class Add {
    @Inject private Logger logger;
    @Inject private MemberService service;

    @Inject @Property @Parameter private Member member;

    void onSelectedFromSave(){
        logger.info("Member name: {}", member.getName());
    }

}

The neat part is as I said before, T5 makes it as if Spring bean is its own component.

Page unit testing

Both in Wicket and Tapestry5 you unit test your page without requiring to start a servlet container.

Wicket
Unit testing your Page class in Wicket does not lock you into any specific testing framework, you can use both JUnit and TestNG without a problem because Wicket supply a helper class named WicketTester for Unit testing your Page class. In brief this is how your test class would look like:

public class TestHomePage extends TestCase
{
	private WicketTester tester;

	@Override
	public void setUp()
	{
		tester = new WicketTester(new WicketApplication());
	}

	public void testRenderMyPage()
	{
		//start and render the test page
		tester.startPage(HomePage.class);

		//assert rendered page class
		tester.assertRenderedPage(HomePage.class);
	}
}

Tapestry 5
Unit testing Page class and Component class in Tapestry also does not lock you into specific testing framework. In brief this is how your test class would look like:

public class MyTest extends Assert
{
    @Test
    public void test1()
    {
        String appPackage = "org.example.app";
        String appName = "LocaleApp";
        PageTester tester = new PageTester(appPackage, appName, "src/main/webapp");
        Document doc = tester.renderPage("MyPage");
        assertEquals(doc.getElementById("id1").getChildText(), "hello");
    }
}

So now that you get the very basic comparison and got the idea about the two frameworks. But as the title say, it’s just a glimpse of it for those who are curious about the difference between the two. So which one fits your style and your requirements better? From my own perspective, both of them is an awesome framework, they’re fun for working with and it’s a great choice to adopt either one for your next project. Again the question shouldn’t be which one is better, but which one suits your style best? The choice is in your hand.

Another question that popped into my head: “Shouldn’t these two frameworks merged like Struts and Webwork since both live under the same house (Apache) ?”. Anyway IMHO the whole point when choosing the framework out of these two is not a matter which one is better, but which one do you prefer more.

Related Post

14 Responses to "A glimpse of Wicket 1.4 and Tapestry 5"

Thanks for taking the time to write that article. Two things I’d like to react to…

* Using inheritance to do layout is just one option in Wicket. You can also use panels and borders – which is laying out through composition -, and combine these three options any way you like. See the template example in wicket-examples for a simple example that uses both markup inheritance and dynamically assigned panels.

* “Shouldn’t these two frameworks merged like Struts and Webwork since both live under the same house (Apache) ?”

Won’t happen :-). Even though both frameworks look somewhat similar on the surface, the basic assumptions are not compatible. The main difference is that Tapestry provides a declarative programming model, while Wicket provides an imperative programming model (stateful programing, just like regular Java programming). Strengths of Tapestry’s declarative model are it makes for shorter code and potentially better optimization. Strengths of Wicket’s model are more control and flexibility (e.g. if you need to work with dynamic component trees).

It’s good to have both alternatives out there for people to choose, and articles like this one hopefully helps people picking out what suits them.

One note:

private static final Logger logger = LoggerFactory.getLogger(Add.class);

shouldbe

@Inject
private final Logger logger;

Otherwise a nice comparison, as far as what it covers.

Wicket’s primary advantage would be in terms of dynamic component model which simplifies certain things, including Ajax operations.

Tapestry’s advantages would be scalability (less stored in the HttpSession) and productivity (due to live class reloading and other factors).

Thanks for doing this research!

In Tapestry5 don’t need get/set methods for member:

@Inject <- don’t need
@Parameter
@Property <- for auto generating get/set by tapestry
private Member member;

Yeah, as stated above, you should correct Form page to following, since it really shows how biolerplate code went away in version 5:

public class Add {
@Inject
private final Logger logger;

@Property @Parameter private Member member;

void onSelectedFromSave(){
logger.info(“Member name: {}”, member.getName());
}
}

You can test Click Framework (http://click.sourceforge.net/)

Please compare the ease of creating new components by modifying or assembling and connecting existing components.

Both frameworks are steaming piles of cow dung compared with Grails.

Oh look, it’s John, the 14 year old we have all been waiting for so eagerly to share his insights.

Nice comparison; thanks for writing this up.

We did a bakeoff between the two (well, Wicket 1.3 and Tap5) earlier this year, and ended up choosing Tapestry. The deal-breaker was the fact that Wicket required considerably more code-behind for each page, mostly due to the fact that you were laying out the nesting of a page’s components in that backing-code. You’d end up with the same page’s structure represented twice: once in the backing code and once in the template. With Tapestry 5, your page structure is by-and-large described in the template, with backing code simply tying the UI to your biz entities.

OTOH, the amount of ‘magic’ that Tapestry does for you can make your code a little mystifying to those not familiar with it; the code for a Wicket application is going to be easier for the uninitiated to understand. Once you know how the magic works, though, your productivity is greatly enhanced, and you end up with less code.

I love Tapestry 5 and I’m using it right now in a project but I’m getting little bit annoyed with lots of annotations in the POJO’s sometimes, Also sometimes I prefer Wicket but yeah the duplicate declaration of Wicket that have to mach the structure in the markup as in the code it is little bit verbose but not much, both frameworks are great, I use both of them.

All depends I think if you like more annotations Tapestry or if you prefer to use Java language constructions so Wicket. For both the IDE and Refactoring tools works good and the templates of both are also good both frameworks true separate coder and designer.

Both have great exception handling/errors reports. Both support EJB3/Seam,Guice, Spring and Tapestry 5 have own IoC.
Tapestry 5 support out of the box Hibernate but Wicket no, I think there is a project for it the databainder but I’m not sure if works, always I use Guice with Hibernate togther.

Mailing list and support both are great even sometimes I’m in both IRC channels asking questions and both are good.

Wicket got an Action book and I think 2 books more, Tapestry 5 not yet an Action book I would like to see one, there is one book for T5 by Alexander Kolesnikov and is pretty good but it doesnt cover the advance features.

Anyway, Congratulations to both Wicket and Tapestry teams for easy of use and great frameworks.

PS. John, grow up bro.

[…] Good comparison of Wicket 1.4 vs Trapetsy is  can be found in this Joshua’s blog article a glimpse of Wicket 1.4 and Tapestry 5… […]

A comment about Wicket and Grails. I was a strong Grails supporter before I found Wicket. Grails is a great integration platform of web technology. But for the front end part it basically builds on Spring MVC that is a good framework for the classic request-response model. The strength of Wicket lies in how it isolates the programmer from the request-reponse-session handling.
The result is that ypu can concentrate on the data you handle instead of when and how to pick up the right data for the specific part of a age for the specific user.
Programming in wicket is more like programming a java swing application.

Currently I’m using T5.1.0.5 it was great… but not all especially the Zone, Delegate with JQuery.

Maybe because it has no proper document on how to to this. That is the biggest problem of Tapestry.

But i still love T5, then im also planning to try wicket.
Maybe in wicket zone, delegate and jquery is very simple thing to do! I hope hehehehe….

good job.

But what, when I want to render   in label? Is that possible?

Leave a comment