You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2006/07/04 00:49:00 UTC

svn commit: r418868 [1/2] - in /tapestry/tapestry4/trunk: ./ framework/src/java/org/apache/tapestry/html/ src/site/ src/site/resources/css/ src/site/resources/images/ src/site/xdoc/ src/site/xdoc/QuickStart/ src/site/xdoc/exampleapps/ src/site/xdoc/exa...

Author: jkuhnert
Date: Mon Jul  3 15:48:59 2006
New Revision: 418868

URL: http://svn.apache.org/viewvc?rev=418868&view=rev
Log:
Updated documentation

Added:
    tapestry/tapestry4/trunk/src/site/resources/images/autocompleter.png   (with props)
    tapestry/tapestry4/trunk/src/site/xdoc/exampleapps/
      - copied from r418860, tapestry/tapestry4/trunk/src/site/xdoc/examples/
Removed:
    tapestry/tapestry4/trunk/src/site/xdoc/examples/
Modified:
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc
    tapestry/tapestry4/trunk/pom.xml
    tapestry/tapestry4/trunk/src/site/resources/css/site.css
    tapestry/tapestry4/trunk/src/site/site.xml
    tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/directlink.xml
    tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/forms.xml
    tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/helloworld.xml
    tapestry/tapestry4/trunk/src/site/xdoc/changes.xml
    tapestry/tapestry4/trunk/src/site/xdoc/exampleapps/index.xml
    tapestry/tapestry4/trunk/src/site/xdoc/index.xml

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc?rev=418868&r1=418867&r2=418868&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc Mon Jul  3 15:48:59 2006
@@ -115,7 +115,7 @@
   </parameter>
   
   <parameter name="ajaxEnabled" 
-             default-value="false" >
+             default-value="true" >
      <description>
      If set to true, will include the required javascript libraries that make all
      of the ajax functionality possible.

Modified: tapestry/tapestry4/trunk/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/pom.xml?rev=418868&r1=418867&r2=418868&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/pom.xml (original)
+++ tapestry/tapestry4/trunk/pom.xml Mon Jul  3 15:48:59 2006
@@ -255,6 +255,7 @@
                             <report>license</report>
                             <report>scm</report>
                             <report>index</report>
+                            <report>dependencies</report>
                         </reports>
                     </reportSet>
                 </reportSets>

Modified: tapestry/tapestry4/trunk/src/site/resources/css/site.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/resources/css/site.css?rev=418868&r1=418867&r2=418868&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/src/site/resources/css/site.css (original)
+++ tapestry/tapestry4/trunk/src/site/resources/css/site.css Mon Jul  3 15:48:59 2006
@@ -3,10 +3,6 @@
     padding-right: 0;
 }
 
-body {
-    font-family: Lucida Grande, Arial, Helvetica, sans-serif;
-}
-
 body ul {
     list-style-type: square;
 }
@@ -42,35 +38,6 @@
     font-size: smaller;
 }
 
-.info {
-    float: left;
-    display: block;
-    margin: 0 1em 2em 2em;
-    padding: 1em;
-    border: 1px solid #aaa;
-    background-color: #efefef;
-}
-
-.warn {
-    float: left;
-    display: block;
-    margin: 0 1em 2em 2em;
-    padding: 1em;
-    border: 2px solid #474747;
-    background-color: #B8AC30;
-}
-
-.section p a {
-    color: #539126;
-    font-weight: bolder;
-}
-
-.section p a:hover {
-    text-decoration: underline;
-}
-
-code {
-    border: 1px dotted #aaa;
-    background: #efefef;
-    padding: 1px;
-}
+.section ul li {
+    margin-top: 8px;
+}
\ No newline at end of file

Added: tapestry/tapestry4/trunk/src/site/resources/images/autocompleter.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/resources/images/autocompleter.png?rev=418868&view=auto
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry4/trunk/src/site/resources/images/autocompleter.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: tapestry/tapestry4/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/site.xml?rev=418868&r1=418867&r2=418868&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/src/site/site.xml (original)
+++ tapestry/tapestry4/trunk/src/site/site.xml Mon Jul  3 15:48:59 2006
@@ -39,26 +39,36 @@
         </menu>
         
         <menu name="Documentation" inherit="top">
+            
             <item name="Users Guide" href="/UsersGuide/index.html" collapse="true">
-                <item name="Introduction" href="/UsersGuide/index.html" collapse="true"/>
-                <item name="Templates" href="/UsersGuide/template.html" collapse="true"/>
-                <item name="Bindings" href="/UsersGuide/bindings.html" collapse="true"/>
-                <item name="Listeners" href="/UsersGuide/listenermethods.html" collapse="true"/>
-                <item name="Page Classes" href="/UsersGuide/page-class.html" collapse="true"/>
-                <item name="Input Validation" href="/UsersGuide/validation.html" collapse="true" />
-                <item name="Creating Components" href="/UsersGuide/components.html" collapse="true"/>
-                <item name="Property Injection" href="/UsersGuide/injection.html" collapse="true"/>
-                <item name="Localization" href="/UsersGuide/localization.html" collapse="true"/>
-                <item name="State Management" href="/UsersGuide/state.html" collapse="true"/>
-                <item name="IOC (HiveMind)" href="/UsersGuide/hivemind.html" collapse="true"/>
-                <item name="Friendly URLs" href="/UsersGuide/friendly-urls.html" collapse="true"/>
-                <item name="Page Events" href="/UsersGuide/events.html" collapse="true"/>
-                <item name="Configuration" href="/UsersGuide/configuration.html" collapse="true"/>
-                <item name="Shared Properties" href="/UsersGuide/properties.html" collapse="true"/>
-                <item name="Upgrading from 3.0" href="/UsersGuide/upgrade.html" collapse="true"/>
-                <item name="Specification DTD" href="/UsersGuide/spec.html" collapse="true"/>
-                <item name="Script Template DTD" href="/UsersGuide/script.html" collapse="true"/>
+                <item name="Introduction" href="/UsersGuide/index.html" />
+                <item name="Templates" href="/UsersGuide/template.html" />
+                <item name="Bindings" href="/UsersGuide/bindings.html" />
+                <item name="Listeners" href="/UsersGuide/listenermethods.html" />
+                <item name="Page Classes" href="/UsersGuide/page-class.html" />
+                <item name="Input Validation" href="/UsersGuide/validation.html"  />
+                <item name="Creating Components" href="/UsersGuide/components.html" />
+                <item name="Property Injection" href="/UsersGuide/injection.html" />
+                <item name="Localization" href="/UsersGuide/localization.html" />
+                <item name="State Management" href="/UsersGuide/state.html" />
+                <item name="IOC (HiveMind)" href="/UsersGuide/hivemind.html" />
+                <item name="Friendly URLs" href="/UsersGuide/friendly-urls.html" />
+                <item name="Page Events" href="/UsersGuide/events.html" />
+                <item name="Configuration" href="/UsersGuide/configuration.html" />
+                <item name="Shared Properties" href="/UsersGuide/properties.html" />
+                <item name="Upgrading from 3.0" href="/UsersGuide/upgrade.html" />
+                <item name="Specification DTD" href="/UsersGuide/spec.html" />
+                <item name="Script Template DTD" href="/UsersGuide/script.html" />
             </item>
+            
+            <item name="Quick Start" href="/QuickStart/helloworld.html" collapse="true">
+                <item name="Hello World" href="/QuickStart/helloworld.html" />
+                <item name="Direct Links" href="/QuickStart/directlink.html" />
+                <item name="Forms" href="/QuickStart/forms.html" />
+            </item>
+            
+            <item name="Examples" href="/exampleapps/index.html" />
+            
         </menu>
         
         <menu ref="modules" />

Modified: tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/directlink.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/directlink.xml?rev=418868&r1=418867&r2=418868&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/directlink.xml (original)
+++ tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/directlink.xml Mon Jul  3 15:48:59 2006
@@ -1,51 +1,50 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 
-   Copyright 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.
+    Copyright 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.
 -->
 <document>
