Step-by-Step Jakarta Tapestry

http://articles.sitepoint.com/article/jakarta-tapestry

The Jakarta Tapestry framework is a hidden treasure of Java web development. It greatly simplifies the work of both web designers and developers. It offers significant convenience by transparently handling much of the boring "plumbing". It even changes the paradigm of web development (at least in terms of the presentation tier) to one that is more natural.

Yet Tapestry remains more or less unknown to a great majority of web developers, for numerous reasons. The most obvious is Tapestry's legendary "steep learning curve" which, in my opinion, is more myth than reality: Tapestry is in fact easier to learn and use than are many other frameworks. Yes, internally Tapestry is more complex than its predecessors, in the same way that a contemporary camcorder is much more complex than those mechanical devices that our grandfathers used to produce their amateur movies. But is a camcorder more difficult to use? No, it is much, much easier (believe me -- I've tried both types of devices).

All right, enough brainwashing, let's jump straight in! By the end of this tutorial, you'll be able to decide for yourself just how easy Tapestry is to use. We won't be creating the traditional 'Hello World' web application here -- that really would be too trivial with Tapestry. We'll start with something more realistic: a login form.

On our way to unraveling the wonders of Tapestry, we need to pass through a kind of purgatory -- the process of creating of a working, Tapestry-ready configuration on our computers. This is more or less standard practice for Java web development, so we'll make it as simple as possible.

If you've ever tried any kind of Java Web development -- using servlets, JSP or Struts -- chances are that you'll already have most of the necessary components on your machine. But if not, don't worry: we'll install everything very quickly and easily. In fact, the installation is mostly about downloading and unpacking ready-to-use pieces of software.

Requirements
We'll need the following:

 

It's now time to return to the first page, Login, and add functionality to its page class so that when the form is submitted, the second page (that we named Content) is shown.

Navigating From Page to Page

Our listener method onFormSubmit() is still empty. Let's add some code to it to display the second page. This can be done quite simply: we'll just ask Tapestry to show another page.

How do we ask Tapestry to do something for us from our code? We've got its representative, cycle (of type IRequestCycle ), which is passed as a parameter to our listener method. So let's just ask this cycle object to do the job for us. This is what our listener method in Home.java looks like:

public void onFormSubmit(IRequestCycle cycle) {    
 cycle.activate("Content");    
}

Let's see if it works. At the moment, we need to keep restarting Tomcat every time we make a change, in order to see the most recent version of our application. This is definitely not the most convenient thing to do, and there are easier ways to achieve the same result. However, we've had enough distractions already, so I'll leave you to research the alternatives. For the moment, let's press on.

Shut down Tomcat if it was running, then start it up again. Point your browser to http://localhost:8080/Login/app and you'll see our login form. Push the Let me in! button and you should see the second page as shown on Fig. 15.

1508_figure15
Figure 15. The Second Page is Displayed Without a User Name

Notice that no username is output. Well, I didn't ask you to enter a login or password into the login form! But even if I had done so, we didn't tell the second page in our listener method what information we were receiving from the user. Let's correct this.

Passing Parameters to the Second Page

I'll now show you a design pattern that's used often in Tapestry development to pass variables to another page: the "bucket brigade" pattern.

We'll do the following:

  1. Ask Tapestry to give us a reference to the next page that we want to display.

  2. Use setters on that page to assign values that we want to pass to the page's properties.

  3. Ask Tapestry to display the next page.

At this point you should understand one important thing: although the users of our web application think of the pages they're viewing as HTML that's being sent to their browsers, in reality (and as far as Tapestry is concerned), each page is a Java class -- a page class -- such as Home or Content. This class has many talents; the ability to send an HTML response is just one of them.

Our next page is called Content. So, if we wanted to declare a reference to the next page, it would look like this:

Content nextPage;

We can tell Tapestry: "Please give us a reference to an instance of a page class for the page named Content". Translated into Java, it would look like this:

Content nextPage = (Content) cycle.getPage("Content");

After receiving the reference, we can use it to invoke any setters that we have prepared in that next page. For example, if we had a username and password received from a user stored in uname and password variables, we could write this:

nextPage.setUname(uname);    
nextPage.setPassword(password);

We'll then ask Tapestry to show the next page:

cycle.activate(nextPage);

Our completed listener method looks like this:

public void onFormSubmit(IRequestCycle cycle) {    
 Content nextPage = (Content) cycle.getPage("Content");    
 nextPage.setUname(getUname());    
 nextPage.setPassword(getPassword());    
 cycle.activate(nextPage);    
}

Note that in nextPage.setUname(getUname()); we're calling the abstract getter of our Home class and passing the returned value to the abstract setter of Content class. It looks strange: how can we use a method that has yet to be implemented? But it works perfectly well at run time, because Tapestry creates implementations of all the abstract methods for us.

Let's test the new version of our application. Shut down and start up your Tomcat server, and point your browser to http://localhost:8080/Login/app . When the login form appears, enter a user name and any password into it and press the Let me in! button. Depending on which user name you used, the result might look like Figure 16.

1508_figure16
Figure 16. The Second Page Displays as Expected

Limiting Access to a Page

Since we're requesting a user name and password, it would be natural to limit access to our valuable Content page, so that only authorised users can access it. For now, let's hard-code one password for all users.

