tapestry tutorial

Upload: narasimha-rao

Post on 31-May-2018

225 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/14/2019 Tapestry Tutorial

    1/48

    Tapestry Tutorialby Howard Lewis Ship

    Updated for Tapestry 3.0by Kevin C. Dorff

  • 8/14/2019 Tapestry Tutorial

    2/48

    Tapestry Tutorialby Howard Lewis ShipCopyright 2000, 2001, 2002, 2003 The Apache Software Foundation

    by Kevin C. Dorff

    Copyright 2003 Kevin C. Dorff

    ii

  • 8/14/2019 Tapestry Tutorial

    3/48

    Special Thanks (from Kevin C. Dorff)

    Howard M. Lewis Ship for Tapestry.

    Geoff Longman for Spindle

    http://spindle.sourceforge.net

    Vladimir Drndarski for helping me edit this Tutorial.

    Harish Krishnaswamy for the Illustrating Tapestry tutorial which helped me get going so Icould get enough up to speed to work on this tutorial.

    http://myworkspace.sourceforge.net

    iii

    http://spindle.sourceforge.net/http://myworkspace.sourceforge.net/http://myworkspace.sourceforge.net/http://spindle.sourceforge.net/
  • 8/14/2019 Tapestry Tutorial

    4/48

    Table of ContentsSpecial Thanks (from Kevin C. Dorff) .............................................................................................. iiiTable of Contents ............................................................................................................................ivTable of Figures................................................................................................................................vChapter 1: Introduction .................................................................................................................... 1Chapter 2: Setting up the Tutorial.................................................................................................... 3Chapter 3: Hello World .................................................................................................................... 8

    Application Engine....................................................................................................................... 8Web Deployment Descriptor........................................................................................................ 8Application Specification.............................................................................................................. 9Home Page Specification .......................................................................................................... 10Run the Application ................................................................................................................... 10

    Chapter 4: Dynamic Content ......................................................................................................... 12Chapter 5: Hangman ..................................................................................................................... 16

    The Visit Object ......................................................................................................................... 18The Home Page......................................................................................................................... 19The Guess Page........................................................................................................................ 22

    Chapter 6: Stylesheet and Image Assets (Hangman2) ................................................................. 25Chapter 7: Creating Reusable Components ................................................................................. 28Chapter 8: The Tapestry Inspector................................................................................................ 34

    Navigation.................................................................................................................................. 34Specification View...................................................................................................................... 35Template View ........................................................................................................................... 36Properties View.......................................................................................................................... 36Engine View............................................................................................................................... 37

    Chapter 9: Tapestry Workbench.................................................................................................... 38Chapter 10: Localization................................................................................................................ 40

    Localization of HTML Templates ............................................................................................... 41Localization of Assets................................................................................................................ 42Other Options for Localization ................................................................................................... 42

    Chapter 11: Further Study ............................................................................................................. 43

    iv

  • 8/14/2019 Tapestry Tutorial

    5/48

    Table of FiguresFigure 2 - 1: Eclipse and the tutorial projects .................................................................................. 5Figure 2 - 2: Potential Build Problems............................................................................................. 6Figure 2 - 3: The tutorial application running ................................................................................... 7Figure 3 - 1: Deployment descriptor, web.xml................................................................................. 9Figure 3 - 2: helloworld.application.................................................................................................. 9Figure 3 - 3: Home.page................................................................................................................ 10Figure 3 - 4: Home.html................................................................................................................. 10Figure 3 - 5: Hello World application running ................................................................................ 11Figure 4 - 1: Dynamic Application.................................................................................................. 12Figure 4 - 2: simple.application...................................................................................................... 12Figure 4 - 3: Home.html................................................................................................................. 13Figure 4 - 4: Home.page................................................................................................................ 14Figure 4 - 5: Home.java ................................................................................................................. 15Figure 4 - 6: HTML generated for the Home page for the simple application ............................... 15Figure 5 - 1: Hangman Home Page............................................................................................... 16Figure 5 - 2: Hangman Guess Page.............................................................................................. 17Figure 5 - 3: Figure 5.3: Hangman Failed Page ............................................................................ 17Figure 5 - 4: Hangman Success Page .......................................................................................... 18Figure 5 - 5: hangman.application................................................................................................. 18Figure 5 - 6: Home.java ................................................................................................................. 20Figure 5 - 7: Home.html (excerpt).................................................................................................. 21Figure 5 - 8: Home.page................................................................................................................ 22Figure 5 - 9: Guess.html (excerpt)................................................................................................. 23Figure 5 - 10: Guess.page (excerpt).............................................................................................. 23Figure 5 - 11: Guess.java (excerpt) ............................................................................................... 24Figure 6 - 1: Success.page............................................................................................................ 25Figure 6 - 2: Success.html............................................................................................................. 26Figure 6 - 3: Excerpt of Guess.html............................................................................................... 26Figure 6 - 4: Excerpt of Guess.page.............................................................................................. 27Figure 6 - 5: Excerpt of Guess.java............................................................................................... 27Figure 7 - 6: Border Home Page ................................................................................................... 28Figure 7 - 7: Border Credo Page ................................................................................................... 29Figure 7 - 8: Home.html................................................................................................................. 29Figure 7 - 9: Border.html................................................................................................................ 30Figure 7 - 10: Border.jwc ............................................................................................................... 31Figure 7 - 11: Show Inspector Button ............................................................................................ 32Figure 7 - 12: Home.page.............................................................................................................. 32Figure 7 - 13: BorderEngine.java................................................................................................... 33Figure 7 - 14: border.application.................................................................................................... 33Figure 8 - 1: Tapestry Inspector .................................................................................................... 34Figure 8 - 2: Specification View ..................................................................................................... 35Figure 8 - 3: Template View .......................................................................................................... 36Figure 8 - 4: Properties View ......................................................................................................... 36Figure 8 - 5: Engine View .............................................................................................................. 37Figure 9 - 1: Workbench................................................................................................................ 38Figure 9 - 2: Workbench (Showing Requests) .............................................................................. 39Figure 10 - 1: L10N Page (English) ............................................................................................... 40Figure 10 - 2: Locale Changed (German) ..................................................................................... 41Figure 10 - 3: L10N Page (German).............................................................................................. 41

    v

  • 8/14/2019 Tapestry Tutorial

    6/48

    Chapter 1: Introduction

    A note from Kevin C. Dorff, the tutorial updater November 2, 2003:

    This tutorial is an attempt to bring the previous Tapestry 2.2 tutorial, written by Howard LewisShip (HLS), into the Tapestry 3.0 realm and to include source code that will work with Tapestry3.0 beta 3 (and hopefully with 3.0 when it is available). The majority of the text in this documentwill remain unchanged from the original tutorial, but, I will make changes where changes,additions, etc. where warranted. It should be noted that I, myself, a relative Tapestry newbie Ihave been using Tapestry for about six weeks at the time of this writing, so, there may be betterways to do things, but, I felt the updated tutorial was desperately needed by people who currentlyin the same boat I was in six weeks ago (and waiting until I was a guru would benefit no one).Instead of just copying and pasting the original text, I have completely re-typed it, re-implementedevery example, and re-captured every screen shot. I have done this to avoid missing some 2.2 to3.0 difference that the reader might find confusing. If I have missed something, you know of abetter (more straightforward) way of doing something or explaining something please donthesitate to contact me so I can update this document ASAP.

    Kevin C. Dorff, [email protected]

    Tapestry is a new application framework for developing web applications. It uses a componentobject model to represent the pages of a web application. This is similar in spirit to using the JavaSwing component object model to build GUIs.

    Just like using a GUI toolkit, there's some preparation and some basic ideas that must be clearedup before going to more ambitious things. Nobody writes a word processor off the top of theirhead as their first GUI project; nobody should attempt a full-featured e-commerce site as their firstattempt using Tapestry.

    The goal of Tapestry is to eliminate most of the coding in a web application. Under Tapestry,

    nearly all code is directly related to application functionality, with very little "plumbing". If you havepreviously developed a web application using PHP, Microsoft Active Server Pages, JavaServerPages or Java Servlets, you may take for granted all the plumbing: writing servlets, assemblingURLs, parsing URLs, managing objects inside the HttpSession, etc.

    Tapestry takes care of nearly all of that, for free. It allows for the development of rich, highlyinteractive applications.

    This tutorial will start with basic concepts, such as the "Hello World" application, and will graduallybuild up to more sophisticated examples.

    This tutorial was build and tested with the Tomcat 4.1 servlet engine,http://jakarta.apache.org/tomcat, a freely available servlet engine

    1. I believe it should work with

    Tomcat 4.0 without issue.

    2

    1

    HLS used Jetty in the Tapestry 2.2 version of the Tutorial, but I have never used Jetty. I believethe only thing that is stopping you from using Jetty (or any other servlet engine for that matter)instead of Tomcat is that I have written ant scripts (deploy.xml for every project) that deploydirectly to Tomcat. Edit these scripts so they instead deploy to Jetty and you should be set.2

    In many Tapestry applications, the web.xml file includes and tags. These do not appear to work with Tomcat 4.0, so I have not included them in theseapplications. This is the only incompatibility I have found between Tapestry 3.0 and Tomcat 4.0thus far.

    1

    mailto:[email protected]://jakarta.apache.org/tomcathttp://jakarta.apache.org/tomcatmailto:[email protected]
  • 8/14/2019 Tapestry Tutorial

    7/48

    This tutorial was built using Eclipse 2.1.1, http://www.eclipse.org, and Spindle 3.0.29,http://spindle.sourceforge.net. It is strongly recommended that you setup a similar environment(you will be happy you did). At the time of this writing, Spindle 3.x.x did not support Eclipse 3.x,only 2.1 or 2.1.x.

    The format of this tutorial is to describe (visually and with text) several small applications withinthe tutorial and to describe how they are constructed, using code excerpts. The reader is bestserved by having an IDE open so that they can look at the complete code in detail, as well as runthe applications.

    2

    http://www.eclipse.org/http://spindle.sourceforge.net/http://spindle.sourceforge.net/http://www.eclipse.org/
  • 8/14/2019 Tapestry Tutorial

    8/48

    Chapter 2: Setting up the TutorialEven if you skim the rest of this tutorial, please read this chapter carefully.

    If you have no interest in using Eclipse and already have Tapestry running, but just wantto look at the tutorial source code and see it execute, a WAR file for each project isincluded under

    \DeployWars\local-dev\.war

    Tapestry requires JDK 1.3 or later.

    This document expects that you will have extracted the full Tapestry (binary) distribution to yourC: drive

    3. This will have created a directory C:\Tapestry-x.x and, beneath it, several more

    directories4.

    This document expects you have Eclipse 2.1.x installed to c:\eclipse.

    You will need to copy the Tapestry and related jar files to the shared/lib (or equivalent) area ofyour servlet engine. For Tomcat 4.1 this means copying

    C:\Tapestry-x.x\lib\*.jar

    C:\Tapestry-x.x\lib\runtime\*.jar

    C:\Tapestry-x.x\lib\ext\*.jar

    To\shared\lib

    \shared\lib should now contain about 13 jar files and no directories (it should not

    contain the directories runtime or ext, the jars from those directories should be placed directly in

    \shared\lib).

    If you are using another servlet engine, the location to which you copy the files will be different. Itis likely you will have problems running the tutorial applications with Tomcat 4.0, please use 4.1.

    This tutorial references the Workbench application. This is an application that is distributed withthe Tapestry binary distribution. It is assumed you will copy the workbench.war to your servletengines webapps directory. For Tomcat this means copying

    C:\Tapestry-x.x\lib\examples\workbench.war

    To\webapps

    The complete source for the Workbench application is included with the Tapestry sourcedistribution. This code can be quite useful when you are developing your own Tapestry

    applications.

    This document expects that you have Spindle 3.0.29 (or whatever the latest version is) installedwithin Eclipse.

    3If you are using Solaris or another non-Windows operating system, you're expected to be savvy

    enough to translate to a sensibly constructed file system.4

    The x.x is the release number. At the time of this writing, the current version was 3.0-beta3, butthis is constantly changing. Simply adjust the actual pathname to reflect the release of Tapestryyou downloaded.

    3

  • 8/14/2019 Tapestry Tutorial

    9/48

    Next, obtain the source for this tutorial. It is distributed separately as a ZIP file named

    TapestryTutorialWorkspace-x.x.zip

    This file can be found on the same web site where you found this tutorial (if you cannot find it,contact [email protected]).

    Extract this tutorial ZIP file to

    c:\save\eclipse

    The result should be a directory named c:\save\eclipse\TapestryTutorialWorkspacewhichwill become a new Eclipse workspace. To make this a workspace, open My Computer (iconfound on your desktop), navigate to C:\Eclipse. Right click on Eclipse.exe and select Create

    Shortcut. Rename that shortcut to Tapestry Tutorial. Right click on the new shortcut and select

    Properties and change the Target to launch eclipse, specifying a new workspace directory(where you expanded the tutorial ZIP file):

    c:\eclipse\eclipse.exe

    -data c:\save\eclipse\TapestryTutorialWorkspace

    If you choose, you can move this new shortcut to your desktop (just drag it there or cut andpaste).

    Launch Eclipse with your new shortcut, make sure Eclipse is in the Resource Perspective andyou should see 6 projects !TapestryLibs (some bundled tapestry jar files), border, hangman,helloworld, portal, simple, and tutorial. You can generally just ignore !TapestryLibs.

    4

    mailto:[email protected]:[email protected]
  • 8/14/2019 Tapestry Tutorial

    10/48

    Figure 2 - 1: Eclipse and the tutorial projects

    Each of these tutorial projects began their life using Spindle via

    File | New | Project

    Tapestry | Tapestry Web Project

    Note: By default, early versions of Spindle versions 3.0.x placed the Home.html template file inthe context directory. Versions 3.0.11 and later will place this file in the WEB-INF directory, so Ihave placed all template (html) files in the WEB-INF directory (if this means nothing to you, dontworry about it at this point).

    The first of two differences between these projects and a standard Spindle project is that astandard Spindle project includes a Library named Tapestry Framework (plugin default).For increased portability from my system to yours of these tutorial applications, I removed thislibrary and refer to a few Tapestry and related jars individually and distribute those jars with the

    tutorial source code distribution.

    The only other addition to the configuration of each project is an additional External ToolsBuilder to deploy the project to Tomcat. Within each project you will find this external tool builder,an ant script, with the filename deploy.xml.

    You will need to edit each of the five deploy.xml files to replace the location in which you haveTomcat installed and the username and password for a Tomcat manager user. At the top of eachof the deploy.xml files is a note about setting up manager users for Tomcat.

    5

  • 8/14/2019 Tapestry Tutorial

    11/48

    Once you have edited each of the deploy.xml files, you should be able to build and install eachof the pieces of the tutorial.

    Note: After editing the project configuration and trying to rebuild the project, you may get an errorthat the "Resource is out of synch with the file system:..." this is easily fixed by right clicking on

    the project, selecting "Refresh" and then rebuilding the project as previously instructed. If youreceived the below dialog, you would want to refresh the simple project.

    Figure 2 - 2: Potential Build Problems

    Lets start with the project named tutorial. To build and install this project into Tomcat (makesure Tomcat is running), click on the project name (tutorial) in the Eclipse Navigator pane,then select, from the main menu

    Project | Rebuild Project

    You may notice the output of the execution of the deploy.xml ant script (in the Eclipse Consolepane) that it reports a FAIL when it try to remove the previous instance of the application fromTomcat this is normal. The FAIL indicates that the project didnt previously exist in Tomcat. Onsubsequent deployments you should not get this failure notice.

    You can repeat this process for deploying all of the tutorial applications (border, hangman,helloworld, and simple).

    If, in the future, you make changes to a specific application and want to install the new versioninto Tomcat, simple click on the project name in the Navigator pane (in the ResourcePerspective) and select the menu item

    Project | Rebuild Project

    You should now be able to navigate to the URL

    http://localhost:8080/tutorial

    6

    http://localhost:8080/tutorial/apphttp://localhost:8080/tutorial/app
  • 8/14/2019 Tapestry Tutorial

    12/48

    where you will see the Tutorial application is running. There is no need to stop and restartTomcat, the deploy.xml ant script handles this for the specific application that is being deployed.

    Figure 2 - 3: The tutorial application running

    7

  • 8/14/2019 Tapestry Tutorial

    13/48

    Chapter 3: Hello WorldIn this first example, well create a very simple Hello World kind of application. It wont have anyreal functionality but it will demonstrate the simplest possible variation of a number of key aspectsof the framework.

    Well define our application, define the lone page of our application, and configure everything tolaunch it.

    The code for this section of the tutorial can be found in the helloworld project, i.e.,

    c:\save\eclipse\TapestryTutorialWorkspace\helloworld

    Application EngineAs each new client connects to the application, an instance of the application engine is createdfor them. The application engine is used to track that clients activity within the application.

    The application engine is an instance of (or a subclass of) the Tapestry class named

    org.apache.tapestry.engine.BaseEngine

    In these first few examples, we have no additional behavior to add to the provided base class, sowe simply use BaseEngine class directly.

    Web Deployment DescriptorThe application servlet is a bridge between the servlet container and the application engine. Its

    job is simply to create (on the first request) or locate (on subsequent requests) the applicationengine.

    All Tapestry applications use the same servlet class, however, its configuration is different. Part ofthe configuration is to identify the location of the application specification which is like the master

    index of all pages in the application.

    The following figure shows the web deployment descriptor (web.xml) for one of the applications inthis tutorial, Hello World

    8

  • 8/14/2019 Tapestry Tutorial

    14/48

    Figure 3 - 1: Deployment descriptor, web.xml

    helloworld

    helloworld

    org.apache.tapestry.ApplicationServlet

    1

    helloworld

    /app

    index.html

    These first few lines are a header for XML files. You will see very similar headers on all.xml, .page, .application, and .jwc files (Tapestry is choc full of these files asTapestry strongly leverages XML). The header will vary slightly based on which of thosetypes the file is each file type has a specific header that is required.

    Most Tapestry applications will have a of

    org.apache.tapestry.ApplicationServlet. If you need to do something like override

    the servlet init() or destroy() methods, you would extend this class and put the nameof your own class here.

    Application SpecificationThe application specification is used to describe the application to the Tapestry framework. Itprovides the application with a name, an engine class, and the name of your applications Homepage5.

    In a deployed Tapestry application, the application specification lives in the applications WEB-INF directory.

    Figure 3 - 2: helloworld.application

    Hello World Application

    The helloworld.application file is very simple; we give the application name, use thestandard engine, and define a single page, named Home. In Tapestry, pages and components

    5In previous versions of Tapestry it was required that you list all of your application pages in the

    .application file. In Tapestry 3.0 it is only necessary to list the Home page.

    9

  • 8/14/2019 Tapestry Tutorial

    15/48

    are specified with the path to their specification file (a file that ends with .page for pagespecifications or .jwc for component specifications).

    The page named Home has a special meaning to Tapestry: when you first launch a Tapestryapplication, it loads and displays the Home page. All Tapestry applications are required to havesuch a page.

    Home Page SpecificationThe page specification defines the Tapestry component responsible for the page. In this firstexample, our component is very simple.

    Figure 3 - 3: Home.page

    Hello World Home Page

    This simply says that Home is a kind of page. We use the supplied Tapestry class BasePagesince we arent adding any behavior to the page.

    Figure 3 - 4: Home.html

    Hello World

    Welcome to your first Tapestry Application.

    Run the ApplicationYou should already be running Tomcat and have a browser window running the tutorials page.Select the first option, Hello World. You will be presented with the first (and only) page generatedby Tapestry for this application.

    10

  • 8/14/2019 Tapestry Tutorial

    16/48

    Figure 3 - 5: Hello World application running

    Not much of an application theres no interactivity or dynamic content. It might as well be astatic web page, but its a start. Remember, there was no JavaServer page (JSP) here, and noHTML directly visible to the web server. We used the Tapestry framework to assemble anapplication consisting of a single component.

    In the following chapters, well see how to add dynamic content and then true interactivity.

    11

  • 8/14/2019 Tapestry Tutorial

    17/48

    Chapter 4: Dynamic ContentIn this chapter, well create a new web application that will demonstrate the dynamic componentsof Tapestry. We'll do two simple things. First we'll have Tapestry invoke a java method thatdisplays the time. Second, we'll have Tapestry create a link to our own page so that the time canbe refreshed. Figure 4-1 shows how this example will look when were finished:

    Figure 4 - 1: Dynamic Application

    Clicking the word here will update the page showing the new date and time. Not incrediblyinteractive, but its a start.

    The code for this section of the tutorial is in the simple project, in the package tutorial.simple.

    The application specification is almost identical to the Hello World example:

    Figure 4 - 2: simple.application

    Simple Application

    Things only begin to get more interesting when we look at the HTML template for the home page:

    12

  • 8/14/2019 Tapestry Tutorial

    18/48

    Figure 4 - 3: Home.html

    Simple

    This application demonstrates some dynamic

    behavior using Tapestry components.

    The current date and time is:

    This Text Will Be Replaced

    Click here to refresh.

    This looks like ordinary HTML, except for the jwcid attribute. jwc is short for Java WebComponents; these attributes identify the tag as a placeholder for a dynamic Tapestrycomponent.

    We have two components. The first inserts the current date and time into the HTML response.The second component creates a hyperlink that refreshes the page when clicked.

    One of the goals of Tapestry is that the HTML should have the minimum amount of specialmarkup. This is demonstrated here; the dynamic component tags blend into the standard HTMLof the template. We also dont confuse the HTML by explaining exactly what an insertDate orrefresh is; that comes out of the specification (described shortly). The ids used here aremeaningful only to the developer

    6, the particular type and configuration of each component is

    defined in the component specification.

    Tapestry doesnt really care what HTML tag you use, as log as you balance the tag correctly. Anytags that Tapestry is required to process must either be in the format

    or

    Again, it is not necessary that you use the tag, only that tag closes itself or has a closing,matching tag. You will also notice that Tapestry is often a stickler for the nesting of other tags. Ifyou have HTML code such as dont be surprised if Tapestry gives an errorwhen you try to display the page.

    In fact, Tapestry ignores the tag entirely: the refresh component above, which use a set of tags, could just as easily have been done with a tag, or any other tag for that matter.Tapestry is only interested in the structure of the HTML template. The fact that you can usemeaningful tags is a convenience; it also allows a Tapestry HTML template to be previewed witha WYSIWYG HTML editor, such as HomeSite or Dreamweaver or even opened directly with aweb Browser such as Internet Explorer. Additionally, Tapestry edits out the content of the tags

    (the text between the open and close tags, if any exists) for components that dont wrap aroundother content, such as the insertDate component in this example. The insertDate tags

    contains the text This Text Will Be Replaced, but, when the page is rendered by Tapestrythat text will be completely replaced by the dynamically created text which represents the currentdate. This allows a preview value to be kept in the template.

    Very significant is the fact that Tapestry components can wraparound other elements of thetemplate. The refresh component wraps around the word here. What this means is that the

    6Of course, good and consistent naming is important.

    13

  • 8/14/2019 Tapestry Tutorial

    19/48

    refresh component will get a chance to emit HTML (an hyperlink tag), then emit the HTML it

    wraps (the word here), then get a chance to emit more HTML (the closing tag).

    Whats more important is that the component can not only wrap static HTML from the template(as shown in this example) but may wrap around other Tapestry components and thosecomponents may themselves wrap text and components, to whatever depth is required.

    And, as well see in later chapters, a Tapestry component itself may have a template and morecomponents inside of it. In a real application, the single page of HTML produced by theframework may be the product of dozens of components, effectively woven from dozens ofHTML templates.

    Again, the HTML templates dont define what the components are, they are simply a mix of staticHTML that will be passed directly back to the web browser, with a few placeholders (the tags withthe jwcid attribute) where dynamic content will be plugged in.

    The pages component specification defines what types of components are used and how datamoves between the application, page, and any components.

    Figure 4 - 4: Home.page

    Simple Home Page

    Home

    Heres what all that means: The Home page is implemented with a custom class,

    tutorial.simple.Home. It contains two components, insertDate and refresh.

    The two components used within this page are provided by the Tapestry framework.

    The insertDate component is of the type Insert. Insert components have a value parameter

    used to specify what should be inserted into the HTML produced by the page. The insertDate

    component has its value parameter bound to a JavaBeans property of its container (the page),

    the currentDate property.

    The refresh component is of the type PageLink, meaning it creates a link to some other page in

    the application. PageLink components have a parameter, named page, which defines the name

    of the page to navigate to (when using the PageLink component, the specified page must be apage within the current application).

    In this case, we only have one page in our application (named Home), so we can use a for the page parameter. A provides a value for thecomponent parameter statically, the same value every time. The value is defined right in thespecification.

    14

  • 8/14/2019 Tapestry Tutorial

    20/48

    This just leaves the implementation (Java code) of the Home page component:

    Figure 4 - 5: Home.java

    package tutorial.simple;

    import java.util.Date;

    import org.apache.tapestry.html.BasePage;

    public class Home extends BasePage {

    public Date getCurrentDate() {

    return new Date();

    }

    }

    Home implements a read-only JavaBeans property, currentDate. This is the same currentDate

    that the insertDate component needs. When asked for the current date, the Home object returns

    a new instance of the java.util.Date object. The insertDate component converts objects intostrings by invoking toString() on the object.

    Now all the bits and pieces are working together.

    Run the application and then use the View Source command to examine the HTML generated bythe Tapestry framework.

    Figure 4 - 6: HTML generated for the Home page for the simple application

    Simple

    This application demonstrates some dynamic

    behavior using Tapestry components.

    The current date and time is:

    Wed Oct 29 16:18:57 MST 2003

    Click here to refresh.

    This should look very familiar, in that it is mostly the same as the HTML template for the page.Tapestry not only inserted simple text (the current date and time, obtained from ajava.util.Date object), but the refresh component inserted the and tags, and

    created an appropriate URL for the href attribute.

    You may notice that Tapestry URLs can get somewhat strange a standard Tapestry applicationdoes not make URLs for human consumption. You wont be typing in URLs to place yourself intothe middle of a standard Tapestry application. Friendly URLs are not a topic for this tutorial. Theexample Vlib application (in the Tapestry distribution) provides examples of friendlier,

    bookmarkable URLs.

    15

  • 8/14/2019 Tapestry Tutorial

    21/48

    Chapter 5: HangmanSo far, these examples have been a little thin. Lets do a meatier example that uses a few moreinteresting components. Lets play hangman!

    Our hangman application consists of four pages. The first page is, of course, the Home page. Itallows the user to start new game at one of three difficulty levels, which simply regulates thenumber of guesses the user is allowed.

    Figure 5 - 1: Hangman Home Page

    16

  • 8/14/2019 Tapestry Tutorial

    22/48

    The workhorse of this little web application is the Guess page, shown in figure 5-2, where thepartially filled out word is displayed, and the user makes guesses from a shrinking list of possibleletters.

    Figure 5 - 2: Hangman Guess Page

    If you give up, or make too many mistakes, you end up on the Failed page.

    Figure 5 - 3: Figure 5.3: Hangman Failed Page

    17

  • 8/14/2019 Tapestry Tutorial

    23/48

    But if you guess all the letters, you are sent to the Success page:

    Figure 5 - 4: Hangman Success Page

    The Visit ObjectThe center of this application is an object that represents the game, an object of classHangmanGame. This object is used to track the word being guessed, the letters that have beenused, the number of misses, and the letters that have been correctly guessed.

    In this application, the HangmanGame object will a property of the applications visit object.Whats the visit object? The visit object is a holder of all information about a single clients visit toyour web application. It contains data and methods that are needed by the pages andcomponents of your application.

    The visit object is owned and created by the engine object. It is serialized and de-serialized withthe engine.

    The application specification includes a little extra segment to specify the class of the applicationsvisit object.

    Figure 5 - 5: hangman.application

    Hangman Application

    tutorial.hangman.Visit

    18

  • 8/14/2019 Tapestry Tutorial

    24/48

    This property specifies that the engine should instantiate an instance of

    tutorial.hangman.Visit when a visit object is first required. This is the default way inwhich the visit object is specified, though if the visit object doesnt have an emptyconstructor method, the engine method createVisit() must be implemented instead.

    So, returning from that distraction, the game object is a property of the visit object, which is

    accessible from any page (via the pages visit property).

    The Home PageThe Home pages job is to collect the difficulty and initiate a game:

    19

  • 8/14/2019 Tapestry Tutorial

    25/48

    Figure 5 - 6: Home.java

    package tutorial.hangman;

    import org.apache.tapestry.IRequestCycle;

    import org.apache.tapestry.html.BasePage;

    public class Home extends BasePage {

    public static final int EASY = 10;

    public static final int MEDIUM = 5;

    public static final int HARD = 3;

    private int misses = 0;

    private String error = "";

    public void detach() {

    misses = 0;

    error = "";

    super.detach();

    }

    public int getMisses() {

    return misses;

    }

    public void setMisses(int value) {

    misses = value;

    }

    public String getError() {

    return error;

    }

    public boolean getHasError() {

    if ((error == null) || (error.length() == 0)) {

    return (false);

    }

    return (true);

    }

    public void formSubmit(IRequestCycle cycle) {

    if (misses == 0) {

    error = "Please select a game difficulty.";

    return;

    }

    Visit visit = (Visit)getVisit();

    visit.startGame(misses);

    cycle.activate("Guess");

    }

    }

    The detach method is automatically called after the page is displayed. The job of thismethod is to reset class level variables back to "default" values. At the time a page isbeing created, the associated Java class for the page is used to help display the page tothe user. After the page is displayed, the associated Java class it not destroyed, butrather, it is placed in a pool for later use (for displaying the page at a later time).Because the Java class is not destroyed, but instead pooled, it is generally desirable toreturn any class-level variables to default values. The next time the page is requestedby any user, the page could be returned from the pool.

    20

  • 8/14/2019 Tapestry Tutorial

    26/48

    By just returning from the listener method, we are implicitly stating that the same pageneeds to be displayed again.

    In Tapestry, cycle.activate(pagename) is the standard way of changing to anotherpage. Here, we are moving control to the Guess page.

    We don't provide a default difficulty level for the user. If the user fails to select a difficulty level

    before pressing "Play!", the listener for the page's form,Home.formSubmit()

    , will set an errormessage then redisplay the Home page.

    Otherwise, we get the visit object and ask it to start a new game with the selected number ofmisses. We then jump to the Guess page to start accepting guesses from the user.

    The interesting part of the Home page HTML template is in the form:

    Figure 5 - 7: Home.html (excerpt)

    Easy game; you are allowed ten misses.

    Medium game; you are allowed five misses.

    Hard game; you are only allowed three misses.

    In HTML, PHP, Perl, JSPs, Servlets, etc., HTML forms can post to any page within theapplication or website. It should be noted that Tapestry forms alwayspost back to thesame Tapestry page or component that created the form. Since the Home page createdthe form, the Home page always receive the post of the form. Because of this, it isnecessary that either the form, the submit button, or both define a listener (a methodwhich will be called to handle the form submission). If you define a listener on both thesubmit button and on the form, the listener for the button will be called, then the listenerfor the form. We can see in Home.page that a listener for the form has been specified.

    Here, the interesting components are group, inputEasy, inputMedium, and inputHard. group is

    of the type RadioGroup, a wrapper that must go around the Radio components (the other three).

    The RadioGroup determines what property of the page is to be read and updated (its bound to

    the misses property). Each Radio button is associated with a particular value to be assigned tothe property, when the radio button is selected by the user.

    This comes together in the Home page specification

    21

  • 8/14/2019 Tapestry Tutorial

    27/48

    Figure 5 - 8: Home.page

    Hangman Home Page

    This is the listener for the form. Looking in Home.java, we will find a method namedformSubmit(). This method will be called when the form is submitted.

    A is used to read a value from a class. Here, instead of a standardJavaBeans property, we are retrieving a static value from the class. You will notice a new

    syntax that is related to using static properties or methods. The syntax is@class@property.

    So the end result is: when the user clicks the radio button for a Hard game, the static constantHARD is assigned to the pages misses property.

    The Guess PageThis page is where users make letter guesses. The page has four sections:

    A display of the word being guessed, with underscores replacing un-guessed letters.

    A status area, showing the number of bad guesses and an optional error message whenthe player guesses a wrong letter.

    A list of letters that may still be guessed. Letters disappear after they are used.

    An option to give up and see the word, terminating the game.

    22

  • 8/14/2019 Tapestry Tutorial

    28/48

    Lets start with the HTML template this time:

    Figure 5 - 9: Guess.html (excerpt)

    Make a Guess

    You have made bad guesses,

    out of a maximum of .

    Guess:

    Give up?

    Most of these components should be fairly obvious by now; we will focus on the components thatallow the user to guess a letter. This could have been implemented in a number of ways usingmore radio buttons, a drop down list or a text field the user could type into. In this example, wechose to simply create a series of links, one for each letter the user may still guess.

    Lets look at the page specification.

    Figure 5 - 10: Guess.page (excerpt)

    Failed

    23

  • 8/14/2019 Tapestry Tutorial

    29/48

    Component e is simply a Foreach, the source is the unused property of the game.

    Component insertLetter inserts the current letter from the list of unused letters. It gets this

    current letter directly from the e component. On successive iterations, the Foreach components

    value property is the value in the iteration.

    Component guess is of type DirectLink, which creates a hyperlink on the page and notifies itslistener when the user clicks on the link. Just knowing that the component was clicked isnt veryhelpful, though; the application needs to know which letter was actually clicked. Passing that kindof information along is accomplished by setting the parameters attribute of the DirectLink

    component. The parameters attribute is an object, or array of objects, that will be encoded intothe URL for the hyperlink. When the components listener is executed, it can obtain the objectfrom the IRequestCycle7.

    The parameters are often used to encode primary keys of objects, names of columns, or otherinformation specific to the application.

    In this case, the parameters consist of a single value, the letter that was guessed.

    All of this comes together in the Java code for the Guess page.Figure 5 - 11: Guess.java (excerpt)

    public void makeGuess(IRequestCycle cycle) {

    Object[] parameters = cycle.getServiceParameters();

    String letter = (String) (parameters[0]);

    HangmanGame game = ((Visit)getVisit()).getGame();

    try {

    game.guess(letter);

    } catch (HangmanGameException ex) {

    error = ex.getMessage();

    if (game.getFailed())

    cycle.activate("Failed");

    return;

    }

    // A good guess.if (game.getDone()) {

    cycle.activate("Success");

    }

    }

    The component specification showed how data was encoded into the URL as parameters; here

    we see how the makeGuess() listener method has access to the parameters and uses them. Thelistener method extracts the letter and informs the game object, which throws an exception if theletter is not in the word being guessed.

    The method HangmanGame.getFailed() returns true when all the missed guesses are used up,

    at which point we go to the Failed page to tell the user what the word was.

    On the other hand, if an exception isnt thrown, the guess was good. getDone() returns a true if

    all the letters have been guessed, in which case we go to the Success page.

    If all the letters werent guessed, we stay on the Guess page, which will display the word with theguessed letters filled in, and with fewer options in the list of possible guesses.

    7Tapestry takes care of converting objects into strings when constructing the URL, the converts

    those strings back into objects when the link is clicked. Your listener method will be able to getcopiesof the original parameters.

    24

  • 8/14/2019 Tapestry Tutorial

    30/48

    Chapter 6: Stylesheet and Image Assets (Hangman2)As a brief aside, we will make some changes to the hangman application. As to not confuse thecode, we have duplicated the Chapter 5 hangman application to a new application called

    hangman2. The changes to the application are minor. We have added a set of graphics in the

    context/images directory, we have added a stylesheet in the context/css directory, we havemade some minor changes to the .html and .page files to reference the stylesheet and images,and have added one method to the Guess.java to display the correct game image based on thenumber of incorrect guesses so far.

    Tapestry has a concept of an asset. A Tapestry asset, generally specified in a .page file, can bea file such as a stylesheet or an image that the application depends on to execute. If a .pagespecies an asset but the asset does not exist, the Tapestry framework will generate an error andnot display the page.

    Looking at the Success.page file, we can see how we specify the assets that this page uses.

    Figure 6 - 1: Success.page

    Home

    Creates a Tapestry asset named stylesheet that is associated with the file

    context/css/hangman.css.

    Creates an Tapestry asset named win that is associated with the filecontext/images/win.gif.

    This is a component that will be referred to from the Success.html template. The name ofthe component is winImage, the type is Image. We can see that the image that will be

    displayed is an asset that is named win.

    Looking at the Success.html template, we can see how the stylesheet is called. It is also worthnoting that we are no longer specifying the title bar for the browser via the HTML tag, butwe are letting Tapestry set the browser title for us.

    25

  • 8/14/2019 Tapestry Tutorial

    31/48

    Figure 6 - 2: Success.html

    You Win!

    The word was:

    .

    Start Again

    The @Shell component lets us specify attributes of stylesheet and title. We arespecifying that the stylesheet for the page should be the asset named stylesheet (as

    defined in the .page file) and the browser title should be the static test Hangman Success.

    The winImage component comes from the .page file and we have already seen this willrender the image associated with the asset named win, so context/images/win.gifwill be displayed to the user.

    Up to now, we have always specified the name of the Tapestry components in the .html file andthe type, attributes, etc. of those components in the .page file. Here, we have provided a sampleof how components can be created completely in the .html file. When we specified in the .html file

    this is equivalent to having a .html file of

    with associated entries in the .page file of

    Hangman Success

    You will see both used in Tapestry applications.

    The Failed and Home pages are very similar to the Success, so we will not cover those here.

    Now that we have demonstrated how to use stylesheets and how to display static images usingassets, we will demonstrate a more dynamic use of graphical assets. On the Guess page, it wouldbe neat to display a graphic that changes, depending on the difficulty of the game and the current

    number of incorrect graphics. To do this, we have created 11 additional graphics named 0.gif to10.gif (again, these live in the /images directory). To display the correct image on theGuess page, we will first look at an excerpt the Guess.html file.

    Figure 6 - 3: Excerpt of Guess.html

    Next we will look at how this component is defined in an excerpt of the Guess.page file.

    26

  • 8/14/2019 Tapestry Tutorial

    32/48

    Figure 6 - 4: Excerpt of Guess.page

    This is very similar to the static image that is displayed via Compared to the static images fromSuccess.page with one notable difference, instead of directly specifying an asset, we are

    specifying that a JavaBeans getter method (in the class Guess.Java) will provide the imageasset. The method that will be called must have the signature

    public IAsset getGuessImageAsset()

    We can see how that method is defined by looking at an excerpt of the Guess.java file.

    Figure 6 - 5: Excerpt of Guess.java

    public IAsset getGuessImageAsset() {HangmanGame game = ((Visit)getVisit()).getGame(); int iMissed = game.getMissed();int iMaxMisses = game.getMaxMisses();int iFactor = 1;if(iMaxMisses==3) {

    iFactor = 3;} else if(iMaxMisses==5) {

    iFactor = 2;}String name = "wrong_" + iMissed*iFactor; return (getAsset(name));

    }

    Obtain the current players HangManGame object from the visit object so we can see howmany letters the player has incorrectly guessed so far and how many they can missbefore the game ends.

    Depending on the number of max misses, define a factor that can be used to determinethe correct asset name to display (so the correct image is displayed).

    Determine the name of the asset to be displayed and obtain the actual asset (via thePages getAsset() method). Return the asset.

    The Guess page can now display a specific image depending on the number of incorrectguesses.

    27

  • 8/14/2019 Tapestry Tutorial

    33/48

    Chapter 7: Creating Reusable ComponentsA quick special notation about the border project The BorderEngine.java class in the border

    project extends the org.apache.tapestry.engine.BaseEngine class. To do this, you need to

    have the class javax.servlet.http.HttpSessionBindingListener in your classpath. If you

    are using Tomcat, this means making sure servlet.jar is in the classpath. In order to makeEclipse happy enough to build the project, I have created a folder in this projected calledReferenceJars_NotInstalled and placed Tomcat 4.1.27s servlet.jar in this directory andreferenced it in the projects Java Build Path | Libraries.

    In this tutorial, well show how to create a reusable component. One common use of componentsis to create a common border for the application that includes basic navigation. Well be creatinga simple three page application with a navigation bar down the left side and the page title acrossthe top.

    Figure 7 - 6: Border Home Page

    28

  • 8/14/2019 Tapestry Tutorial

    34/48

    Navigating to another page results in a similar display

    Figure 7 - 7: Border Credo Page

    Each pages content is confined to the silver area in the center. Note that the border adapts itselfto each page: the title Home or Credo across the top is specific to the page, and the menuitem for the current page doesnt have an active link (in the above page, Credo is set to thecurrent page, so only Home and Legal are usable navigation links).

    The T in the lower right hand corner is the Show Inspector link. It will be described in the nextchapter.

    Each of the three pages has a similar HTML template:

    Figure 7 - 8: Home.html

    Nothing much doing here on the home page.

    Please visit one of our other fine pages.

    Remember that Tapestry components can wrap around other HTML elements or components.For the border, we have an HTML template where everything on the page is wrapped by the

    border component.

    Note that we dont specify any or tags; those are provided by the Border

    component.

    This illustrates a key concept within Tapestry: embedding vs. wrapping. The Home page embeds

    the border component (as well see in the Home pages specification). This means that the Homepage is implemented using the border component.

    However, the border component wraps the content of the Home page, the Home page HTMLtemplate indicates the order in which components (and static HTML elements) are rendered. Onthe Home page, the border component bats first and performs cleanup.

    29

  • 8/14/2019 Tapestry Tutorial

    35/48

    The construction of the Border component is driven by how it differs from page to page. Youllsee that on each page, the title (in the upper left corner) changes. The names of all three pagesare displayed, but only two of the three will have links (the third, the current page, is just text).Lastly, each page contains the specific content from its own HTML template.

    Figure 7 - 9: Border.html


    The shell component provides the and elements of the response HTML,including the title for the browser window.

    The body component provides the element. It also provides support for

    JavaScript related to Rollover buttons, such as the inspector component.

    The e component is a Foreach configured to work through a list of page names (providedby the engine).

    The link and insertName components provide inter-page navigation links.

    The renderBody component provides the actual content for the page. The Border

    component is used on all three pages, but its a different instance on each page,wrapping around different content specific to the page.

    The inspector component provides the button on the lower right hand corner of thepage (the T in a circle) and will be explained in the next chapter.

    The Border component is designed to be usable in other Tapestry applications, so it doesnt hardcode the list of page names. These must be provided to the component as a parameter. In fact,the application engine provides the list.

    30

  • 8/14/2019 Tapestry Tutorial

    36/48

    Figure 7 - 10: Border.jwc

    Declares a required parameter for the border, the title that will appear on the page. Declares a parameter to specify the list of page names. We dont specify a particular type

    because its pretty unbounded; the framework will accept List, Iterator, or Java array. We then provide the shell component with its title parameter; this will be the

    browsers window title. We use the applications name, which is extracted from theapplications specification.

    The element allows a component to share parameters. Here the

    Borders title is used as the value parameter of the insertPageTitle component (an

    Insert component). Using these inherited bindings simplifies the process of creatingcomplex component from simple ones.

    Likewise, the e component (a Foreach) needs as its source the list of pages, which it

    inherits from the Border components pages parameters. It has been configured to store

    each successive page name into the pageName property of the Border component; this is

    necessary so that the Border component can determine which page link to disable (itdisables the current page since were already there).

    The link component creates a link to the other pages. It has a disabled parameter,which, when true, causes the link component to not create the hyperlink (though it stillallows the elements it wraps to render). The Java class for the Border component,

    tutorial.border.Border, provides a method, getDisabledPageLink(), that returns

    true when the pageName instance variable (set by the e component) matches the currentpages name.

    31

  • 8/14/2019 Tapestry Tutorial

    37/48

    This component will raise the Tapestry Inspector in a new window when the Inspectorgraphic is clicked.

    So, the specification for the Border component must identify the parameters it needs, but alsothe components it uses and how they are configured.

    Figure 7 - 11: Show Inspector Button

    Clicking on the Tapestry Inspector button raises a second window that describes the current pagein the application (this is used when debugging a Tapestry application). The Inspector isdescribed in the next chapter.

    The final mystery is the wrapped component. It is used to render the elements wrapped by the

    Border on the page containing the Border. Those elements will vary from page to page; runningthe application shows that they are different on the Home, Credo, and Legal pages (different textappears in the central silver box). There is no limitation on other elements either: Tapestry isdesigned to allow components to wrap other components this way, without any arbitrarylimitations.

    This means that the different pages could contain forms, images, or any set of components atall not just static HTML text.

    The specification of the home page shows how the title and pages parameters are set. This title isstatic, the literal value Home (this isnt the best approach if localization is a concern).

    Figure 7 - 12: Home.page

    Home

    The pages property is retrieved from the application engine, which implements a pageNamesJavaBeans property.

    32

  • 8/14/2019 Tapestry Tutorial

    38/48

    Figure 7 - 13: BorderEngine.java

    package tutorial.border;

    import org.apache.tapestry.engine.BaseEngine;

    public class BorderEngine extends BaseEngine {

    private static final String[] pageNames = { "Home", "Credo", "Legal" };

    public String[] getPageNames() {

    return pageNames;

    }

    }

    In order for the application to utilize this new engine, we must specify the engine in the applicationfile.

    Figure 7 - 14: border.application

    Border Application

    It should also be noted that because the InspectorButton is part of the contrib library, anexternal library of Tapestry components that are bundled with the Tapestry distribution, we mustspecifically make this library available to the application with the element.

    33

  • 8/14/2019 Tapestry Tutorial

    39/48

    Chapter 8: The Tapestry InspectorUnlike scripting systems (such as JavaServer Pages and the like), Tapestry applications aregifted with a huge amount of information about how they are implemented. The same componentobject model that allows Tapestry to perform so many ordinary functions can be leveraged toprovide some unusual functionality.

    Run the border tutorial from the previous chapter and click on the show Inspector button (the Tin the lower right corner). A new window will launch, containing the Inspector:

    Figure 8 - 1: Tapestry Inspector

    The Inspector displays live information from the running application; in fact, it is simply anotherpart of the application (the drop-down list of pages will include the Inspector page itself, titledcontrib:Inspector). The Inspector is most often used to debug HTML generation by viewingthe HTML templates. It is also very useful in debugging problems where the wrong data isdisplayed, since it allows the developer to navigate to the particular components and see directlywhat properties are used.

    NavigationThe inspector allows the user to navigate to any page and any component on any page. The dropdown list in the upper left corner lists all pages in the application; changing the selectionimmediately updates the inspector.

    Next to the drop down list is the component path, a list of nested component ids, starting withpage, to represent the page. Clicking on any id on the page changes the information displayedbelow.

    Underneath the component navigation tools are a set of tab buttons for the different inspectorviews.

    34

  • 8/14/2019 Tapestry Tutorial

    40/48

    Specification View

    Figure 8 - 2: Specification View

    The specification view shows several sets of information about the selected component.

    First shown are basic properties, such as the specification path and Java class.

    Each formal parameter is displayed. Unbound parameters will show no value in the Bindingcolumn.

    Beneath formal parameters are informal parameters (the Border page/component has none, sothere is nothing to see). Informal parameters are usually mapped directly to HTML attributes.They are most often used with components that generate a single HTML tag, such as theActionLink, DirectLink, or TextField components.

    If the component contains assets, they are shown next.

    Any helper beans for the component are displayed last.

    On the right side is a list of each embedded component and its type. Clicking on the componentwill navigate to the selected component.

    35

  • 8/14/2019 Tapestry Tutorial

    41/48

    Template View

    Figure 8 - 3: Template View

    The template view shows the HTML template for the page/component. It shows dynamic tags inbold, and makes the component id a clickable link (which navigates to the component, butmaintains the Template View). This allows the developer to quickly drill down throughcomponents.

    Properties View

    Figure 8 - 4: Properties View

    The properties view shows persistent properties stored by the page (or any components on thepage). Most pages do not store any persist ant state (it is more commonly stored in the

    applications visit object).

    36

  • 8/14/2019 Tapestry Tutorial

    42/48

    Engine View

    Figure 8 - 5: Engine View

    The engine view shows information about the running application engine, as well as some detailsfrom the application specification.

    Under Operations are two buttons: the first restarts the application. The second (when enabled8)

    resets the application, which forces a reload of all component specifications and HTML templates.This is useful during development since it allows for incremental development without stoppingand restarting the servlet container, which may otherwise be necessary depending on the servletcontainer you are using.

    Below the operations is a binary dump of the application engine. This is useful when developingto see how large the serialized state is, and perhaps gleam how it might be trimmed.

    Further below (and not visible in the screen shot above) is a dump of the request context. This isa vast amount of data also displayed when an unexpected exception is thrown.

    8By default, the reset service (used by the reset button) is disabled. To enable it, set the JVM

    system property org.apache.tapestry.enable-reset-service to true. The service isdisabled since it is too tempting a target for denial of service attack.

    37

  • 8/14/2019 Tapestry Tutorial

    43/48

    Chapter 9: Tapestry WorkbenchThe Tapestry distribution includes an application, the Workbench, which is used to show offinteresting Tapestry components and features.

    Figure 9 - 1: Workbench

    The Workbench is divided into several areas, as shown by the tabs across the top of the page.Over time, the Workbench will expand and the number of tabs will increase.

    In addition to the Inspector (which, you can see, can be disabled via the textbox in the lower righthand corner), the workbench has a useful feature which can be activated using the checkbox inthe lower left hand corner. When enabled, the complete (and verbose) information available

    about the request, session, and context (normally displayed by the Inspectors engine view) isshown at the bottom of each page.

    38

  • 8/14/2019 Tapestry Tutorial

    44/48

    Figure 9 - 2: Workbench (Showing Requests)

    This feature can be very useful if you are interested in exactly how Tapestry forms and links work.

    39

  • 8/14/2019 Tapestry Tutorial

    45/48

    Chapter 10: LocalizationOne of the most powerful and useful features of the Tapestry framework is the way it assists withlocalization of a web application. This is normally and ugly area of web applications, withtremendous amounts of ad-hoc coding necessary.

    Because Tapestry does such a strong job of separating the presentation of a component (itsHTML template) from its control logic (its specification and Java class) it becomes easy for it toperform localization automatically. Its as simple as providing additional localized HTML templatesfor the component and letting the framework select the proper one.

    However, the static text of an application, provided by the HTML templates, is not all.

    Applications also have assets (images, stylesheets, and the like) that must be localized: thatfancy button labeled Search is fine for your English clients, but your French clients will require asimilar button labeled Recherch.

    Again, the framework assists, because it can look for localized versions of the assets as it runs.

    A demonstration of localization is built into the Workbench, under the L10N9 tab. The page allowsthe user to select a new language for the application:

    Figure 10 - 1: L10N Page (English)

    Selecting German from the list and clicking the Change button brings you to a new page thatacknowledges your selection:

    9The 10 refers to the number of letters between L and N in the word LOCALIZATION.

    40

  • 8/14/2019 Tapestry Tutorial

    46/48

    Figure 10 - 2: Locale Changed (German)

    Clicking the button (its labeled Return in German) returns you to the L10N page to select a newlanguage:

    Figure 10 - 3: L10N Page (German)

    The neat thing here is that the L10N page has been localized to German as well; it shows theequivalent German text, the options in the popup list are in German, and the Change button hasbeen replaced with the German equivalent.

    Localization of HTML Templates

    Localization of HTML templates is automatic. When Tapestry reads a template, it looks for alocalized version of it. In this example, in addition to the English language Localization.html,

    three additional files were created: Localization_de.html, Localization_fr.html, and

    Localization_it.html.

    Tapestry tracks the locale for each user using either an HTTP Cookie, or the HttpSession. Itmakes sure that all templates for all components on the page use the best available template; itdoes a standard search.

    41

  • 8/14/2019 Tapestry Tutorial

    47/48

    Localization of AssetsIn the L10N pages, there are images that are also localized. Tapestry has a hand in this as well.As with HTML templates, Tapestry search for matches based on the users locale.

    Both context assets (assets that are part of the WAR) and private assets (assets stored in theJava frameworks) can be localized. This is demonstrated on the L10N page: the Change button

    is a private asset; the Back button is a context asset.

    Other Options for LocalizationIn some cases, different localizations of a component may be very similar, perhaps having onlyone or two small snippets of text that is different. In those cases, it may be easier on thedeveloper not to localize the HTML template, but to replace the variant text with an Insertcomponent.

    The page can read a localized strings file (a .properties file) to get appropriate localized text.This saves the bother of maintaining multiple HTML templates. This is the same approach takenby the Apache Struts framework.

    All components on a page share the single locale for the page, but each performs its own searchfor its HTML template. This means that some components may not have to be localized, if theynever contain any static HTML text. This is sometimes the case for reusable components, evennavigational borders.

    42

  • 8/14/2019 Tapestry Tutorial

    48/48

    Chapter 11: Further StudyThe preceding chapters cover many of the basic aspects of Tapestry. You should be comfortablewith the basic Tapestry concepts:

    Separation of presentation, business, and control logic

    Use of JavaBeans properties as the source of dynamic data

    How bindings access JavaBeans properties to provide data to components

    How components wrap each other, allowing for the creation of very complicatedcomponents through aggregation

    Different types of page properties (transient, dynamic, and persistent)

    Tapestry is capable of quite a bit more. Also available within the Tapestry distribution is theexample for a Virtual Library application (Vlib).

    Vlib is a full blown J2EE application which makes use of Tapestry as its front end, and a set ofsession and entity Enterprise JavaBeans as its back end.

    Vlibalso demonstrates some of the other aspects of developing a Tapestry application. It showshow to create pages that are bookmarkable (meaning that their URL includes enough information

    to reconstruct them in a subsequent session). It shows how to handle logging in to an application,and how to protect pages from being accessed until the user is logged in. It has manyspecialized, reusable components for creating links to pages about books and people.