-<properties>
-<title>QuickStart: DirectLink</title>
-</properties>
-<body>
-  
-<p>
-  In this tutorial, we'll get introduced to one of the real workhorses of Tapestry, the <a href="site:DirectLink">DirectLink</a>
-  component. It is one of the most common ways of triggering server-side behavior.  Along the way,
-  we'll start seeing some other common aspects of developing web applications using Tapestry.
-</p>
+    <properties>
+        <title>QuickStart: DirectLink</title>
+    </properties>
+    <body>
+        
+        <section name="QuickStart: DirectLink">
+        <p>
+            In this tutorial, we'll get introduced to one of the real workhorses of Tapestry, the
+            <a href="site:DirectLink">DirectLink</a>
+            component. It is one of the most common ways of triggering server-side behavior. Along
+            the way, we'll start seeing some other common aspects of developing web applications
+            using Tapestry.
+        </p>
+        
+        <section name="HTML Template">
 
-<section name="HTML Template">
-  
-  
-<p>
-  This application simply counts the number of times we click a link.
-</p>  
 
-<img src="../images/QuickStart/directlink1.png" alt="Initial DirectLink Tutorial"/>
-  
-<p>
-  This requires a little more than we can accomplish with just an HTML template; we'll need
-  to supplement with a Java class.  This java class will contain a property that stores the count,
-  and contain logic used to increment the count.
-</p>  
-  
-<p>
-  We'll start again with the Home page's template:
-</p>  
-  
-<source xml:space="preserve">
+            <p>This application simply counts the number of times we click a link.</p>
+
+            <img src="../images/QuickStart/directlink1.png" alt="Initial DirectLink Tutorial" />
+
+            <p>
+                This requires a little more than we can accomplish with just an HTML template; we'll
+                need to supplement with a Java class. This java class will contain a property that
+                stores the count, and contain logic used to increment the count.
+            </p>
+
+            <p>We'll start again with the Home page's template:</p>
+
+            <source xml:space="preserve">
 &lt;html&gt;
   &lt;head&gt;
     &lt;title&gt;Tutorial: DirectLink&lt;/title&gt;
@@ -68,47 +67,53 @@
         
   &lt;/body&gt;
 &lt;/html&gt;  
-</source>  
-  
-<p>
-  Much of this should look familiar. We're again using the <a href="site:Insert">Insert</a> component, and we're using
-  <a href="http://www.ognl.org">OGNL</a> again. Instead of creating a new instance, we're using OGNL in a simpler way; it will
-  read the counter property and provide that to the Insert  component
-  in its value parameter.
-</p>
-  
-<p>
-  That's fine, but where does this counter property live?  In the Home page's Java class. We'll see how
-  to create that class shortly.
-</p>  
-
-<p>
-  Just displaying the current value isn't enough, we need a way to change that value.  That's where
-  the <a href="site:DirectLink">DirectLink</a> component comes in; it will invoke a method of our Java class for us.
-  This connection between component and method is supplied in the listener parameter. 
-  The "listener:" prefix activates the logic that lets Tapestry invoke the method
-  with the matching name.
-  We provide a method,  doClick(), in the page's Java class, and the DirectLink
-  component will invoke this method for us, in response to the user clicking the rendered link in their web browser.
-</p>
-
-  
-</section>
+</source>
 
-<section name="Page classes">
-  
-  
-<p>
-  So, we have half the puzzle: the HTML template. But we need the Java class that will contain the
-  properties to be stored, and the methods to be invoked.
-</p>
-
-<p>
-  First, we need a Java package to store the class.  For this tutorial, we'll use tutorials.directlink.pages. That means
-  we'll create the Home.java source file as src/java/tutorials/directlink/pages/Home.java:
-</p>
+            <p>
+                Much of this should look familiar. We're again using the
+                <a href="site:Insert">Insert</a>
+                component, and we're using
+                <a href="http://www.ognl.org">OGNL</a>
+                again. Instead of creating a new instance, we're using OGNL in a simpler way; it
+                will read the counter property and provide that to the Insert component in its value
+                parameter.
+            </p>
+
+            <p>
+                That's fine, but where does this counter property live? In the Home page's Java
+                class. We'll see how to create that class shortly.
+            </p>
+
+            <p>
+                Just displaying the current value isn't enough, we need a way to change that value.
+                That's where the
+                <a href="site:DirectLink">DirectLink</a>
+                component comes in; it will invoke a method of our Java class for us. This
+                connection between component and method is supplied in the listener parameter. The
+                "listener:" prefix activates the logic that lets Tapestry invoke the method with the
+                matching name. We provide a method, doClick(), in the page's Java class, and the
+                DirectLink component will invoke this method for us, in response to the user
+                clicking the rendered link in their web browser.
+            </p>
+
+
+        </section>
+
+        <section name="Page classes">
+
+
+            <p>
+                So, we have half the puzzle: the HTML template. But we need the Java class that will
+                contain the properties to be stored, and the methods to be invoked.
+            </p>
+
+            <p>
+                First, we need a Java package to store the class. For this tutorial, we'll use
+                tutorials.directlink.pages. That means we'll create the Home.java source file as
+                src/java/tutorials/directlink/pages/Home.java:
+            </p>
 
-<source xml:space="preserve">
+            <source xml:space="preserve">
 package tutorials.directlink.pages;
 
 import org.apache.tapestry.annotations.Persist;
@@ -131,137 +136,172 @@
 }
 </source>
 