Normally, we'd check the password in the Login page and, if it was correct, we'd send the visitor the hidden Content. But what if some unwanted visitor managed to request the Content page directly, without logging in? Technically, this is possible.

One of the solutions to this problem is to check the password in the Content page. If the password is correct, we display the contents of the page, otherwise we redirect the user to the Login page.

To be able to do this, our Content page needs to make an agreement with Tapestry. It should ask, "Please notify me when you are going to show me, so that I can check a few things." This kind of agreement can be achieved if the page implements the PageValidateListener interface. To implement this interface, we need to declare it and add a pageValidate() method to our page class. With these additions, our Content.java looks like this:

package com.sitepoint.tapestry.login;    
   
import org.apache.tapestry.html.BasePage;    
import org.apache.tapestry.event.PageValidateListener;    
import org.apache.tapestry.event.PageEvent;    
   
public abstract class Content extends BasePage    
   implements PageValidateListener {    
     
 public void pageValidate(PageEvent event) {    
   // Some code will go here    
 }    
     
 public abstract String getUname();    
 public abstract String getPassword();    
 public abstract void setUname(String uname);    
 public abstract void setPassword(String password);    
}

Notice the two new import statements. You don't have to know where to find the classes or interfaces that you need, and you don't need to write these statements by hand. Eclipse will do all that for you. For example, when you type PageEvent , Eclipse will underline it with red, because it doesn't know what you mean. Place your cursor somewhere on this word and choose Source > Add Import, and this smart IDE will create the necessary import statement for you!

Tapestry will check that the page implements the PageValidateListener interface, so it should have a pageValidate() method. Tapestry calls this method just before showing the page to a user, and it is up to us to define which checks should be done in the method.

We're going to check if the password specified by the user is the same as the one we've hard-coded. If not, we'll tell Tapestry: "Stop! Don't show this page! Redirect the user to the Home page instead." This is what it looks like in Java:

if (!"mellon".equals(getPassword())) {    
 throw new PageRedirectException("Home");    
}

If the password entered by the user is "mellon" (the Elvish word for "friend"), everything is fine: they'll see the Content page. If not, we switch on an alarm and tell Tapestry: "Forget whatever you were doing, just show our login form to this user."

This is how the completed Content.java should look:

package com.sitepoint.tapestry.login;    
   
import org.apache.tapestry.PageRedirectException;    
import org.apache.tapestry.html.BasePage;    
import org.apache.tapestry.event.PageValidateListener;    
import org.apache.tapestry.event.PageEvent;    
   
public abstract class Content extends BasePage implements PageValidateListener {    
     
 public void pageValidate(PageEvent event) {    
   if (!"mellon".equals(getPassword())) {    
     throw new PageRedirectException("Home");    
   }    
 }    
     
 public abstract String getUname();    
 public abstract String getPassword();    
 public abstract void setUname(String uname);    
 public abstract void setPassword(String password);    
   
}

Now let's test our completed login web application.

Start or restart Tomcat and navigate, as usual, to http://localhost:8080/Login/app . Enter any user name and a wrong password, and press the Let me in! button. Nothing should happen -- you'll just see the same login form. Now type the secret word for the password that we hard-coded above. You should be able to view the Content page!

What Have we Learnt?

First, we saw that Tapestry HTML templates can be displayed perfectly in any web browser, because Tapestry's server-side hooks are limited to the attributes of standard HTML tags, so they remain virtually invisible.

This is very important because the presentation (HTML) remains absolutely independent of the logic (Java code), and either of them can be edited without any changes to the other. This is the cleanest possible separation between presentation and logic -- something that other frameworks struggle with and often fail to achieve.

We also saw how convenient and useful the Eclipse IDE (with the Spindle plug-in) is when it comes to Tapestry development.

We got our hands dirty and created a couple of pages, and saw that every page has three parts to it: an HTML template, a page specification and a page class.

We learned that Tapestry components are declared in the page specification, and saw how the binding is established between a component's jwcid attribute in the HTML template and either an event listener or a property.

We also saw one of the trickier but more powerful aspects of Tapestry: how page properties can be declared in the page specification, and how we can work with them as if they really existed, even though they're only created by Tapestry at run time.

We learned how to write code to navigate from one page to another, and how to pass parameters between pages (the "bucket brigade" pattern).

Finally, we saw how a Tapestry page can protect itself from being accessed by unauthorised visitors, and how little needs to be done to implement this functionality.

Whew! We've mastered quite a lot for this introduction, but there is still much more to the world of Tapestry!

Further Reading

Currently there are only two books on Jakarta Tapestry available in English:

  1. "Tapestry in Action" by Howard Lewis Ship , the creator of Tapestry. This book is useful for gaining a deeper understanding of the ideas behind Tapestry, and details of the inner workings of Tapestry 3. However, it's not very useful as a tutorial for beginners.
  2.  

  3. "Enjoying Web Development with Tapestry" by Ka lok 'Kent' Tong . I would call this book an advanced tutorial, and it is a must-have title for every Tapestry developer. It's packed with examples and advice starting from the basics and going on to some advanced topics. I found it invaluable when working on my own commercial Tapestry application. The book is available in two editions: for Tapestry 3 and for Tapestry 4.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值