| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| Copyright 2004, 2005 The Apache Software Foundation |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.2//EN" |
| "http://maven.apache.org/dtd/xdoc_1_0.dtd"> |
| <document> |
| <properties> |
| <title>Introduction</title> |
| </properties> |
| <body> |
| |
| <section name="Introduction" > |
| <p> |
| Tapestry is a component-based web application framework, written in Java. Tapestry |
| is more than a simple templating system; Tapestry builds on the Java Servlet API to |
| build a platform for creating dynamic, interactive web sites. More than just another |
| templating language, Tapestry is a real framework for building complex applications |
| from simple, reusable components. Tapestry offloads much of the error-prone work in |
| creating web applications into the framework itself, taking over mundane tasks such |
| as dispatching incoming requests, constructing and interpretting URLs encoded with |
| information, handling localization and internationalization and much more besides. |
| </p> |
| |
| <p> |
| The "mantra" of Tapestry is "objects, methods and properties". That is, rather than |
| have developers concerned about the paraphanlia of the Servlet API: requests, |
| responses, sessions, attributes, parameters, URLs and so on, Tapestry focuses the |
| developer on objects (including Tapestry pages and components, but also including |
| the domain objects of the application), methods on those objects, and JavaBeans |
| properties of those objects. That is, in a Tapestry application, the actions of the |
| user (clicking links and submitting forms) results in changes to object properties |
| combined with the invocation of user-supplied methods (containing application |
| logic). Tapestry takes care of the plumbing necessary to connect these user actions |
| with the objects. |
| </p> |
| |
| <p> |
| This can take some getting used to. You don't write servlets in Tapestry, you write |
| <a href="listenermethods.html">listener method</a> |
| s. You don't build URLs to servlets either -- you use an existing component (such as |
| <a href="../components/link/directlink.html">DirectLink</a> |
| ) and configure its |
| <code>listener</code> |
| parameter to invoke your listener method. What does a listener method do? It |
| interacts with backend systems (often, stateless session EJBs) or does other |
| bookkeeping related to the request and selects a new page to provide a response to |
| the user ... basically, the core code at the center of a servlet. In Tapestry, you |
| write much less code because all the boring, mechanical plumbing (creating URLs, |
| dispatching incoming requests, managing server-side state, and so forth) is the |
| responsibility of the framework. |
| </p> |
| |
| <p> |
| This is not to say the Servlet API is inaccessible; it is simply not |
| <em>relevant</em> |
| to a typical Tapestry user. |
| </p> |
| |
| <p> |
| This document describes many of the internals of Tapestry. It is not a tutorial, |
| that is available as a separate document. Instead, this is a guide to some of the |
| internals of Tapestry, and is intended for experienced developers who wish to |
| leverage Tapestry fully. |
| </p> |
| |
| <p> |
| Tapestry is currently in release 4.0, and has come a long way in the last couple of |
| years. Tapestry's focus is still on generating dynamic HTML pages, although there's |
| plenty of support for XHTML, WML and other types of markup as well. |
| </p> |
| |
| <p> |
| Nearly all of Tapestry's API is described in terms of interfaces, with default |
| implementations supplied. By substituting new objects with the correct interfaces, |
| the behavior of the framework can be changed significantly. A common example is to |
| override where page and component specifications are stored (perhaps in a database). |
| </p> |
| |
| <p> |
| Finally, Tapestry boasts extremely complete JavaDoc API documentation. This document |
| exists to supplement that documentation, to fill in gaps that may not be obvious. |
| The JavaDoc is often the best reference. |
| </p> |
| |
| <subsection name="An overview of Tapestry" > |
| <p> |
| Perhaps the hardest part of understanding Tapestry is the fact that it is |
| <em>component-centric</em> |
| not |
| <em>operation-centric</em> |
| . Most web technologies ( |
| <a href="http://struts.apache.org/">Struts</a> |
| , servlets, PHP, etc.) are operation-centric. You create servlets (or Actions, |
| or what have you) that are invoked when a user clicks a link or submits a form. |
| You are responsible for selecting an appropriate URL, and the name and type of |
| any query parameters, so that you can pass along the information you need in the |
| URL. |
| </p> |
| |
| <p> |
| You are also responsible for connecting your output pages (whether they are |
| JSPs, |
| <a href="http://jakarta.apache.org/velocity/">Velocity</a> |
| templates, or some other form of templating technology) to those operations. |
| This requires you to construct those URLs and get them into the |
| <code>href</code> |
| attribute of your <a> tag, or into the |
| <code>action</code> |
| attribute of your <form> tag. |
| </p> |
| |
| <p> |
| Everything is different inside Tapestry. Tapestry applications consist of pages; |
| pages are constructed from smaller components. Components may themselves be |
| constructed from other components. Every page has a unique name, and every |
| component within a page has its own unique id ... this is a |
| <em>component object model</em> |
| . Effectively, every component has an |
| <em>address</em> |
| that can easily be incorporated into a URL. |
| </p> |
| |
| <p> |
| In practical terms, your don't write a servlet for the |
| <code>add-item-to-shopping-cart</code> |
| operation. In fact, you don't even write an |
| <code>add-item-to-shopping-cart</code> |
| component. What you do is take an existing component, such as |
| <a href="../components/link/directlink.html">DirectLink</a> |
| , and configure it. When the component renders, it will create a callback URL. |
| When you click that link, the callback URL (which includes the name of the page |
| and the id of the component within the page) will invoke a method on the |
| component ... and |
| <em>that</em> |
| method invokes your application-specific |
| <em>listener method</em> |
| . |
| </p> |
| |
| <span class="info"> |
| <strong>Note:</strong> |
| <p> |
| Listener methods in Tapestry are very similar in intent to |
| <em>delegates</em> |
| in C#. In both cases, a method of a particular object instance is represented as |
| an object. Calling this a "listener" or a "listener method" is a bit of a naming |
| snafu; it should be called a "delegate" and a "delegate method" but the existing |
| naming is too deeply entrenched to change any time soon. |
| </p> |
| </span> |
| |
| <p> |
| You supply just the listener method ... not an entire servlet. Tapestry takes |
| care that your listener method is invoked at the right time, under the right |
| conditions. You don't have to think about how to build that URL, what data goes |
| in the URL, or how to hook it up to your application-specific code--that's all |
| handled by the framework. |
| </p> |
| |
| <img alt="Tapestry request dispatch (high level)" |
| src="../images/UsersGuide/high-level-component-request.png" /> |
| |
| </subsection><!-- intro.overview --> |
| |
| <subsection name="Pages and components"> |
| |
| |
| <p> |
| Tapestry divides an application into a set of pages. Each page is assembled from |
| Tapestry components. Components themselves may be assembled from other |
| components ... there's no artificial depth limit. |
| </p> |
| |
| |
| <p> |
| Tapestry pages are themselves components, but are components with some special |
| responsibilities. |
| </p> |
| |
| <p> |
| All Tapestry components can be containers of other components. Tapestry pages, |
| and most user-defined components, have a template, a special HTML file that |
| defines the static and dynamic portions of the component, with markers to |
| indicate where embedded components are active. Components do not have to have a |
| template, most of the components provided with Tapestry generate their portion |
| of response in code, not using a template. |
| </p> |
| |
| <p> |
| Components may have one or more named parameters which may be set (or, more |
| correctly, "bound") by the page or component which contains them. Unlike Java |
| method parameters, Tapestry component parameters may be bidirectional; a |
| component may read a parameter to obtain a value, or write a parameter to set a |
| value. |
| </p> |
| |
| <p> |
| Most components are concerned only with generating HTML. A certain subset of |
| components deal with the flip-side of requests; handling of incoming requests. |
| Link classes, such as |
| <a href="../components/link/pagelink.html">PageLink</a> |
| and |
| <a href="../components/link/directlink.html">DirectLink</a> |
| create clickable links in the rendered page and are involved in dispatching to |
| user-supplied code when such a link is triggered by clicking it. |
| </p> |
| |
| <p> |
| Other components, |
| <a href="../components/form/form.html">Form</a> |
| , and the form control components ( |
| <a href="../components/form/textfield.html">TextField</a> |
| , |
| <a href="../components/form/propertyselection.html">PropertySelection</a> |
| , |
| <a href="../components/form/checkbox.html">Checkbox</a> |
| , etc.), facilitate HTML forms. When such components render, they read |
| properties from application objects so as to provide default values. When the |
| forms are submitted, the components within the form read HTTP query parameters, |
| convert the values to appropriate types and then update properties of |
| application objects. |
| </p> |
| |
| </subsection><!-- intro.pages-and-components --> |
| |
| <subsection name="Engines, services and friends"> |
| |
| |
| <p>Tapestry has evolved its own jargon over time.</p> |
| |
| <p> |
| The Engine is a central object, it occupies the same semantic space in Tapestry |
| that the HttpSession does in the Servlet API. The Engine is ultimately |
| responsible for storing the persistent state of the application (properties that |
| exist from one request to the next), and this is accomplished by storing the |
| Engine into the HttpSession. This document will largely discuss the |
| <em>default</em> |
| implementation, with notes about how the default implementation may be extended |
| or overriden, where appropriate. |
| </p> |
| |
| <p> |
| Engine services are the bridge between servlets and URLs and the rest of |
| Tapestry. Engine services are responsible for encoding URLs, providing query |
| parameters that identify, to the framework, the exact operation that should |
| occur when the generated URL is triggered (by the end user clicking a link or |
| submitting a form). Services are also responsible for dispatching those incoming |
| requests. This encapsulation of URL encoding and decoding inside a single object |
| is key to how Tapestry components can flexibily operate without concern for how |
| they are contained and on which page ... the services take into account page and |
| location when formulating URLs. |
| </p> |
| |
| <p> |
| The |
| <a href="state.html#state.visit">Visit object</a> |
| is an application-defined object that acts as a focal point for all server-side |
| state (not associated with any single page). Individual applications define for |
| themselves the class of the Visit object. The Visit is stored as a property of |
| the Engine, and so is ultimately stored persistently in the HttpSession. |
| </p> |
| |
| <p> |
| The |
| <a href="state.html#state.global">Global object</a> |
| is also application-specific. It stores information global to the entire |
| application, independent of any particular user or session. A common use for the |
| Global object is to centralize logic that performs JNDI lookups of session EJBs. |
| </p> |
| |
| </subsection><!-- intro.engine-service-visit --> |
| |
| <subsection name="Object Graph Navigation Language"> |
| |
| |
| <p> |
| Tapestry is tightly integrated with |
| <a href="http://www.ognl.org">OGNL</a> |
| , the Object Graph Navigation Language. OGNL is a Java expression language, |
| which is used to peek into objects and read or update their properties. OGNL is |
| similar to, and must more powerful than, the expression language built into the |
| JSP 2.0 standard tag library. OGNL not only support property access, it can |
| include mathematical expressions and method invocations. It can reference static |
| fields of public classes. It can create new objects, including lists and maps. |
| </p> |
| |
| <p> |
| The simplest OGNL expressions are property names, such as |
| <code>foo</code> |
| , which is equivalent to method |
| <code>getFoo()</code> |
| (or |
| <code>setFoo()</code> |
| if the expression is being used to update a property). The "Navigation" part |
| comes into play when the expression is a series of property names, such as |
| <code>foo.bar.baz</code> |
| , which is equivalent to |
| <code>getFoo().getBar().getBaz()</code> |
| ... though care must always be taken that the intermediate properties ( |
| <code>foo</code> |
| and |
| <code>bar</code> |
| in this example) are not null. |
| </p> |
| |
| <p> |
| OGNL is primarily used to allow two different objects (such as a page and a |
| component contained by that page) to share information. |
| </p> |
| |
| </subsection><!-- intro.ognl --> |
| |
| <subsection name="Tapestry Past, Tapestry Future"> |
| |
| |
| <p> |
| Since its initial introduction in early 2000, Tapestry has been in a constant |
| state of evolution, driven by feedback from its community. Tapestry took a big |
| leap forward in 2003. During that period, the Tapestry project moved from |
| <a href="http://sf.net">SourceForge</a> |
| to |
| <a href="http://jakarta.apache.org">Jakarta</a> |
| . This was also the transition from release 2.3 to release 3.0 (the final 3.0 |
| release occuring in April 2004). |
| </p> |
| |
| <p> |
| Tapestry 3.0 was designed to radically change how Tapestry applications were |
| created. It introduced a kind of RAD (Rapid Application Development) support in |
| the form of |
| <a href="template.html#template.components">implicit components</a> |
| ... a way of specifying a component's type and parameters in place in the HTML |
| template, which is much more familiar to JSP and PHP developers. |
| </p> |
| |
| <p> |
| Tapestry 3.0 also saw the introduction of |
| <em>line precise error reporting</em> |
| , in which runtime errors are related back to relevant lines in the HTML |
| template or specification file. Further, 3.0 introduced the |
| <a href="spec.html#spec.property"><property></a> |
| element, and the |
| <em>bytecode enhancement</em> |
| technology behind it. |
| </p> |
| |
| <p> |
| Tapestry 4.0 represents an even more radical leap beyond 3.0 by introducing a |
| new, sophisticated infrastructure on top of the |
| <a href="http://hivemind.apache.org/hivemind1/">HiveMind</a> |
| microkernel. This new backbone provides the support necessary to meet the needs |
| of Tapestry's much larger community ... including support for |
| <em>prettier</em> |
| URLs, integration of Tapestry and the Java Portlet API, and modularization of |
| applications (allowing the use of folders, and thus, J2EE declarative security). |
| In addition, a more sophisticated approach to implementing connected parameter |
| properties has been introduced in release 4.0, and more flexibility for storing |
| session-specific state as HTTP query parameters has been provided. For JDK 1.5 |
| users, the XML page and component specifications can now be sidelined in favor |
| of Java annotations. |
| </p> |
| |
| <p> |
| A further future direction, in the Tapestry 5.0 timeframe (the far future), is |
| to rethink the component object model such that the classes |
| <em>you</em> |
| write do not sub-class Tapestry base classes. Page and component Java classes |
| will be simple POJOs (Plain Old Java Objects) and will have any Tapestry |
| dependencies |
| <em>injected</em> |
| into them. |
| </p> |
| |
| </subsection> |
| |
| </section> |
| </body> |
| </document> |