-<p>
-  The Java classes you write will extend from the Tapestry BasePage class<sup>1</sup>. 
-  To this base class, we are adding a property, counter, and a listener method, doClick()<sup>2</sup>.
-</p>  
-
-
-<p>
-  <em>Abstract? What's up with that?</em> That's a pretty typical first reaction to seeing a Tapestry page class; why is it
-  abstract, why is it not an ordinary JavaBean?
-</p>
-
-<p>
-  The answer involves a bit of a digression.  Tapestry pages exist on the server, and are somewhat expensive
-  to create ... expensive enough that you don't want to constantly create them and discard them. In this way,
-  they are much like database connections ... you want to pool pages for reuse from one request to the next.
-</p>
-
-<p>
-  Because the pages are pooled and shared, in fact shared <em>between different users</em>, it's very important
-  that they page objects be cleansed of any user-specific or request-specific data before they go back
-  into the pool.  You can do this in your own code (there are additional interfaces to implement and additional
-  code to write), but it is <em>easier</em> to let Tapestry do that work for you.  
-</p> 
-
-<p>
-  By declaring an accessor method as abstract, you are implicitly directing Tapestry to
-  "fill in" the details; at <em>runtime</em>, it will create a subclass of the Java class you provide,
-  extending your implementation with all the grinding details.  As well see in later tutorials,
-  this in fact goes far beyond just properties; all sorts of useful features can be tied to
-  different flavors of abstract methods (often coupled with different 
-  <a href="../tapestry-annotations/index.html">annotations</a>).
-</p>
-
-<p>
-  There's something special about this counter property. It has to remember its value
-  <em>between</em> requests.  The @Persist annotation, attached to the getCounter() accessor method,
-  directs Tapestry to make this a <em>persistent page property</em>.  Despite the name, this has nothing to do
-  with database persistence, it's about storing the value for the property in the
-  HttpSession between requests, and restoring it the next time that the same user, in the same session, 
-  accesses the page.
-</p>
-
-<p>
-  This is another pivotal feature in Tapestry; individual page properties (or properties of components
-  used within the page) can store their value in the HttpSession automatically. We can seperate out
-   the persistent state of the page from any <em>instance</em> of the page. This minimizes the
-   amount of information that must be stored in the HttpSession; rather than entire page objects (with all
-   those templates and nested components), we store just the tiny handful of properties that need
-   to "stick around" until the next request.
-</p>
-
-<p>
-  This approach to session management, combined with the pooling of page instances, is critical to
-  achieving another of Tapestry fundamental principals: <strong>Efficiency</strong>.  Tapestry
-  applications will scale because of how they manage server-side state.  The cost of this
-  is that the classes and methods are abstract, with the implementations of many methods only provided dynamically,
-  by Tapestry, at runtime.
-</p>
-
-<p>
-  Back from our digression. We now have the counter property, and we understand how it is stored in the
-  HttpSession between requests.  That makes the implementation of the doClick() listener method straight
-  forward: get the current value for the proeprty, increment it, and store it back into the property.
-</p>
-
-<p>
-  Again, we're demonstrating part of our promise about Tapestry: we're talking about objects and methods
-  and properties.  There's a URL in there, generated by Tapestry, for the DirectLink.  There's 
-  attributes stored in the HttpSession.  We don't see those or care about them.
-</p>
-
-</section>
+            <p>
+                The Java classes you write will extend from the Tapestry BasePage class
+                <sup>1</sup>
+                . To this base class, we are adding a property, counter, and a listener method,
+                doClick()
+                <sup>2</sup>
+                .
+            </p>
+
+
+            <p>
+                <em>Abstract? What's up with that?</em>
+                That's a pretty typical first reaction to seeing a Tapestry page class; why is it
+                abstract, why is it not an ordinary JavaBean?
+            </p>
+
+            <p>
+                The answer involves a bit of a digression. Tapestry pages exist on the server, and
+                are somewhat expensive to create ... expensive enough that you don't want to
+                constantly create them and discard them. In this way, they are much like database
+                connections ... you want to pool pages for reuse from one request to the next.
+            </p>
+
+            <p>
+                Because the pages are pooled and shared, in fact shared
+                <em>between different users</em>
+                , it's very important that they page objects be cleansed of any user-specific or
+                request-specific data before they go back into the pool. You can do this in your own
+                code (there are additional interfaces to implement and additional code to write),
+                but it is
+                <em>easier</em>
+                to let Tapestry do that work for you.
+            </p>
+
+            <p>
+                By declaring an accessor method as abstract, you are implicitly directing Tapestry
+                to "fill in" the details; at
+                <em>runtime</em>
+                , it will create a subclass of the Java class you provide, extending your
+                implementation with all the grinding details. As well see in later tutorials, this
+                in fact goes far beyond just properties; all sorts of useful features can be tied to
+                different flavors of abstract methods (often coupled with different
+                <a href="../tapestry-annotations/index.html">annotations</a>
+                ).
+            </p>
+
+            <p>
+                There's something special about this counter property. It has to remember its value
+                <em>between</em>
+                requests. The @Persist annotation, attached to the getCounter() accessor method,
+                directs Tapestry to make this a
+                <em>persistent page property</em>
+                . Despite the name, this has nothing to do with database persistence, it's about
+                storing the value for the property in the HttpSession between requests, and
+                restoring it the next time that the same user, in the same session, accesses the
+                page.
+            </p>
+
+            <p>
+                This is another pivotal feature in Tapestry; individual page properties (or
+                properties of components used within the page) can store their value in the
+                HttpSession automatically. We can seperate out the persistent state of the page from
+                any
+                <em>instance</em>
+                of the page. This minimizes the amount of information that must be stored in the
+                HttpSession; rather than entire page objects (with all those templates and nested
+                components), we store just the tiny handful of properties that need to "stick
+                around" until the next request.
+            </p>
+
+            <p>
+                This approach to session management, combined with the pooling of page instances, is
+                critical to achieving another of Tapestry fundamental principals:
+                <strong>Efficiency</strong>
+                . Tapestry applications will scale because of how they manage server-side state. The
+                cost of this is that the classes and methods are abstract, with the implementations
+                of many methods only provided dynamically, by Tapestry, at runtime.
+            </p>
+
+            <p>
+                Back from our digression. We now have the counter property, and we understand how it
+                is stored in the HttpSession between requests. That makes the implementation of the
+                doClick() listener method straight forward: get the current value for the proeprty,
+                increment it, and store it back into the property.
+            </p>
+
+            <p>
+                Again, we're demonstrating part of our promise about Tapestry: we're talking about
+                objects and methods and properties. There's a URL in there, generated by Tapestry,
+                for the DirectLink. There's attributes stored in the HttpSession. We don't see those
+                or care about them.
+            </p>
+
+        </section>
+
+        <section name="Locating the page class">
+
+
+            <p>
+                We've provided the Home page's template and Java class, but we haven't quite
+                connected the dots enough for our application to run. If we tried to run the
+                application (by opening a web browser to
+                <a href="http://localhost:8080/directlink/app">
+                    http://localhost:8080/directlink/app
+                </a>
+                ), we'd get the Tapestry exception page:
+            </p>
+
+            <img src="../images/QuickStart/directlink2.png"
+                alt="Exception report - missing property" />
+
+            <p>
+                That's quite a lot of information. The root cause of the exception is the fact that
+                Tapestry couldn't find the Home class we created, so it instead used BasePage as-is.
+                BasePage doesn't have a counter property, so the OGNL expression
+                <code>counter</code>
+                couldn't be evaluated (you can see that in the deepest exception). You can see in
+                the target property of the ognl.NoSuchPropertyException, the value
+                <code>$BasePage_0@cec78d[Home]</code>
+                is the toString() of a page class; the first part is the name of the class
+                (remember, this is a subclass generated at runtime by Tapestry), the value in
+                brackets is the name of the page.
+            </p>
+
+            <p>
+                This exception bubbled up to the top-level of Tapestry, getting wrapped inside other
+                exceptions along the way. The framework couldn't continue with the Home page, so it
+                generated this exception report instead.
+            </p>
+
+
+            <p>
+                As you can see, the exception report is quite detailed; it shows the entire stack of
+                exceptions, including their properties. It identifies the file and line at the root
+                of the problem, and even displays an excerpt from that file. Further down on the
+                page are exhaustive details about all the Servlet API objects ... in short you are
+                given all the information you need to understand what was going on in your
+                application at the time of the failure, without having to restart using a debugger.
+                This is another Tapestry priciple in action:
+                <strong>Feedback</strong>
+                . When things go wrong, Tapestry should help you fix your problem, rather than get
+                in the way.
+            </p>
+
+            <p>
+                So, the root of our problem is that Tapestry can't find our Home page, so we need to
+                tell it where to look. This involves providing Tapestry with a little bit of
+                configuration about our application.
+            </p>
+
+            <p>
+                We'll create an
+                <em>application specification</em>
+                for our application, and store the configuration data there. An application
+                specification is an XML file that provides extra information about the application
+                to Tapestry. It is optional; we didn't have one in the previous example.
+            </p>
+
+            <p>
+                The name of the servlet ("app", in this example) is appended with the extension
+                ".application" to form the name of the specification. The specification itself is
+                stored in the WEB-INF folder of the web application. In our project, it is stored as
+                src/context/WEB-INF/app.application:
+            </p>
 
