CVS: TapestryBook/doc Chapter-01-IntroducingTapestry.doc,NONE,1.1 Book-Introduction.doc,NONE,1.1 index.html,1.2,1.3 Chapter-02-GettingStarted.doc,1.2,1.3 Chapter-01-Introduction.doc,1.3,NONE
Howard Lewis Ship <[email protected]>
| Newsgroups | gmane.comp.java.tapestry.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/tapestry/TapestryBook/doc In directory sc8-pr-cvs1:/tmp/cvs-serv15970/doc Modified Files: index.html Chapter-02-GettingStarted.doc Added Files: Chapter-01-IntroducingTapestry.doc Book-Introduction.doc Removed Files: Chapter-01-Introduction.doc Log Message: Checkpoint. --- NEW FILE: Chapter-01-IntroducingTapestry.doc --- ÐÏࡱá ng URLs and specifying names and values for query parameters. Pages, Components and Parameters Tapestry applications are composed of a finite number of pages, and individual pages are composed of components. Most of Tapestry is in detailing the relationship between pages and the components contained with the page. Each page has an XML specification, a description of the page. This description starts with the name of class that will be instantiated to represent the page in memory. It can include specifications for many other types of resources needed by the page; details on these options will be presented in later chapters. All pages have an HTML template. The template will contain placeholders for any components embedded by the page. These placeholders act like JSP tags, but are designed to be simpler and less obtrusive. Components are much like pages; they may have an HTML template and they may embed other components as well. Additionally, components may specify the names and types of any parameters the component accepts. Components have other similarities to a JSP tag; both components and tags have parameters that may be optional or required. Unlike a JSP tag, a Tapestry component parameter is strongly typed (JSP tag parameters are always strings). Also, unlike a JSP tag, a Tapestry component parameter is both readable and writable. Writable parameters allow for a much richer, more dynamic relationship between a page and its components. For example, the suite of form-related components have the ability to read page properties via their parameters when rendering an HTML form, but when that form is submitted, the exact same components can update page properties through the same parameters. In fact, this give and take, with components both reading and updating the properties of their page, is central to the dynamic process of rendering a Tapestry page. Ultimately, the page acts as an intermediary, brokering the transfer of information between its components. Much like a JSP tag, a Tapestry component can wrap around other components and static HTML. Ultimately, each component controls if, or even how often, it will render its body. Implicit and Declared Components Pages represent embedded components in their templates in two different forms: implicit and declared. Implicit components are simpler, and more like a JSP tag. .With implicit components, the pages HTML template will include a placeholder for the component, as well as the type of component and the configuration of the all the components parameters. Declared components are more powerful, but more complex. Declared components are up, with some aspects stored in the HTML template and the others stored in the page specification. The HTML template contains only the placeholder for the component, not its type. The page specification fills in the remaining details, providing the type of component and the parameter configuration. The decision to use implicit or declared parameters is up to the developer. Typically, simple components (with few parameters) are good candidates for implicit components. Components with many parameters, or with especially complex parameters, are good candidates for declared components. Object Graph Navigation Library Tying all of these objects, properties and parameters together is Tapestrys expression language, OGNL, the Object Graph Navigation Library. OGNL is actually a separate open-source project that is used by Tapestry. Simple OGNL expressions are the names of JavaBean properties, such as color or pageName. OGNL expressions can also be sequences of property names, such as visit.game. OGNL is, in fact, a very rich language, and OGNL expressions can include constants, conditionals, arithmetic operations, comparisons, method invocations and more. Virtually any valid Java expression is a valid OGNL expression, except that there is no need to worry about type conversions; OGNL takes care of that automatically. OGNL expressions allow components to reach, through the page, to a wide range of domain objects. This basic infrastructure allows Tapestry components to be simple and flexible, yet very powerful. The Model-View-Controller Pattern Model-View-Controller is a very common concept in user-interface design. It refers to an important approach when developing user interfaces that separates the data to be presented and edited from the visual aspects. Keeping these aspects separated has great benefits in flexibility and testablility. In a proper user interface, the objects involved are divided into three categories: Model: The model portion of the pattern consists of the domain objects, the classes that implement pure logic. These objects have no connection to the user interface at all, and could be reused in any type of user-interface, anything from command line to Swing to Tapestry. View: The view portion of the pattern is concerned with how the information provided by the Model is presented to the user. In Tapestry, this is bound up in the HTML templates, as well as the related style sheets and images. Tapestry is organized specifically so that non-Java developers can make changes to these aspects of the view without breaking the application; as well see, Tapestry templates are still valid HTML documents, and can be easily edited in a WYSIWYG editor such as HomeSite or Dreamweaver. Controller: The controllers job is to coordinate the Model and the View, acting as an intermediary. This means extracting data from the model and providing it to the view, as well as responding to any user input (updating the model and view as necessary). Tapestry pages and components work together to fulfill the controller portion of the pattern, in that they mediate and organize the model and the view to produce an active application. Understanding Web Archives Getting and Running the Examples Running Hangman The complete source code for all the examples in this book is available for download at XXX. The package includes source code and all necessary libraries as well as pre-compiled WAR files. The WAR files can even be regenerated using the Ant build tool (available from XXX). If you want to try out any of the examples, the easiest way to do so is to download a copy of the Tomcat Servlet container from HYPERLINK "http://jakarta.apache.org/tomcat/index.html" http://jakarta.apache.org/tomcat/index.html, and then deploy the WARs by copying them into the Tomcat deploy directory. Summary Tapestry is a uniquely powerful way to create web applications in Java; freeing developers to work in traditional object-oriented fashion when developing applications for the very non-traditional web environment. In the following chapters, well visit all these features of Tapestry and show how Tapestry expands developer productivity, allowing developers to focus on the details of the application, and not on the trivia of web applications and the Servlet API. PAGE 4 PAGE 3 Authors Template Manning Publications Co. PAGE 4 Authors Template Manning Publications Co. PAGE 3 &F . &F &F &F &F &F &F &F l & &F &F &F & &F & & ð ð .:áÿÿÿÿÿÿÿÿÿ Þaæ¦( XüÆ `Xüo( XüÆ `Xüo( od od íÀ@ --- NEW FILE: Book-Introduction.doc --- ÐÏࡱá e pages. Reuse is not an add-on in Tapestry, or a mere theoretical possibility; component reuse was designed into Tapestry from day one. Reduced Coding In a typical Java web application, the majority of coding falls into the category of "plumbing". This is code that performs mundane tasks such as reading query parameters and converting the values for assignment to application object properties, constructing URLs with query parameters, storing and retrieving server-side state into the HttpSession object and the like. In fact, percentage wise, the amount of application-specific code in a Java web application, even in the presentation layer, is very, very small. The vast majority of code is performing these simple "plumbing" tasks. These bits of plumbing show up as a few lines here, a few lines there, distributed across all the classes of the application, but they build up. Worse, it is very hard to unit test servlets effectively, which means it is relatively easy for incompletely tested code to make it into a production system. Even frameworks such as Jakarta Struts don't significantly reduce coding. Using Struts, you'll code Actions instead of Servlets, but the methods you implement will be similar. For form and link submissions, Struts may read query parameters and update the properties of a form object, but you, the developer, will still be responsible for reading properties from the form object and updating your application objects and you still have to write the form object yourself. Struts, when combined with its JSP tag libraries, implements a partial pull model, but still requires that the developer "seed" things, by storing root objects into the HttpServletRequest as attributes before forwarding to the JSP to render a response. When multiple Actions share a single JSP, the code that performs this seeding may be duplicated. Meanwhile, once the query parameters are converted into objects and values, and once those values have been used to update application objects, the final relevant code, the application-specific code, is typically very short. It may be just a few lines of code to validate data before storing it into a database, or to fire off a message to an Enterprise JavaBean to initiate a business process. The core concept of Tapestry is to move all this plumbing into the framework, where it can be coded, verified and stress-tested just once. Tapestry link components build URLs and invoke application-specific code when those URLs are triggered. Tapestry form components read object properties when rendering, and update object properties when the form is submitted. Developers dont provide all the code for converting values and updating properties, just the final bit of application specific code . There is no magic in Tapestry; it doesn't read the developers mind. Developers must still inform the framework where data comes from and where it goes and even what to do with it but this is done inside a page specification file, a succinct XML file that describes the page, its components and the configuration of those components. It's still programming, yes, but its declarative programming, and done not in Java, but in the higher-level XML specification language. Developer Support Tapestry is designed from the ground up to be developer-friendly. Tapestry includes a number of built-in tools to assist developers. Tapestry catches unexpected exceptions with several layers of handling and reporting. In a typical web application, when an unexpected exception is thrown while processing a request, the user will be presented with a page showing the name of the exception and a stack trace. Tapestry does significantly more; it shows the name of the exception, the message associated with it, any JavaBean properties of the exception, and then does the same for any nested exception, as deep as possible, showing a stack trace only at the deepest level. When the problem is, for example, invalid syntax in a specification file, these exception properties will identify the specific file and line that is in error. The exception report also displays all the information it can about the request and query parameters, the application, the Servlet API objects even all the JVM system properties. The goal is to provide the developer with the tools needed to quickly diagnose and repair the problem without needing to re-run the application using a debugger. Team Development Tapestry's model of the application, as a cluster of individual pages, meshes well with how medium- to large-scale web applications are developed. Tapestry allows multiple developers to work in parallel with few hot spots, points of contention, to cause conflicts. Pages may share some set of components for common elements (page navigation and the like), but unless and until the API for those components change, it will not affect other developers (even when the implementation of the shared component changes significantly). On the first Tapestry project at Primix (my employer during the initial development of Tapestry), I received and integrated the finished HTML for the Border component from the creative team. The Border component provided the basic look and feel of the application. The other developers, unaware, synched up their workspaces to the common source code repository and suddenly and unexpectedly, found their pages had the finished look and feel, complete with images, style sheets and JavaScript popup menus. The point is that these significant style and functionality changes were contained within a single shared component. Changing that component internally meant that the changes were shared with all other team members, without affecting any of the pages the other developers were responsible for. Tapestry also supports a proper division of labor between the "creative" team, responsible for HTML and graphics, and the "technical" team, responsible creating a functional application. These two teams may not be physically located near each other they may not even work for the same company. Streamlining the interaction between these two teams is critical for large-scale applications that may have hundreds of individual pages. Converting HTML for use in a web application is typically a destructive, one-way process. HTML mockups are provided by the creative team and converted into JSPs by slicing and dicing the mockup, adding lots of JSP specific tags (or even Java scriptlets) and replacing some of the HTML tags with JSP tags. Common portions of the JSP may even be moved into JSP include files. Once instrumented in this way, the JSP will no longer preview properly in a WYSIWYG editor such as HomeSite or Dreamweaver. This makes later changes to the look and feel of the application, even tasks as simple as changing a font or the width of a column, a tedious process. Often, the application must be run so that the creative team member can see if a desired change worked. Tapestry HTML templates, unlike JSPs, are still completely valid HTML documents, and still preview correctly in WYSIWYG editors. Within some simple guidelines, discussed in detail in chapter XXX, it is reasonable to have creative and technical developers work on the same HTML templates without breaking each other's work. What's Wrong with Servlets and JSPs? Tapestry was created, not to right the wrongs of the Servlet API, but simply to build a different model of web application development on top of it. There's nothing wrong with what the Servlet API provides in terms of facilities, but it is only a starting point for a framework such as Tapestry. Many organizations code Java web applications using just the Servlet API. When following Suns Model-2 architectural pattern, a web application consists of a number of servlets that handle incoming requests, and a number of JSPs that render responses. Servlets are responsible for extracting values from query parameters, managing any server-side state, performing application-specific operations, and finally, selecting and forwarding to a JSP to render the response. The Jakarta Struts framework also builds on the Servlet API, in a much less ambitious way than Tapestry does. Struts "rounds out" the rough edges of the Servlet API, adding a few select features, supported by a JSP tag library. Like Tapestry, Struts filters all application requests through a single servlet. The servlet dispatches to a specific Action, a class provided by the developer. Actions, however, are all but indistinguishable from servlets in style and implementation. Like servlets, they must be stateless, containing no data specific to any individual user of the overall application. Struts provides assistance when decoding query parameters, using form beans. Query parameters contain values either encoded into a URL, or passed up from an HTML form. The Struts configuration file for the application will link Actions to form beans. When a request for the Action is processed, Struts will extract values of query parameters from the request and assign them to properties of the form bean, doing necessary conversions as needed. This can replace a good amount of code related to extracting query parameters from the request, and performing conversions on them. Struts provides an abstraction that separates an Action from the JSP that renders a response. An Action must return a forward, an object that will next process the request. Typically, the forward maps to a JSP, which will render the HTML response returned to the client. A forward can also be another Struts Action. Additionally, Struts can use other technologies to render responses, such as the Velocity template engine. It is quite possible to create applications using just the Servlet API, or by using Struts. For small, simple applications, this is quite reasonable. Likewise, using JSPs can also be effective, at least initially. By simple, I mean applications that do not have a lot of duplicated functionality between pages. As long as the application falls into the category of "form on page A submits into result on page B" the interactions between the servlets (or Actions) and the JSPs are manageable. This is the domain of demos and tutorials, but is rarely the domain of real applications. Real applications have "fixtures", common features that appear on many pages. Real web applications have consistent navigation bars, search forms, login links even banner ads. In the world of JSP, some of these fixtures can be implemented using JSP includes, or as custom JSP tags. For output-only fixtures, such solutions do work. For example, a common fixture may display an error message in a special font, perhaps with a graphical warning symbol. This might be used when validating an input form, to indicate missing values or input errors. Such as fixture could easily be implemented using a custom JSP tag. The more interesting, and problematic, fixtures are interactive. A common example is a "paging component" used on many application pages, to allow the user to page through long lists of results one page at a time. Such a control may have links to jump forwards and backwards through the list of pages and may include a form or other control for controlling how many items are displayed on each page. Building such a component in a flexible way can be a challenge. A paging component will have some internal state: how many items per page? What page in the sequence is being displayed? It must be parameterized so that different sets of data can be displayed using it. To be truly useful, such a component must be reusable throughout the application. Having a component with interactivity is a challenge. Quite often, the component will be used on a page that requires setup before the JSP can render a response. This setup is storing objects as request attributes, so that the JSP can access them perhaps the list of results to be displayed by the paging component is one of these attributes. Making this paging component work requires either that the component has special knowledge of the page that contains it, or that the page has special knowledge of the needs of the component. If the component has its own servlet to handle interactions (such as clicking the "next page" link), then the component needs to be connected, somehow, to the page that contains it, so that it can invoke setup code needed by the page's JSP. This could be another servlet that the paging component must forward to. This second servlet performs setup and, finally, forwards to the JSP to render the response. Alternately, the page may have to provide the component with a servlet to invoke when component interactions occur. This page-provided servlet has to invoke code, provided by the component, to allow the component to update its internal state, and then perform setup and forward to a JSP to render the response. What's going on here is that there is an only tenuous connection between the simple notion of a "page" and the servlets and JSPs that make up the page. If several servlets can each render the same JSP, which of them is the page? Can a JSP that requires setup by a servlet be a page? There needs to be a more formal concept of a page, of a component within a page, and of the setup and render process for the page. These concepts exist formally in Tapestry, but do not exist in the Servlet API, or within Struts. The dispatch model used by the servlets and Struts Actions is purely at the level of identifying an operation. Which object, or objects, to operate on is left open; it is the developers responsibility to define query parameters when constructing URLs, and to interpret those query parameters within the servlet (or Action). This is very much a procedural model, where operations are distinct from data. By contrast, Tapestry's dispatch model is component-oriented; it identifies pages (or components within pages) to trigger behavior in. Linking all these pages and fixtures together purely as URLs and query parameters has its share of pitfalls as well. When coding a traditional, non-servlet, application, the Java compiler can identify many kinds of programming errors, such as a using an incorrect name for a method. This means that errors are caught at compile time. Modern sophisticated IDEs don't even wait that long, they identify errors as soon as the incorrect method name is typed. Likewise, if one developer on a team changes the name or signature of a method, a recompile of the application will generate errors that guide the developer to existing code that must be updated to account for the change to the method. There is a strong, explicit dependency that can be checked at compile time, during development. When the interface between developers is expressed in terms of a URL and query parameters, no such safeguards exist. For example, an application may include search forms on many pages that all submit to a single servlet to perform the search and display the results. If the developer of the search form servlet changes the name of the servlet, or changes the name of any of the query parameters expected by the servlet, this will invisibly break all the uses of the search form on all the pages in the application. This will require searching for affected JSPs and manually fixing them, with no compile-time support that every occurrence was found and fixed. Errors may only be discovered during system testing or worse, in production. Tapestry ensures that these kind of page-to-page interactions occur in Java code. A listener method for each individual search form would invoke methods on the search page to initiate the search and render the response. A change to the method's name or signature would be caught at compile time, just like any traditional Java application. Readership This book is targeted at two camps: Individual developers who want a quick-start to using the Tapestry framework, and team leaders looking for ways to ease the pain of web application development. Readers are expected to have some understanding of the Java Servlet API and a general understanding of Java Server Pages (JSPs). Readers should be familiar with the JavaBeans framework, especially the concept of JavaBeans properties, and how they map to accessor methods. Tapestry makes use of portions of the Java Collections framework (such as Map, List and Iterator). Tap estry uses XML to store specifications of applications, pages and components, so an understanding of XML syntax is expected as well. PAGE 6 PAGE 7 Authors Template Manning Publications Co. PAGE 6 Authors Template Manning Publications Co. PAGE 7 A A &F A A A &F A A A A &F &F &F &F &F &F &F l & &F &F &F & &F A & & ð ð Þaæ¦( XüÆ `Xüo( XüÆ `Xüo( XüÆ `Xüo( A od od íÀ@ Index: index.html =================================================================== RCS file: /cvsroot/tapestry/TapestryBook/doc/index.html,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** index.html 25 Jan 2003 20:16:55 -0000 1.2 --- index.html 8 Feb 2003 02:05:57 -0000 1.3 *************** *** 8,16 **** <p> <ul> ! <li><a href="Chapter-01-Introduction.doc">Chapter 01 - Introduction</a> (Word) <br> - <i>This chapter is likely to be changed quite a bit; some of its content will - be shifted to fore matter, etc.</i> <li><a href="Chapter-02-GettingStarted.doc">Chapter 02 - Getting Started</a> (Word) <ul> --- 8,21 ---- <p> + Status: + Based on Marilyn's notes, I've moved much material from the old "Introduction" chapter into the new Introduction. + I've also moved other material from Chapter 2 (Getting Started) into Chapter 1 (Introducing Tapestry). It's still + in progress! + + <p> <ul> ! <li><a href="Book-Introduction.doc">Introduction</a> (Word) ! <li><a href="Chapter-01-IntroducingTapestry.doc">Chapter 01 - Introducing Tapestry</a> (Word) <br> <li><a href="Chapter-02-GettingStarted.doc">Chapter 02 - Getting Started</a> (Word) <ul> Index: Chapter-02-GettingStarted.doc =================================================================== RCS file: /cvsroot/tapestry/TapestryBook/doc/Chapter-02-GettingStarted.doc,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 Binary files /tmp/cvsjvPl9e and /tmp/cvssenhFm differ --- Chapter-01-Introduction.doc DELETED --- ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com