Table of Contents
Tapestry is a comprehensive web application framework, written in Java.
Tapestry is not an application server. Tapestry is a framework designed to be used inside an application server.
Tapestry is not an application. Tapestry is a framework for creating web applications.
Tapestry is not a way of using JavaServer Pages. Tapestry is an alternative to using JavaServer Pages.
Tapestry is not a scripting environment. Tapestry uses a component object model, not simple scripting, to create highly dynamic, interactive web pages.
Tapestry is based on the Java Servlet API version 2.2 It is compatible with JDK 1.2 and above. Tapestry uses a sophisticated component model to divide a web application into a hierarchy of components. Each component has specific responsibilities for rendering web pages (that is, generating a portion of an HTML page) and responding to HTML queries (such as clicking on a link, or submitting a form).
The Tapestry framework takes on virtually all of the responsibilities for managing application flow and server-side client state. This allows developers to concentrate on the business and presentation aspects of the application.
Most leading web application frameworks are based on some form of scripting. These frameworks (often bundled into a web or application server) include:
All of these systems are based on reading an HTML template file and performing some kind of processing on it. The processing is identified by directives ... special tags in the HTML template that indicate dynamic behavior.
Each framework has a scripting language. For JavaServer Pages it is Java itself. For ASP it is Visual Basic. Most often, the directives are snippets of the scripting language inserted into the HTML.
For example, here's a snippet from a hypothetical JavaServer Page that displays part of a shopping cart.
<% String userName = (String)session.getAttribute("userName"); %> <h1>Contents of shopping cart for <%= userName %>:</h1> |
Most of the text is static HTML that is sent directly back to the client web browser. The emphasised text identifies scripting code.
The first large block is used to extract the user name from the HttpSession, a sort of per-client scratch pad (it is part of the Java Servlet API; other systems have some similar construct). The second block is used to insert the value of an expression into the HTML. Here, the expression is simply the value of the userName variable. It could be more complex, including the result of invoking a method on a Java object.
This kind of example is often touted as showing how useful and powerful scripting solutions are. In fact, it shows the very weaknesses of scripting.
First off, we have a good bit of Java code in an HTML file. This is a problem ... no HTML editor is going to understand the JavaServer Pages syntax, or be able to validate that the Java code in the scripting sections is correct, or that it even compiles. Validation will be deferred until the page is viewed within the application. Any errors in the page will be shown as runtime errors. Having Java code here is unnatural ... Java code should be developed exclusively inside an IDE.
In a real JavaServer Pages application I've worked on, each JSP file was 30% - 50% Java. Very little of the Java was simple presentation logic like <%= userName %>, most of it was larger blocks needed to 'set up' the presentation logic. Another good chunk was concerned with looping through lists of results.
In an environment with separate creative and technical teams, nobody is very happy. The creative team is unlikely to know JSP or Java syntax. The technical team will have difficulty "instrumenting" the HTML files provided by creative team. Likewise, the two teams don't have a good common language to describe their requirements for each page.
One design goal for Tapestry is minimal impact on the HTML. Many template-oriented systems add several different directives for inserting values into the HTML, marking blocks as conditional, performing repetitions and other operations. Tapestry works quite differently; it allows existing tags to be marked as dynamic in a completely unobtrusive way.
A Tapestry component is any HTML tag with a jwcid attribute ("jwc" stands for "Java Web Component"). For comparison, an equivalent Tapestry template to the previous JSP example:
This defines a component named insertUserName on the page. To assist HTML development, a sample value, "John Doe" is included, but this is automatically editted out when the HTML template is used by the framework.
The <span> tag simply indicated where the Tapestry component will go ... it doesn't identify any of its behavior. That is provided elsewhere, in a component specification.
A portion of the page's specification file defines what the insertUserName component is and what it does:
<component id="insertUserName" type="Insert"> |
![]() | The id attribute gives the component a unique identifier, that matches against the HTML template. The type attribute is used to specify which kind of component is to be used. |
![]() | Bindings identify how the component gets the data it needs. In this example, the Insert component requires a binding for its value parameter, which is what will be inserted into the response HTML page. This type of binding (there are others), extracts the userName property from the visit object (a central, application-defined object used to store most server-side state in a Tapestry application). |
Tapestry really excels when it is doing something more complicated than simply producing output. For example, let's assume that there's a checkout button that should only be enabled when the user has items in their shopping cart.
In the JSP world, this would look something like:
<% boolean showLink; String imageURL; showLink = applicationObject.getHasCheckoutItems(); if (showLink) imageURL = "/images/Checkout.gif"; else imageURL = "/images/Checkout-disabled.gif"; if (showLink) { String linkURL; linkURL = response.encodeURL("/servlet/checkout"); %> <a href="<%= linkURL %>"> <% } %> <img border=0 src="<%= imageURL %>" alt="Checkout"><% if (showLink) out.println("</a>"); %> |
This assumes that applicationObject exists to determine whether the user has entered any checkout items. Presumably, this object was provided by a controlling servlet, or placed into the HttpSession.
The corresponding Tapestry HTML template is much simpler:
A bit more goes into the page's specification :
![]() | Component checkoutLink is a Page, a component that creates a link to another page in the application. Tapestry takes care of generating the appropriate URL. |
![]() | The disabled parameter allows the link to be "turned off"; here it is turned off when the shopping cart is empty. |
![]() | A Rollover component inserts an image; it must be inside some kind of link component (such as the Page) and is sensitive to whether the link is enabled or disabled; inserting a different image when disabled. Not shown here is the ability of the Rollover component to generate dynamic mouse over effects as well. |
![]() | Tapestry uses an abstraction, assets, to identify images, stylesheets and other resources. The Rollover component wants a reference to an asset, not a URL. |
The point of this example is that the JSP developer had to worry about character-by-character production of HTML. Further, the ratio of Java code to HTML is quickly getting out of hand.
By contrast, the Tapestry developer is concerned with the behavior of components and has an elegant way of specifying that behavior dynamically.