-<section name="Locating the page class">
-  
-  
-<p>
-  We've provided the Home page's template and Java class, but we haven't quite connected the dots enough
-  for our application to run.  If we tried to run the application (by opening a web browser to
-  <a href="http://localhost:8080/directlink/app">http://localhost:8080/directlink/app</a>), we'd get the Tapestry
-  exception page:
-</p>  
-
-<img src="../images/QuickStart/directlink2.png" alt="Exception report - missing property"/>
-
-<p>
-That's quite a lot of information.  The root cause of the exception is the fact
-that Tapestry couldn't find the Home class we 
-created, so it instead used BasePage as-is.  BasePage doesn't have a counter property, so the OGNL expression
-<code>counter</code> couldn't be evaluated (you can see that in the deepest exception).  You can see in the
-target property of the ognl.NoSuchPropertyException, the value <code>$BasePage_0@cec78d[Home]</code> is the 
-toString() of a page class; the first part is the name of the class (remember, this is a subclass
-generated at runtime by Tapestry), the value in brackets is the name of the page.
-</p>
-
-<p>
-  This exception bubbled up to the top-level of Tapestry, getting wrapped inside other exceptions
-  along the way.  The framework couldn't continue with the Home page, so it generated this exception
-  report instead.
-</p>
-
-
-<p>
-  As you can see, the exception report is quite detailed; it shows the entire stack of exceptions,
-  including their properties.  It identifies the file and line at the root of the problem,
-  and even displays an excerpt from that file.  Further down on the page are exhaustive details about
-  all the Servlet API objects ... in short you are given all the information you need to understand what
-  was going on in your application at the time of the failure, without having to restart using
-  a debugger.  This is another Tapestry priciple in action: <strong>Feedback</strong>. When things go wrong, Tapestry
-  should help you fix your problem, rather than get in the way.
-</p>
-
-<p>
-  So, the root of our problem is that Tapestry can't find our Home page, so we need to tell it where
-  to look.  This involves providing Tapestry with a little bit of configuration about our application.
-</p>
-
-<p>
-  We'll create an <em>application specification</em> for our application, and store the configuration
-  data there.  An application specification is an XML file that provides extra information about the application
-  to Tapestry.  It is optional; we didn't have one in the previous example.
-</p>
-
-<p>
-  The name of the servlet ("app", in this example) is appended with the extension ".application" to
-  form the name of the specification.  The specification itself is stored in the 
-  WEB-INF folder of the web application.  In our project, it is stored as
-  src/context/WEB-INF/app.application:
-</p>
-
-<source xml:space="preserve">
+            <source xml:space="preserve">
 &lt;?xml version="1.0"?&gt;
 &lt;!DOCTYPE application PUBLIC 
   "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
@@ -273,166 +313,185 @@
 &lt;/application&gt;
 </source>
 
-<p>Application specifications are validated XML files, with a real DTD (at the specified
-  location). The &lt;meta&gt; element is used to specify meta data ... configuration data that
-  doesn't fit in elsewhere.  Here we're using it to inform Tapestry about which
-  Java packages to search for pages. This value can even be a comma-seperated list of packages, if there is more
-  than one package to search.</p>
-  
-<p>
-  With this file in place, Tapestry has all it needs to run our application: the Home page's HTML template, its
-  Java class, at the connection between the two. Now, let's look at improving our example a bit.
-</p>  
-  
-</section>
-  
-<section name="Understanding DirectLink URLs">
-  
-  
-<p>
-  The URLs generated by the DirectLink component are more complex than those generated by the
-  PageLink component. Let's look at one:
-</p>  
+            <p>
+                Application specifications are validated XML files, with a real DTD (at the
+                specified location). The &lt;meta&gt; element is used to specify meta data ...
+                configuration data that doesn't fit in elsewhere. Here we're using it to inform
+                Tapestry about which Java packages to search for pages. This value can even be a
+                comma-seperated list of packages, if there is more than one package to search.
+            </p>
+
+            <p>
+                With this file in place, Tapestry has all it needs to run our application: the Home
+                page's HTML template, its Java class, at the connection between the two. Now, let's
+                look at improving our example a bit.
+            </p>
+
+        </section>
+
+        <section name="Understanding DirectLink URLs">
+
+
+            <p>
+                The URLs generated by the DirectLink component are more complex than those generated
+                by the PageLink component. Let's look at one:
+            </p>
 
-<source xml:space="preserve">
+            <source xml:space="preserve">
 http://localhost:8080/directlink/app?component=%24DirectLink&amp;page=Home&amp;service=direct&amp;session=T
 </source>
 
-<p>
-The first query parameter, component, identifies the component within the page. That %24 is "URL-ese" for a dollar sign.
-In Tapestry, every component ends up with a unique id within its page. If you don't provide one, Tapestry
-creates one from the component type, prefixed with a dollar sign.  Here, our annoynmous DirectLink component was given the id $DirectLink.  
-If you had many different DirectLinks on a page, you'd start seeing
-component ids such as $DirectLink_0, $DirectLink_1, etc.
-</p>
-
-<p>
-  You can give a component a shorter and more mneumonic id by putting the desired id before the "@" sign:
-</p>
+            <p>
+                The first query parameter, component, identifies the component within the page. That
+                %24 is "URL-ese" for a dollar sign. In Tapestry, every component ends up with a
+                unique id within its page. If you don't provide one, Tapestry creates one from the
+                component type, prefixed with a dollar sign. Here, our annoynmous DirectLink
+                component was given the id $DirectLink. If you had many different DirectLinks on a
+                page, you'd start seeing component ids such as $DirectLink_0, $DirectLink_1, etc.
+            </p>
+
+            <p>
+                You can give a component a shorter and more mneumonic id by putting the desired id
+                before the "@" sign:
+            </p>
 
-<source xml:space="preserve">
+            <source xml:space="preserve">
   &lt;a href="#" jwcid="inc@DirectLink" listener="listener:doClick"&gt;increment counter&lt;/a&gt;
 </source>
 
-<p>
-After making that change to the template, the URL for the DirectLink component is just a bit easier to read:
-</p>
+            <p>
+                After making that change to the template, the URL for the DirectLink component is
+                just a bit easier to read:
+            </p>
 
-<source xml:space="preserve">
+            <source xml:space="preserve">
 http://localhost:8080/directlink/app?component=inc&amp;page=Home&amp;service=direct&amp;session=T
 </source>
 
-<p>
-The other changes from the previous examples are the service query parameter and the session query parameter.
-The service query parameter indicates that the processing of the request is different than 
-for a link created by the PageLink component.  Here
-we need to get a page, find a component in the page and invoke a listener method <em>before</em> we can render
-the response.  With PageLink, we just get the page and render it.
-</p>
-
-<p>
-  Lastly, the session query parameter indicates whether there was an HttpSession at the time the link was rendered.
-  Tapestry uses this to detect when the HttpSession expired ... perhaps because the user walked away from the 
-  computer for a while before clicking the link.  If the application was stateless (no HttpSession) when this link
-  was generated, then the session parameter simply wouldn't appear in the URL.
-</p>
-
-<p>
-  One thing to take note of is that the method name <em>is not</em> part of the URL, just the id of the 
-  component. This is very desirable ... why expose more of the construction of your application than 
-  you have to? As importantly, this helps to prevent malicious users from subverting your application; there
-  simply isn't a way to get an arbitrary listener method to be invoked, only one that you, as the developer, wired
-  to a specific component.
-</p>
-
-<p>
-  These are what Tapestry pros call "ugly URLs".  The ugly part is the use of query parameters, rather than paths,
-  to express the information in the URL.  Ugly URLs can cause some problems; since the entire application is
-  routed through the /app path, it's hard to apply J2EE declarative security.  Likewise, the use
-  of query parameters means that most search engines will not spider the site.  The solution is
-  to
-  use "friendly URLs"<sup>3</sup>, which is covered in a later tutorial.
-</p>
-
-
-</section>  
-
-<section name="Adding more links">
-  
-  
-<p>
-  This application is good, but we should have a way to reset the counter back to zero. We're going to
-  add a link to the page to do just that.  The end result will look like:
-</p>  
-
-<img src="../images/QuickStart/directlink3.png" alt="Tutorial with clear link"/>
-
-<p>
-  To accomplish this we need to add another link to the Home page's HTML template, and connect that
-  to logic expressed as a new method on the Home page class.  First the template:
-</p>
+            <p>
+                The other changes from the previous examples are the service query parameter and the
+                session query parameter. The service query parameter indicates that the processing
+                of the request is different than for a link created by the PageLink component. Here
+                we need to get a page, find a component in the page and invoke a listener method
+                <em>before</em>
+                we can render the response. With PageLink, we just get the page and render it.
+            </p>
+
+            <p>
+                Lastly, the session query parameter indicates whether there was an HttpSession at
+                the time the link was rendered. Tapestry uses this to detect when the HttpSession
+                expired ... perhaps because the user walked away from the computer for a while
+                before clicking the link. If the application was stateless (no HttpSession) when
+                this link was generated, then the session parameter simply wouldn't appear in the
+                URL.
+            </p>
+
+            <p>
+                One thing to take note of is that the method name
+                <em>is not</em>
+                part of the URL, just the id of the component. This is very desirable ... why expose
+                more of the construction of your application than you have to? As importantly, this
+                helps to prevent malicious users from subverting your application; there simply
+                isn't a way to get an arbitrary listener method to be invoked, only one that you, as
+                the developer, wired to a specific component.
+            </p>
+
+            <p>
+                These are what Tapestry pros call "ugly URLs". The ugly part is the use of query
+                parameters, rather than paths, to express the information in the URL. Ugly URLs can
+                cause some problems; since the entire application is routed through the /app path,
+                it's hard to apply J2EE declarative security. Likewise, the use of query parameters
+                means that most search engines will not spider the site. The solution is to use
+                "friendly URLs"
+                <sup>3</sup>
+                , which is covered in a later tutorial.
+            </p>
+
+
+        </section>
+
+        <section name="Adding more links">
+
+
+            <p>
+                This application is good, but we should have a way to reset the counter back to
+                zero. We're going to add a link to the page to do just that. The end result will
+                look like:
+            </p>
+
+            <img src="../images/QuickStart/directlink3.png" alt="Tutorial with clear link" />
+
+            <p>
+                To accomplish this we need to add another link to the Home page's HTML template, and
+                connect that to logic expressed as a new method on the Home page class. First the
+                template:
+            </p>
 
-<source xml:space="preserve">
+            <source xml:space="preserve">
 &lt;p&gt;
   &lt;a href="#" jwcid="clear@DirectLink" listener="listener:doClear"&gt;clear counter&lt;/a&gt;
 &lt;/p&gt;
 </source>
-  
-<p>This is just <em>another</em> DirectLink component, on the same page, but with
-  a different component id, and a different configuration. Here, we've called the component
-  "clear", and connected it to the doClear() listener method.</p>
-  
- <p>
-  That method is also quite simple:
- </p>
- 
-<source xml:space="preserve">
+
+            <p>
+                This is just
+                <em>another</em>
+                DirectLink component, on the same page, but with a different component id, and a
+                different configuration. Here, we've called the component "clear", and connected it
+                to the doClear() listener method.
+            </p>
+
+            <p>That method is also quite simple:</p>
+
+            <source xml:space="preserve">
     public void doClear()
     {
         setCounter(0);
     }
 </source>
 
-<p>
-  And that's all it takes.  We've added a new operation to our page, clearing the counter, in
-  four lines of Java code (three if you format your code the way Sun likes you to), and a couple
-  of lines of HTML.  No outside configuration beyond that. This conforms to another Tapestry
-  principle: <strong>Consistency</strong>.  Adding more  operations is not different from adding the first operation. Add
-  as many as you like, Tapestry will take care of it.
-</p>
-
-<p>
-  By contrast, using traditional servlets, we would have had to:
-</p>
-<ul>
-  <li>Decide on the URL</li>
-  <li>Update the HTML with that URL</li>
-  <li>Write an entire new servlet class for this single operation</li>
-  <li>Update web.xml with the servlet and the servlet mapping (the URL)</li>
-</ul>
-
-  
-</section>
+            <p>
+                And that's all it takes. We've added a new operation to our page, clearing the
+                counter, in four lines of Java code (three if you format your code the way Sun likes
+                you to), and a couple of lines of HTML. No outside configuration beyond that. This
+                conforms to another Tapestry principle:
+                <strong>Consistency</strong>
+                . Adding more operations is not different from adding the first operation. Add as
+                many as you like, Tapestry will take care of it.
+            </p>
+
+            <p>By contrast, using traditional servlets, we would have had to:</p>
+            <ul>
+                <li>Decide on the URL</li>
+                <li>Update the HTML with that URL</li>
+                <li>Write an entire new servlet class for this single operation</li>
+                <li>Update web.xml with the servlet and the servlet mapping (the URL)</li>
+            </ul>
+
+
+        </section>
+
+        <section name="Passing data in the links">
+
+
+            <p>
+                Just invoking a single operation is a bit limiting; we should be able to increment
+                by more than just 1:
+            </p>
+
+            <img src="../images/QuickStart/directlink4.png" alt="Multiple DirectLinks" />
+
+            <p>
+                In this case, we want to have more than one DirectLink component call the same
+                listener. And we need to figure out whether to increment the counter by 1, 5 or 10.
+            </p>
+
+            <p>
+                This requires two changes. First, we must change the old increment link into three
+                new links:
+            </p>
 
-<section name="Passing data in the links">
-  
-  
-<p>
-  Just invoking a single operation is a bit limiting; we should be able to increment by more than just 1:
-</p>  
-
-<img src="../images/QuickStart/directlink4.png" alt="Multiple DirectLinks"/>
-
-<p>
-In this case, we want to have more than one DirectLink component  call the same listener.  And we
-need to figure out whether to increment the counter by 1, 5 or 10.
-</p>
-
-<p>
-  This requires two changes.  First, we must change the old increment link into three new links:
-</p>
-
-<source xml:space="preserve">
+            <source xml:space="preserve">
 &lt;p&gt;
   &lt;a href="#" jwcid="by1@DirectLink" listener="listener:doClick" parameters="ognl:1"&gt;increment counter by 1&lt;/a&gt;
 &lt;/p&gt;
@@ -446,25 +505,29 @@
 &lt;/p&gt;
 </source>
 
-<p>
-  We've given the three components mnuemonic ids ("by1", "by5" and "by10"). In addition, we're passing
-  parameters in the URL; that's the parameters parameter<sup>4</sup>. We can see that value
-  encoded into the URL:
-</p>
+            <p>
+                We've given the three components mnuemonic ids ("by1", "by5" and "by10"). In
+                addition, we're passing parameters in the URL; that's the parameters parameter
+                <sup>4</sup>
+                . We can see that value encoded into the URL:
+            </p>
+
+            <source xml:space="preserve">http://localhost:8080/directlink/app?component=by10&amp;page=Home&amp;service=direct&amp;session=T&amp;sp=10</source>
+
+            <p>
+                The sp query parameter holds the value. "sp" is short for "service parameter", and
+                is a hold over from Tapestry 3.0. In Tapestry 4.0, these are called "listener
+                parameters", because they are only meaningful to the listener method. Also, we're
+                only showing a single parameter, but the same mechanism supports multiple
+                parameters.
+            </p>
+
+            <p>
+                That's how information gets encoded into the URL, but how does the listener method
+                find out about it? By adding a parameter to the doClick() listener method:
+            </p>
 
-<source xml:space="preserve">http://localhost:8080/directlink/app?component=by10&amp;page=Home&amp;service=direct&amp;session=T&amp;sp=10</source>
-  
-<p>The sp query parameter holds the value.  "sp" is short for "service parameter", and is a hold over
-  from Tapestry 3.0.  In Tapestry 4.0, these are called "listener parameters", because they are
-  only meaningful to the listener method.  Also, we're only showing a single parameter, but the
-  same mechanism supports multiple parameters.</p>  
-  
-<p>
-  That's how information gets encoded into the URL, but how does the listener method find out about it?
-  By adding a parameter to the doClick() listener method:
-</p>  
-
-<source xml:space="preserve">
+            <source xml:space="preserve">
     public void doClick(int increment)
     {
         int counter = getCounter();
@@ -474,55 +537,66 @@
         setCounter(counter);
     }  
 </source>
-  
-<p>
-  Tapestry maps the values in the sp query parameter to the parameters of the listener method.  Also, note
-  that <em>type</em> of the value has been maintained.  it started as a number, and is still a number.
-  Listener parameters can be of virtually any type, and will keep their type through being encoded into the URL
-  and decoded in the subsequent request. You can even pass arbitrary objects ... as long as they implement java.io.Serializable (but
-  you will start seeing some very long URLs if you do).
-</p>  
-  
-<p>
-  Again, we're seeing consistency. We wanted to pass information in the URL, and were able to use the
-  same mechanisms; the DirectLink component, the listener method ... we just added a little sensible extra
-  to get the needed information from point A (the page as it renders) to point B (the listener method when the
-  link is clicked).
-</p>  
-</section>  
 
-<section name="Next: Forms">
-  
+            <p>
+                Tapestry maps the values in the sp query parameter to the parameters of the listener
+                method. Also, note that
+                <em>type</em>
+                of the value has been maintained. it started as a number, and is still a number.
+                Listener parameters can be of virtually any type, and will keep their type through
+                being encoded into the URL and decoded in the subsequent request. You can even pass
+                arbitrary objects ... as long as they implement java.io.Serializable (but you will
+                start seeing some very long URLs if you do).
+            </p>
+
+            <p>
+                Again, we're seeing consistency. We wanted to pass information in the URL, and were
+                able to use the same mechanisms; the DirectLink component, the listener method ...
+                we just added a little sensible extra to get the needed information from point A
+                (the page as it renders) to point B (the listener method when the link is clicked).
+            </p>
+        </section>
+
+        <section name="Next: Forms">
+
+
+            <p>
+                <a href="site:DirectLink">DirectLink</a>
+                may be a real workhorse, but the heart of most web applications are the subject of
+                our next tutorial:
+                <a href="forms.html">Tapestry Forms</a>
+                .
+            </p>
 
-<p>
-<a href="site:DirectLink">DirectLink</a> may be a real workhorse, but the heart of most web applications are the
-subject of our next tutorial: <a href="forms.html">Tapestry Forms</a>.
-</p>
-
-</section>
-
-
-<p>
-  <sup>1</sup>This is my (Howard Lewis Ship's) least favorite thing in Tapestry 4.0; it is something
-  that should be erradicated from Tapestry (you should not have to extend a base class at all), but
-  that will cause some significant backwards compatibility issues.
-</p>
-
-<p>
-  <sup>2</sup>Listener methods don't have to be named in any special way, they just have to be 
-  public methods. This naming convention, do<em>Something</em>, is a good one, but is
-  anything but mandatory.
-</p>
-
-<p>
-  <sup>3</sup>For some reason, "ugly" is the opposite of "friendly".  
-</p>
-
-<p>
-  <sup>4</sup>Say that a few times fast.
-</p>
-  
-  
-  
-</body>
+        </section>
+        
+        <span class="info">
+        <p>
+            <sup>1</sup>
+            This is my (Howard Lewis Ship's) least favorite thing in Tapestry 4.0; it is something
+            that should be erradicated from Tapestry (you should not have to extend a base class at
+            all), but that will cause some significant backwards compatibility issues.
+        </p>
+
+        <p>
+            <sup>2</sup>
+            Listener methods don't have to be named in any special way, they just have to be public
+            methods. This naming convention, do
+            <em>Something</em>
+            , is a good one, but is anything but mandatory.
+        </p>
+
+        <p>
+            <sup>3</sup>
+            For some reason, "ugly" is the opposite of "friendly".
+        </p>
+
+        <p>
+            <sup>4</sup>
+            Say that a few times fast.
+        </p>
+        </span>
+        
+        </section>
+    </body>
 </document>

Modified: tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/forms.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/forms.xml?rev=418868&r1=418867&r2=418868&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/forms.xml (original)
+++ tapestry/tapestry4/trunk/src/site/xdoc/QuickStart/forms.xml Mon Jul  3 15:48:59 2006
@@ -1,60 +1,61 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 
-   Copyright 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.
+    Copyright 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.
 -->
 <document>
-<properties>
-<title>QuickStart: Forms</title>
-</properties>
-<body>
-
-<p>
-In this tutorial, we'll cover the basics of Tapestry forms, and gain an understanding of the lifecycle of
-a Tapestry application.  We'll also see how to transfer information from one
-page to another.
-</p>	
-
-<p>
-The theme of this tutorial is an application used to track third-party libraries for Tapestry.
-Each project will have a number of properties:
-</p>
-
-<ul>
-	<li>name</li>
-	<li>release ID</li>
-	<li>short and long description</li>
-	<li>category</li>
-	<li>supported Tapestry version</li>
-	<li>release date</li>
-	<li>public (visible to others) or private (visible only to the owner)</li>
-</ul>
-	
-<p>
-	Later tutorials will return to this theme, and cover the issues related to
-	accessing data from a database. For this tutorial, we're just going to collect
-	the above data (in an Add Project page), and then echo it back to the user.
-</p>	
-	
-<section name="Home Page">
-	
-	
-<p>
-The Home page for our application is very simple, it doesn't require a Java class:
-</p>	
+    <properties>
+        <title>QuickStart: Forms</title>
+    </properties>
+    <body>
+
+        <section name="QuickStart: Forms">
+            <p>
+                In this tutorial, we'll cover the basics of Tapestry forms, and gain an
+                understanding of the lifecycle of a Tapestry application. We'll also see how to
+                transfer information from one page to another.
+            </p>
+
+            <p>
+                The theme of this tutorial is an application used to track third-party libraries for
+                Tapestry. Each project will have a number of properties:
+            </p>
+
+            <ul>
+                <li>name</li>
+                <li>release ID</li>
+                <li>short and long description</li>
+                <li>category</li>
+                <li>supported Tapestry version</li>
+                <li>release date</li>
+                <li>public (visible to others) or private (visible only to the owner)</li>
+            </ul>
+
+            <p>
+                Later tutorials will return to this theme, and cover the issues related to accessing
+                data from a database. For this tutorial, we're just going to collect the above data
+                (in an Add Project page), and then echo it back to the user.
+            </p>
+
+        <section name="Home Page">
+
+
+            <p>
+                The Home page for our application is very simple, it doesn't require a Java class:
+            </p>
 
-<source xml:space="preserve">
+            <source xml:space="preserve">
 &lt;html jwcid="@Shell" title="Tapestry Component Database"&gt;
 &lt;body&gt;
 	
@@ -72,36 +73,41 @@
 &lt;/body&gt;
 &lt;/html&gt;
 </source>
-	
-<p>
-We've introduced another handy component, <a href="site:Shell">Shell</a>.  This component is just a 
-convienience for generating the &lt;html&gt;, &lt;head&gt;, and &lt;title&gt; tags (though
-it has quite a few other tricks up its sleeve).
-</p>	
-	
-	
-</section>	
 
-<section name="Value Object">
-	
-	
-<p>
-	One of the cornerstones of Tapestry is the ability to edit properties of value objects directly.
-	These value objects, in a real application, will be read from the database, editted by Tapestry
-	components, then written back into the database.
-</p>
-
-<p>
-	Objects editted by Tapestry in this manner have <em>no</em> requirements.  Unlike pages, they don't
-	have to extend a base class or implement an interface. They are truly the <strong>Model</strong>
-	in the <strong>Model-View-Controller Pattern</strong>.
-</p>
-
-<p>
-	For this tutorial, we're using a very simple value object:
-</p>
+            <p>
+                We've introduced another handy component,
+                <a href="site:Shell">Shell</a>
+                . This component is just a convienience for generating the &lt;html&gt;,
+                &lt;head&gt;, and &lt;title&gt; tags (though it has quite a few other tricks up its
+                sleeve).
+            </p>
+
+
+        </section>
+
+        <section name="Value Object">
+
+
+            <p>
+                One of the cornerstones of Tapestry is the ability to edit properties of value
+                objects directly. These value objects, in a real application, will be read from the
+                database, editted by Tapestry components, then written back into the database.
+            </p>
+
+            <p>
+                Objects editted by Tapestry in this manner have
+                <em>no</em>
+                requirements. Unlike pages, they don't have to extend a base class or implement an
+                interface. They are truly the
+                <strong>Model</strong>
+                in the
+                <strong>Model-View-Controller Pattern</strong>
+                .
+            </p>
 
-<source xml:space="preserve">package tutorial.forms.data;
+            <p>For this tutorial, we're using a very simple value object:</p>
+
+            <source xml:space="preserve">package tutorial.forms.data;
 
 import java.util.Date;
 
@@ -235,21 +241,22 @@
 }
 </source>
 
-</section>
+        </section>
 
-<section name="AddProject Page">
-	
-	
-<p>
-	As we've seen, the Home page includes a link to the AddProject page; the AddProject page
-	will contain the form that collects the data about the project before storing it into a database.
-	We don't have a database in this example, but we can still collect the data.
-</p>	
-	
-<subsection name="HTML Template">
-	
-	
-<source xml:space="preserve">&lt;html jwcid="@Shell" title="Add New Project"&gt;
+        <section name="AddProject Page">
+
+
+            <p>
+                As we've seen, the Home page includes a link to the AddProject page; the AddProject
+                page will contain the form that collects the data about the project before storing
+                it into a database. We don't have a database in this example, but we can still
+                collect the data.
+            </p>
+
+            <subsection name="HTML Template">
+
+
+                <source xml:space="preserve">&lt;html jwcid="@Shell" title="Add New Project"&gt;
   &lt;body jwcid="@Body"&gt;
     &lt;h1&gt;Add New Project&lt;/h1&gt;
     &lt;form jwcid="form@Form" success="listener:doSubmit"&gt;
@@ -300,68 +307,98 @@
       &lt;input type="submit" value="Add Project"/&gt;
     &lt;/form&gt;
   &lt;/body&gt;
-&lt;/html&gt;</source>	
-	
-<p>
-This template introduces a number of new components:
-</p>  
-
-<ul>
-  <li>
-<a href="site:Body">Body</a> -- organizes the JavaScript generated for the page (needed to use the <a href="site:DatePicker">DatePicker</a>)</li>
-  <li>
-<a href="site:Form">Form</a> -- generates an HTML form and controls the submit behavior</li>
-  <li>
-<a href="site:TextField">TextField</a> -- creates a text field (&lt;input type="text"/&gt;) used to <em>edit</em> (read and update) a property
-    of the page</li>
-  <li>
-<a href="site:TextArea">TextArea</a> -- as with <a href="site:TextField">TextField</a>, but generates a multi-line &lt;textarea&gt;</li>
-  <li>
-<a href="site:DatePicker">DatePicker</a> -- a JavaScript popup calendar</li>
-  <li>
-<a href="site:Checkbox">Checkbox</a> -- edits a <em>boolean</em> property of the page</li> 
-</ul>
-
-<p>
-The <a href="site:Form">Form</a>'s success parameter is linked to a listener method. It is invoked only when there
-are no validation errors. We'll discuss validation in a later tutorial.
-</p>
-
-<p>
- The <a href="site:Body">Body</a> component plays a crucial role in Tapestry; it organizes all the JavaScript generated when
- a page renders. It assists components with generated unique names for client-side variables and functions,
- and organizes all the JavaScript generated by all the component within the page into two large blocks (one at
- the top of the page, one at the bottom). The <a href="site:DatePicker">DatePicker</a> component will not operate unless it is
- enclosed by a <a href="site:Body">Body</a> component.
-</p>
-  
-<p>
-The <a href="site:TextField">TextField</a> and <a href="site:TextArea">TextArea</a> components edit properties of the page.  Because the value
-parameter is an <a href="http://www.ognl.org">OGNL</a> expression, it is not limited to editting properties directly exposed
-by the page class; it can follow property paths. We'll see how to define the project
-property of the page shortly.
-</p>
-
-<p>
-  As you can see, Tapestry offers a number of components for editting specific types of properties. In addition,
-  we'll see in a bit how the existing components can be configured for editting other types as well.
-</p>
-
-<p>
-  As the template shows, this page is reliant on 
-  having a specific Java class, with a doSubmit() listener method and a project property. Let's create that next.
-</p>
-
-</subsection>
-
-<subsection name="AddProject Page Class">
-  
-  
-<p>
-  Let's start with the minimum for this class and add details as necessary.
-</p>  
+&lt;/html&gt;</source>
+
+                <p>This template introduces a number of new components:</p>
+
+                <ul>
+                    <li>
+                        <a href="site:Body">Body</a>
+                        -- organizes the JavaScript generated for the page (needed to use the
+                        <a href="site:DatePicker">DatePicker</a>
+                        )
+                    </li>
+                    <li>
+                        <a href="site:Form">Form</a>
+                        -- generates an HTML form and controls the submit behavior
+                    </li>
+                    <li>
+                        <a href="site:TextField">TextField</a>
+                        -- creates a text field (&lt;input type="text"/&gt;) used to
+                        <em>edit</em>
+                        (read and update) a property of the page
+                    </li>
+                    <li>
+                        <a href="site:TextArea">TextArea</a>
+                        -- as with
+                        <a href="site:TextField">TextField</a>
+                        , but generates a multi-line &lt;textarea&gt;
+                    </li>
+                    <li>
+                        <a href="site:DatePicker">DatePicker</a>
+                        -- a JavaScript popup calendar
+                    </li>
+                    <li>
+                        <a href="site:Checkbox">Checkbox</a>
+                        -- edits a
+                        <em>boolean</em>
+                        property of the page
+                    </li>
+                </ul>
+
+                <p>
+                    The
+                    <a href="site:Form">Form</a>
+                    's success parameter is linked to a listener method. It is invoked only when
+                    there are no validation errors. We'll discuss validation in a later tutorial.
+                </p>
+
+                <p>
+                    The
+                    <a href="site:Body">Body</a>
+                    component plays a crucial role in Tapestry; it organizes all the JavaScript
+                    generated when a page renders. It assists components with generated unique names
+                    for client-side variables and functions, and organizes all the JavaScript
+                    generated by all the component within the page into two large blocks (one at the
+                    top of the page, one at the bottom). The
+                    <a href="site:DatePicker">DatePicker</a>
+                    component will not operate unless it is enclosed by a
+                    <a href="site:Body">Body</a>
+                    component.
+                </p>
+
+                <p>
+                    The
+                    <a href="site:TextField">TextField</a>
+                    and
+                    <a href="site:TextArea">TextArea</a>
+                    components edit properties of the page. Because the value parameter is an
+                    <a href="http://www.ognl.org">OGNL</a>
+                    expression, it is not limited to editting properties directly exposed by the
+                    page class; it can follow property paths. We'll see how to define the project
+                    property of the page shortly.
+                </p>
+
+                <p>
+                    As you can see, Tapestry offers a number of components for editting specific
+                    types of properties. In addition, we'll see in a bit how the existing components
+                    can be configured for editting other types as well.
+                </p>
+
+                <p>
+                    As the template shows, this page is reliant on having a specific Java class,
+                    with a doSubmit() listener method and a project property. Let's create that
+                    next.
+                </p>
+
+            </subsection>
+
+            <subsection name="AddProject Page Class">
 
-<source xml:space="preserve">package tutorial.forms.pages;
+
+                <p>Let's start with the minimum for this class and add details as necessary.</p>
+
+                <source xml:space="preserve">package tutorial.forms.pages;
 
 import org.apache.tapestry.html.BasePage;
 
@@ -383,41 +420,51 @@
     }
 }
 </source>
