Tapestry in Action
Licensed to Scott Douglass [email protected]
Tapestry in Action
HOWARD M. LEWIS SHIP
MANNING Greenwich (74° w. long.)
Licensed to Scott Douglass
©2004 by Manning Publications Co. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher.
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps.
Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books they publish printed on acid-free paper, and we exert our best efforts to that end.
Manning Publications Co. Copyeditor: Liz Welch 209 Bruce Park Avenue Typesetter: Denis Dalinnik Greenwich, CT 06830 Cover designer: Leslie Haimes
ISBN 1-932394-11-7
Printed in the United States of America 12345678910–VHG–08 07 06 05 04
Licensed to Scott Douglass
Licensed to Scott Douglass
Licensed to Scott Douglass
1 ■ Introducing Tapestry 3
2 ■ Getting started with Tapestry 38
3 ■ Tapestry and HTML forms 92
4 ■ Advanced form components 133
5 ■ Form input validation 169
PART 2CREATING TAPESTRY COMPONENTS...... 213
6 ■ Creating reusable components 215
7 ■ Tapestry under the hood 269
8 ■ Advanced techniques 322
PART 3BUILDING COMPLETE TAPESTRY APPLICATIONS...... 381
9 ■ Putting it all together 383
10 ■ Implementing a Tapestry application 403
vii
Licensed to Scott Douglass
APPENDIXES
A ■ Getting involved with Tapestry 479
B ■ Building the examples with Ant 485
C ■ Tapestry component reference 493
D ■ Tapestry specifications 516
Licensed to Scott Douglass
foreword xvii preface xix acknowledgments xxi about this book xxiii about the title xxvii about the cover illustration xxviii
PART 1 USING BASIC TAPESTRY COMPONENTS ...... 1
Introducing Tapestry 3 1 1.1 What are web applications? 5 1.2 What are Java servlets? 7 Understanding servlet multithreading 9 ■ Managing server-side state 10 ■ Using Struts with servlets 12 ■ Understanding the limitations of servlets 12 1.3 Why do we need Tapestry? 16 What is a framework? 16 ■ What is a component? 17 What is Tapestry? 18 ■ Comparing Tapestry to Swing 21 1.4 Understanding Tapestry’s goals 22 Simplicity 22 ■ Consistency 22 ■ Efficiency 23 Feedback 23
ix
Licensed to Scott Douglass
1.5 How does Tapestry work? 25 What’s in a Tapestry application? 27 ■ Tapestry’s Model- View-Controller (MVC) pattern 29 ■ Tapestry classes 33 1.6 Using Spindle 35 1.7 Summary 37 Getting started with Tapestry 38 2 2.1 Introducing the Hangman application 39 Determining the application flow 41 ■ Creating page mockups 42 ■ Defining the domain objects 44 Defining the pages 49 2.2 Developing the Home page 51 Understanding the Home page specification 52 ■ Rendering the Home page 54 ■ Defining the Home page class 57 Examining the Visit object 60 2.3 Implementing the Home page using standard servlets 62 2.4 Developing the Guess page 65 Displaying the remaining guesses 73 ■ Generating the guessed word display 79 ■ Selecting guesses 83 2.5 Developing the Win and Lose pages 89 2.6 Configuring the web.xml deployment descriptor 89 2.7 Summary 91 Tapestry and HTML forms 92 3 3.1 Understanding HTML forms 93 3.2 Creating a simple login form 96 Implementing the Login page class 99 ■ Using specified properties 101 3.3 Understanding the Form component 103 Developing forms without Tapestry 103 ■ Developing forms with Tapestry 105 ■ Handling form submissions 108 3.4 Using basic form control components 109 Understanding the essentials 110 ■ The Checkbox component 111 ■ Radio and RadioGroup components 111
Licensed to Scott Douglass
Select and Option components 113 ■ Submit and ImageSubmit components 118 3.5 Creating a to-do list 120 Defining the data object 121 ■ Creating the ToDo HTML template 122 ■ Specifying properties in the page specification 125 ■ Initializing the toDoList property 126 Handling reordering 127 ■ Deleting completed items 128 Triggering stale links 129 3.6 Summary 132 Advanced form components 133 4 4.1 Introducing the advanced form components 134 4.2 Creating drop-down lists with PropertySelection 134 Adding priority levels to the ToDo application 136 ■ Updating the HTML template 138 ■ Implementing the page class 139 Implementing the model 140 ■ Using enums instead of integers 144 4.3 Recording data in the form with Hidden 148 4.4 Looping within a form using ListEdit 151 Using the ListEditMap 153 ■ Using ListEdit in the ToDo application 154 4.5 Handling file uploads 160 4.6 Creating pop-up date selections using DatePicker 165 4.7 Summary 168 Form input validation 169 5 5.1 Validating user input 170 Using FieldLabels in conjunction with ValidFields 173 Using validators 173 ■ Using validation delegates 174 Using helper beans 178 5.2 Building the Register page 179 Creating the Register HTML template 181 ■ Creating the Register page specification 189 5.3 Validating input based on regular expressions 195 5.4 Customizing label and field decorations 199 5.5 Enabling client-side validation 202
Licensed to Scott Douglass
5.6 Handling form-level validations 205 5.7 Using validation without ValidField 208 5.8 Summary 211
PART 2 CREATING TAPESTRY COMPONENTS ...... 213
Creating reusable components 215 6 6.1 Creating simple template components 216 6.2 Creating the component specification 219 Specifying the component’s Java class 219 ■ Discarding the component’s body 220 ■ Forbidding informal parameters 221 Declaring parameters 222 ■ Reserving names 230 6.3 Creating the Digit and Scaffold components 230 Specifying the digit parameter 232 ■ Using the digit parameter 232 ■ Creating the template 233 ■ Using the Digit component 233 ■ Using the Scaffold component 234 6.4 Creating the Letter component 234 Specifying the Letter component 235 ■ Implementing the Letter component 236 ■ Using the Letter component 237 6.5 Building the Spell component 238 Implementing the Spell component 239 ■ Using the Spell component 240 6.6 Building the Border component 242 Creating the Border template 243 ■ Creating the Border specification 244 ■ Using the Border component 244 6.7 Creating interactive, reusable components 246 Introducing the Pet Store image map 246 ■ Specifying the DirectArea component 247 ■ Implementing the DirectArea component 248 ■ Using the DirectArea component 252 6.8 Using component libraries 254 Declaring libraries 254 ■ Referencing library components 256 6.9 Packaging components into libraries 261 Creating the library specification 262 ■ Creating the library specification 264 ■ Creating the FormError component 264 Using the FormError component 267 6.10 Summary 268
Licensed to Scott Douglass
Tapestry under the hood 269 7 7.1 Processing requests 270 7.2 Understanding the application servlet 271 Servlet request processing 271 ■ Understanding server-side state 272 ■ Managing server-side state in a cluster 274 7.3 Understanding the Tapestry engine 277 7.4 Understanding engine services 279 What’s the problem with application URLs? 279 ■ How does Tapestry handle application operations? 280 ■ Using the home service 281 ■ Rendering pages with the page service 283 Linking to listener methods with the direct service 284 Creating bookmarkable links using the external service 290 7.5 Page rendering in detail 291 Using markup writers 292 ■ Going beyond HTML 295 Understanding the page-rendering sequence 297 Using page-rendering events 297 7.6 Loading and pooling pages 299 Retrieving pages from the pool 300 ■ Creating new page instances 302 ■ Returning pages to the pool 304 7.7 Using persistent page properties 306 7.8 Using specified properties 308 7.9 Localizing Tapestry applications 309 Using Java localization 310 ■ Using Tapestry’s localization features 311 7.10 Summary 321 Advanced techniques 322 8 8.1 Creating new engine services 323 Defining a banner ad system 324 ■ Defining the data model 326 ■ Accessing the data model as an application extension 328 ■ Implementing the BannerAd component 329 Implementing the banner service 332 ■ Creating the library specification 336 ■ Building a banner ad application 337 8.2 Client-side scripting 339 Defining the CreditCardField component 341 ■ Working with the Body component 344 ■ Creating the Tapestry script
Licensed to Scott Douglass
specification 345 ■ Creating the CreditCardField specification 355 ■ Creating the CreditCardField component 356 ■ Using the component 368 8.3 Integrating with JavaServer Pages 369 Redirecting to a JSP 369 ■ Linking JSPs to Tapestry pages 371 ■ Submitting JSP forms into Tapestry 375 8.4 Summary 379
PART 3 BUILDING COMPLETE TAPESTRY APPLICATIONS ...... 381
Putting it all together 383 9 9.1 Introducing the Virtual Library 384 9.2 Performing searches 385 Changing the table sort order 387 ■ Paging through the results 387 9.3 Logging in and registering 388 9.4 Borrowing books 389 9.5 Getting details about books and persons 390 Viewing book details 390 ■ Viewing a person 392 9.6 Managing your books 393 Editing a book 394 ■ Deleting a book 395 ■ Returning books 395 ■ Adding a new book 396 ■ Editing your profile 396 ■ Giving away books 396 9.7 Administering the Virtual Library 399 Editing users 399 ■ Editing publishers 400 ■ Transferring books 400 9.8 Summary 402 Implementing a Tapestry application 403 10 10.1 Looking at the application layers 404 10.2 Organizing EJB access 406 Handling authentication 407 ■ Accessing Enterprise JavaBeans 407 ■ Tracking user identity with the Visit object 407 ■ Understanding page inheritance 410
Licensed to Scott Douglass
10.3 Implementing the Search page 413 Identifying application-specific components 415 ■ Referencing the engine 416 ■ Specifying the page class and properties 417 Performing searches 418 10.4 Implementing the BookMatches page 419 Handling paging and column sorting 420 ■ Using the Browser component 425 ■ Executing queries and re-queries 426 10.5 Implementing the Browser component 430 Specifying Browser’s parameters 430 ■ Getting results from the BookQuery bean 432 ■ Rendering the Browser component 433 10.6 Implementing the ColumnSorter component 434 Creating the ColumnSorter HTML template 434 ■ Specifying ColumnSorter parameters 435 ■ Responding to the user 437 10.7 Implementing the Border component 438 Handling user login 442 ■ Linking to MyLibrary 443 10.8 Authenticating the user 445 Remembering the user 446 ■ Clearing the password field 447 Invoking the login operation 449 10.9 Creating bookmarkable links 449 Creating the BookLink component 450 ■ Displaying the Book on the ViewBook page 451 ■ Creating the PersonLink component 453 ■ Displaying the Person 455 10.10 Editing a Book 457 Tracking the Book ID 459 ■ Generating dynamic JavaScript 460 10.11 Giving books away 463 10.12 Editing the publishers 464 Constructing the EditPublishers template 464 ■ Declaring properties for the EditPublishers page 465 ■ Creating the ListEditMap 467 ■ Updating the publishers 469 10.13 Editing the list of users 470 Creating the ListEditMap subclass 471 ■ Handling the form submission 472
Licensed to Scott Douglass
10.14 Creating the web deployment descriptor 474 Deploying web applications as root 476 ■ Deploying an enterprise application as root 476 10.15 Wrapping it all up 477
appendix A: Getting involved with Tapestry 479 appendix B: Building the examples with Ant 485 appendix C: Tapestry component reference 493 appendix D: Tapestry specifications 516
index 537
Licensed to Scott Douglass
My involvement with Tapestry began in the autumn of 2001. I read about the framework in an article in ONJava magazine. At the same time, our company was poised to begin several new web projects, and we were looking for a way to avoid the problems inherent in building complex web pages and forms with the standard tools. We analyzed a large number of frameworks, but Tapestry immediately attracted our attention, with its unique development method and its helpful community. The first glance was not misleading—Tapestry proved to be a powerful and helpful instrument in practice as well. The component structure was not sim- ply an add-on but was entrenched in the philosophy of the framework. We also discovered that Tapestry offered a number of other powerful features that proved to be critical in our work. For example, it allowed a clean separation between Java and HTML, and made it possible for the design work on the application to continue well after the code had been completed—and it could be performed by designers who never had to know anything about Tapestry. It provided internationalization capabilities well beyond simply replacing text with its translation. The framework was designed with EJBs and clustering in mind, and integrated with them effortlessly. Today our company has libraries containing hundreds of Tapestry compo- nents. Some of these are simple, such as a Login component that manages authentication using HTTP cookies. Others are far more complex, constructed
xvii
Licensed to Scott Douglass
from smaller components and full of intricate JavaScript, such as a tool for dynamically defining web forms. All of these components can simply be taken off the shelf and plugged into our latest application with ease. We do not have to worry how the various components will work together—we know that they will do so by design. During the two years we have worked with Tapestry, its development has not stood still. While the earlier versions of the framework concentrated on deliver- ing power, version 3.0 (described in this book) concentrates on both delivering maximum ease of use for programmers and enhancing their productivity. It low- ers the entry requirements, decreases the amount of developer effort needed, and makes the framework as easy to use as a scripting language for simple appli- cations. The result is that you can achieve the same results as before but with much less coding. The majority of these improvements have occurred and moved forward due to feedback and ideas from Tapestry users and contributors. The active commu- nity surrounding the framework helps it remain focused on resolving the prob- lems developers encounter in the real world. A major commendation for encouraging and integrating the contributions must also go to Howard Lewis Ship, the author of this book. As the creator and original designer of Tapestry, he has made a remarkable effort to listen to users, understand their needs, and address their requirements. The other Tapestry contributors have followed his lead and have extended the framework to provide support for a variety of new functionality areas. The community has also been instrumental in the process that made Tapestry a part of the Apache Jakarta family. With this step, it became a companion project of other popular projects, including Struts, Tomcat, and log4J. All of these factors ensure that Tapestry will persist in its evolution and will continue to improve the ways in which it makes the life of web developers easier and more productive. This book will allow you to delve into a different, better world of web develop- ment than the one you have known. It will show you an innovative approach for creating and organizing your applications, enable you to develop more robust and scalable code, and make previously difficult tasks much simpler. After you get to know Tapestry, you will start looking at web development in a very differ- ent way. Enjoy!
THEODORE TONCHEV “MINDBRIDGE” TECHNICAL DIRECTOR, RUSHMORE DIGITAL
Licensed to Scott Douglass
From the fall of 1998 through late 1999, I worked on a mix of interesting projects for my then-employer, Primix, a Boston Internet consulting firm. The first of these was a standard CRUD (Create Read Update Delete) application, and it used servlets and JavaServer Pages (JSPs). Despite the fact that we were a small team (just three or four of us at various times) working on a very mod- est application, it seemed like we were constantly having to reinvent the wheel. I’d had some exposure to Apple’s WebObjects framework, and the difference between the two approaches was like night and day: Not only did WebObjects have better tool integration, including a WYSIWYG ( W h a t Yo u S e e I s W h a t Yo u Get) HTML editor, it was easier to use even without the extra tools, just by edit- ing the underlying template and configuration files. We were a small, smart, experienced team—but working with servlets and JSPs was always an uphill battle compared to using WebObjects. A major part of this problem was impedance; each developer worked in his or her own corner of the application and had a particular way of working. Dif- ferent developers used different naming conventions and solved similar prob- lems in different ways—which caused extra grief when new developers cycled through the team, or when we had to venture outside our little fiefdoms to fix bugs. Remember, this was a time before J2EE servers really existed, before cus- tom JSP tag libraries, before Sun had even started promoting the Model 2 design pattern. It was also obvious that WebObjects, with its notion of components and
xix
Licensed to Scott Douglass
all the magic it did to hide URLs from the developer, was a far superior option. At the same time, steep licensing fees and lukewarm support and marketing by Apple made pitching a WebObjects solution to clients a nonstarter. We soldiered on with servlets and JSPs. Near the end of 1999 I was left with engagements in the pipeline but no short-term responsibilities. What was to eventually become Tapestry started as a kind of mental doodle: How does WebObjects do it? I started drawing diagrams and sketches, puzzling out a way to gracefully connect stateless HTTP requests to stateful Java objects via Java servlets, and eventually decided to code up a little prototype to see if my ideas would work. Somewhere along the line, I came up with the name: Tapestry. Tapestry quickly took on a life of its own; as primitive as that early code base looks compared to the Tapestry of today, it was still a solid foundation, something that would start to address the issues Primix had with servlet and JSP develop- ment. Primix was in the business of creating high-quality web sites on a regular basis, and Tapestry was a platform that would support the solid software engi- neering principles necessary to achieve its goals. Tapestry set up shop at Source- Forge (http://sf.net) and was released under the Lesser GNU Public License. Along the way, I realized something profound: I could make a difference. Inter- esting software didn’t have to come forth directly from the Suns, IBMs, and Microsofts, or even from the Apaches; it could be homegrown, like Tapestry. With Tapestry, I really thought I could change the world…or at least, the little niche of the world that writes web applications in Java. As fun as working on the code has been, the most fascinating part of Tapestry has been the creation of a real, online community around Tapestry. These are people for the most part I have yet to meet, who have recognized Tapestry as a Good Thing and who work as hard as I do to improve and promote it. It was on the strength of this community that Tapestry relocated from SourceForge to Apache’s Jakarta project, alongside established projects such as Struts, Turbine, and Velocity. Crafting a book about Tapestry has been more difficult and more intense an experience than anything else related to the project, but ultimately the result is worth the effort. What you are holding in your hands may open up a whole new approach to web application development for you and (I hope) will change your world for the better.
Licensed to Scott Douglass
Working on this book has been the highlight of my career to date. I’ve never before had the opportunity to be so focused and so self-directed for such a long time. I would never have had this opportunity without the support and friend- ship of Timothy Dion, the CTO of Primix, who gave me the green light to work on Tapestry in the first place, as well as the support to release it as open source. Just as instrumental was my good friend Gregory Burd, who championed Tap- estry within Primix and put it into play for its first big engagement. The Tapestry crew—Theodore Tonchev, Richard Lewis-Shell, David Solis, Neil Swinton, Harish Krishnaswamy, and Geoff Longman—have been tireless supporters of Tapestry, and good friends, many of whom I’ve yet to meet in person! Thanks as well to Andrew C. Oliver for sponsoring Tapestry in the Apache Jakarta project. Writing a book is a group effort—without the tireless help from the crew at Manning, this book would never have reached your hands. Both Marilyn Smith and Liz Welch provided endless assistance with grammar and style, as well as much valuable advice. Tiffany Taylor’s eagle eyes spotted an embar- rassing number of typos and inconsistencies. Denis Dalinnik did a standout job of typesetting. Special thanks to Jackie Carter, for keeping me honest and keeping me focused on the reader. Thanks also to my technical reviewers, espe- cially Bill Lear, Ryan Cox, Adam Greene, and Joel Trunick—they pushed me to create a better book than I would have thought possible. Thanks as well to
xxi
Licensed to Scott Douglass
Mary Piergies for keeping it all organized, to Clay Andres for getting the whole thing started, and to publisher Marjan Bace for the vote of confidence. Special thanks go to my wife, Suzanne, who has encouraged me every step of the way on this long process. Suzanne’s support has never wavered, even as this project consumed my time, attention, energy, and the dining room table (my workspace) for months on end. Suzanne has indulged my need to talk about Tapestry and this book long past the point where anyone else would have run screaming from the room, and I love her for that, and for her boundless enthusi- asm. We are stylin’, baby!
Licensed to Scott Douglass
Tapestry is a comprehensive web application framework for the Java pro- gramming language. Tapestry is based on components, highly reusable build- ing blocks that can be quickly and easily combined to form pages within your application. By using and reusing components, and creating your own com- ponents, you can create richly interactive, robust applications with only a modest effort. Tapestry’s basic style is to break problems into smaller and smaller units; this complements a team development environment where different develop- ers work on different parts of the application. The framework makes it easy for both Java and HTML-only developers to work together without acciden- tally undermining each other’s work. When building a web application with any technology, you will be faced with a constant stream of questions: How do I figure out what the user has requested? Where can I store this bit of information? How can I safely add this new functionality? How can I make my application scale? In too many envi- ronments, it’s easy to make the wrong decision when confronted with any of these, and many other, development-time questions. It’s too easy to take a quick-and-dirty detour down the wrong path, which ultimately comes back to bite you when you are least prepared to deal with it. The central goal of Tapestry is to make the easiest choice the correct choice. Over the course of this book, we’ll show you how to build applications using
xxiii
Licensed to Scott Douglass
Tapestry, but we will also show you the hidden traps and tangles that Tapestry helps you to avoid.
Roadmap
■ Chapter 1 introduces web applications in general. We begin to describe where Tapestry fits into the overall scheme of things and expand on the basic goals achieved by the framework. ■ Chapter 2 sets the stage, describing the implementation of a simple web application that plays the word game Hangman. Here we introduce many of the major concepts of Tapestry. ■ Chapters 3 through 5 describe how Tapestry handles HTML form input, including the framework’s sophisticated form-validation subsystem. ■ Chapter 6 describes how to build basic reusable components and how to package them into component libraries. ■ Chapter 7 delves into the inner implementation of Tapestry, shedding light on how the framework addresses scalability issues, localization, and the lifecycle of pages. ■ Chapter 8 describes advanced components, including components that create client-side JavaScript. We also discuss integrating Tapestry with a traditional servlets-and-JSPs application. ■ Chapters 9 and 10 describe the Virtual Library, a complete J2EE example application using Tapestry for the presentation layer and a mix of session and entity EJBs for the application layer. We include several real-world examples that illustrate how to build and polish a Tapestry application.
Who should read this book?
This is a book about getting things done using the Tapestry framework; as such, it will appeal to Java web developers looking for a better, easier way to build web applications. Because Tapestry is explicitly designed to support team develop- ment of web applications, this book will also be of interest to managers looking for a better way to leverage their team’s efforts. This book is targeted at people who have at least gotten their feet wet in terms of Java web application development (or perhaps have already taken the full plunge). Therefore, we assume that you are at least somewhat acquainted with a number of concepts and technologies. Obviously, an understanding of the Java programming language is a prerequisite, as well as familiarity with such key Java APIs as the
Licensed to Scott Douglass
collections framework. You should also be clear on the distinction between Java interfaces and Java classes. Much of Tapestry concerns the moving of information from one object to another; this is facilitated using JavaBeans properties. The core concept of the JavaBeans framework is that an object can be treated as if it was a Map, as a collec- tion of named properties that can be read or updated without knowing the actual class of the object. More information about JavaBeans is available at http:// java.sun.com/products/javabeans/docs/. You should be familiar with the basic set of HTML tags, including
, , ,