-  
-<p>
-  Maybe this is too minimal; if we launch the application and choose the Add New Project link, we
-  get an exception:
-</p>  
-
-<img src="../images/QuickStart/forms1.png" alt="Null Pointer Exception"/>
-  
-<p>
-  The root of this exception is a null value:  we defined a place to store a ProjectRelease object
-  but didn't actually provide an instance.  <a href="http://www.ognl.org">OGNL</a> attempted to dereference through the null value
-  and threw the OgnlException. Here we can see the advantage of Tapestry's exception reporting ... showing the 
-  stack of exceptions gave us context into our application (the line in the template associated with the
-  error) without obscuring the underlying cause.
-</p>  
-
-<p>
-  What we need to do is create an instance of ProjectRelease and store it into
-  the property so that the <a href="site:TextField">TextField</a> components can edit it.  We have to be careful
-  because in a live application, pages will be pooled and reused constantly.
-</p>
-
-<p>
-  For this situation, the right approach is to listen for the PageBeginRender event, and
-  store the new instance into the property then.  The ProjectRelease object will be used for the
-  duration of the request, then discarded at the end of the request.
-</p>
-
-<p>
-  Listening for these lifecycle events is simple; you just need to select the correct listener interface
-  and implement it; Tapestry will automatically register your page to receive the notifications.  Here,
-  the interface is <a href="../tapestry-framework/apidocs/org/apache/tapestry/event/PageBeginRenderListener.html">PageBeginRenderListener</a>:
-</p>
 
-<source xml:space="preserve">package tutorial.forms.pages;
+                <p>
+                    Maybe this is too minimal; if we launch the application and choose the Add New
+                    Project link, we get an exception:
+                </p>
+
+                <img src="../images/QuickStart/forms1.png" alt="Null Pointer Exception" />
+
+                <p>
+                    The root of this exception is a null value: we defined a place to store a
+                    ProjectRelease object but didn't actually provide an instance.
+                    <a href="http://www.ognl.org">OGNL</a>
+                    attempted to dereference through the null value and threw the OgnlException.
+                    Here we can see the advantage of Tapestry's exception reporting ... showing the
+                    stack of exceptions gave us context into our application (the line in the
+                    template associated with the error) without obscuring the underlying cause.
+                </p>
+
+                <p>
+                    What we need to do is create an instance of ProjectRelease and store it into the
+                    property so that the
+                    <a href="site:TextField">TextField</a>
+                    components can edit it. We have to be careful because in a live application,
+                    pages will be pooled and reused constantly.
+                </p>
+
+                <p>
+                    For this situation, the right approach is to listen for the PageBeginRender
+                    event, and store the new instance into the property then. The ProjectRelease
+                    object will be used for the duration of the request, then discarded at the end
+                    of the request.
+                </p>
+
+                <p>
+                    Listening for these lifecycle events is simple; you just need to select the
+                    correct listener interface and implement it; Tapestry will automatically
+                    register your page to receive the notifications. Here, the interface is
+                    <a
+                        href="../tapestry-framework/apidocs/org/apache/tapestry/event/PageBeginRenderListener.html">
+                        PageBeginRenderListener
+                    </a>
+                    :
+                </p>
+
+                <source xml:space="preserve">package tutorial.forms.pages;
 
 import java.util.Date;
 
@@ -454,67 +501,82 @@
     }
 }
 </source>
-  
-<p>
-  The pageBeginRender() method will be invoked whenever the page renders. It is also, due to a useful quirk of Tapestry,
-  invoked when a form within the page is submitted. Not only can we create an instance, but we
-  have the opportunity to set some initial values for fields.
-</p>  
-  
-<p>
-  With this in place, the page will now render, and we can begin entering some data into it:
-</p>  
-
-<img src="../images/QuickStart/forms2.png" alt="AddProject Page"/>
-  
-  
-</subsection>
-
-<subsection name="Form Submission">
-  
-  
-  <p>
-    As implemented above, submitting the form doesn't appear to do anything.  Sure, the form submits, and information is pulled
-    out of the request and applied to the properties of the ProjectRelease object, but then the AddProject page
-    is re-rendered.  
-  </p>  
-  
-  <p>
-    So ... how did the ProjectRelease object stick around?  Shouldn't we have gotten a NullPointerException again, when
-    the form submitted and the <a href="site:TextField">TextField</a> component updated property project.name?  What actually happened is that
-    the ProjectRelease object was discarded ... but when a form is submitted on a page, the PageBeginRender interface is
-    triggered again, just like for a form render. This means that the existing code does create a new ProjectRelease instance,
-    giving the TextField components a place to store the values from the form.
-  </p>
-
-  
-  <p>
-    As wonderful as it is that the new ProjectRelease object gets updated, what we 
-    really want is for <em>something to happen</em>.  We're going to change things so that a different page is
-    displayed when the form is submitted.  Further, that form will show the same information collected by
-    the AddProject page.
-  </p>
-  
-  <p>
-   To accomplish this, we're going to change the doSubmit() method, and have it obtain the ShowProject page. The easiest way to
-    make different pages work together is by <em>injecting</em> one page into another.  This can be done using
-    an annotation<sup>1</sup>:
-  </p>
-  
-  <source xml:space="preserve">
+
+                <p>
+                    The pageBeginRender() method will be invoked whenever the page renders. It is
+                    also, due to a useful quirk of Tapestry, invoked when a form within the page is
+                    submitted. Not only can we create an instance, but we have the opportunity to
+                    set some initial values for fields.
+                </p>
+
+                <p>
+                    With this in place, the page will now render, and we can begin entering some
+                    data into it:
+                </p>
+
+                <img src="../images/QuickStart/forms2.png" alt="AddProject Page" />
+
+
+            </subsection>
+
+            <subsection name="Form Submission">
+
+
+                <p>
+                    As implemented above, submitting the form doesn't appear to do anything. Sure,
+                    the form submits, and information is pulled out of the request and applied to
+                    the properties of the ProjectRelease object, but then the AddProject page is
+                    re-rendered.
+                </p>
+
+                <p>
+                    So ... how did the ProjectRelease object stick around? Shouldn't we have gotten
+                    a NullPointerException again, when the form submitted and the
+                    <a href="site:TextField">TextField</a>
+                    component updated property project.name? What actually happened is that the
+                    ProjectRelease object was discarded ... but when a form is submitted on a page,
+                    the PageBeginRender interface is triggered again, just like for a form render.
+                    This means that the existing code does create a new ProjectRelease instance,
+                    giving the TextField components a place to store the values from the form.
+                </p>
+
+
+                <p>
+                    As wonderful as it is that the new ProjectRelease object gets updated, what we
+                    really want is for
+                    <em>something to happen</em>
+                    . We're going to change things so that a different page is displayed when the
+                    form is submitted. Further, that form will show the same information collected
+                    by the AddProject page.
+                </p>
+
+                <p>
+                    To accomplish this, we're going to change the doSubmit() method, and have it
+                    obtain the ShowProject page. The easiest way to make different pages work
+                    together is by
+                    <em>injecting</em>
+                    one page into another. This can be done using an annotation
+                    <sup>1</sup>
+                    :
+                </p>
+
+                <source xml:space="preserve">
     @InjectPage("ShowProject")
-    public abstract ShowProject getShowProject();   </source>  
-  
-  <p>
-    This code, part of AddProject.java, establishes the connection from the AddProject page to the ShowProject page.
-  </p>
-  
-  <p>
-    We can leverage that code inside doSubmit() to pass information from the AddProject page to the ShowProject page; we can
-    also <em>activate</em> the ShowProject page, so that it renders the response.
-  </p>
-  
-  <source xml:space="preserve">  
+    public abstract ShowProject getShowProject();   </source>
+
+                <p>
+                    This code, part of AddProject.java, establishes the connection from the
+                    AddProject page to the ShowProject page.
+                </p>
+
+                <p>
+                    We can leverage that code inside doSubmit() to pass information from the
+                    AddProject page to the ShowProject page; we can also
+                    <em>activate</em>
+                    the ShowProject page, so that it renders the response.
+                </p>
+
+                <source xml:space="preserve">  
   public IPage doSubmit()
   {
     ShowProject showProject = getShowProject();
@@ -522,44 +584,52 @@
     showProject.setProject(getProject());
 
     return showProject;
-  }  </source>  
-  
-  <p>
-  A lot is going on here in a very small amount of code.  First off, this method is no longer void, it returns
-  a page (<a href="../tapestry-framework/apidocs/org/apache/tapestry/IPage.html">IPage</a> is the interface all page classes must implement). When a listener method returns a page,
-  that page becomes the <em>active page</em>, the page which will render the response to the client.
-  </p>
-  
-  <p>
-    This is an example of what we mean when we talk about objects, methods and properties. We don't talk about the
-    "ShowProject.html" template ... we talk about the ShowProject page, and leave the details about where its template is
-    and what's on that template to the ShowProject page.  Further, to pass information from the AddProject page
-    to the ShowProject page, we don't muck about with HttpServletRequest attributes ... we store an object into a
-    property of the ShowProject page.
-  </p>
-
-  <p>
-    With all this in place, we can now submit the form and see the ShowProject page:
-  </p>
-  
-<img src="../images/QuickStart/forms3.png" alt="ShowProject Page"/>
-  
-</subsection>  
-	
-</section>
+  }  </source>
 
-  <section name="Next: ???">
-    
-  </section>
-  
-<p>
-<em>More coming soon ...</em>
-</p>
-
-  <p>
-    <sup>1</sup> Of course, annotations required JDK 1.5, which you'll need for these tutorials.  If you can't use
-    JDK 1.5 in production, that's OK.  Tapestry is compatible with JDK 1.3 and has another approach, based on XML,
-    for injecting pages or doing just about anything else that shows up as an annotation in the tutorials.
-  </p>
-</body>
+                <p>
+                    A lot is going on here in a very small amount of code. First off, this method is
+                    no longer void, it returns a page (
+                    <a href="../tapestry-framework/apidocs/org/apache/tapestry/IPage.html">IPage</a>
+                    is the interface all page classes must implement). When a listener method
+                    returns a page, that page becomes the
+                    <em>active page</em>
+                    , the page which will render the response to the client.
+                </p>
+
+                <p>
+                    This is an example of what we mean when we talk about objects, methods and
+                    properties. We don't talk about the "ShowProject.html" template ... we talk
+                    about the ShowProject page, and leave the details about where its template is
+                    and what's on that template to the ShowProject page. Further, to pass
+                    information from the AddProject page to the ShowProject page, we don't muck
+                    about with HttpServletRequest attributes ... we store an object into a property
+                    of the ShowProject page.
+                </p>
+
+                <p>
+                    With all this in place, we can now submit the form and see the ShowProject page:
+                </p>
+
+                <img src="../images/QuickStart/forms3.png" alt="ShowProject Page" />
+
+            </subsection>
+
+        </section>
+
+        <section name="Next: ???">
+            <p>
+                <em>More coming soon ...</em>
+            </p>
+        </section>
+            
+            <span class="info">
+                <sup>1</sup>
+                Of course, annotations required JDK 1.5, which you'll need for these tutorials. If
+                you can't use JDK 1.5 in production, that's OK. Tapestry is compatible with JDK 1.3
+                and has another approach, based on XML, for injecting pages or doing just about
+                anything else that shows up as an annotation in the tutorials.
+            </span>
+            
+        </section>
+    </body>
 </document>