tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jkuhn...@apache.org
Subject svn commit: r418665 [5/6] - in /tapestry/tapestry4/trunk: src/documentation/content/xdocs/ src/documentation/content/xdocs/QuickStart/ src/documentation/content/xdocs/UsersGuide/ src/documentation/content/xdocs/examples/ src/site/ src/site/resources/im...
Date Mon, 03 Jul 2006 00:17:31 GMT
Added: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/state.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/state.xml?rev=418665&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/state.xml (added)
+++ tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/state.xml Sun Jul  2 17:17:29 2006
@@ -0,0 +1,554 @@
+<?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.
+-->
+<document>
+<properties>
+<title>Managing server-side state</title>
+</properties>
+<body>
+
+<p>
+Server-side state is any information that exists on the server, and persists between requests.
+This can be anything from a single flag all the way up to a large database result set.  In a typical
+application, server-side state is the identity of the user (once the user logs in) and, perhaps,
+a few important domain objects (or, at the very least, primary keys for those objects).
+</p>
+
+<p>
+In an ordinary servlet application, managing server-side state is 
+entirely the application's responsibility.  The Servlet API provides just the HttpSession, which
+acts like a Map, relating keys to arbitrary objects.  It is the application's responsibility
+to obtain values from the session, and to update values into the session when they change.
+</p>
+
+<p>
+Tapestry takes a different tack; it defines server side state in terms of
+either entire objects (<a href="state.html#state.aso">application state object</a>s) or by allowing specific page or component properties to be persistent.
+</p>
+
+<section name="Understanding servlet state">
+	
+	
+
+<p>
+Managing server-side state is one of the most complicated and error-prone aspects of web
+application design, and one of the areas where Tapestry provides the most benefit.  Generally
+speaking, Tapestry applications which are functional within a single server will be functional within
+a cluster with no additional effort.  This doesn't mean planning for clustering, and testing of
+clustering, is not necessary; it just means that, when using Tapestry, it is possible to narrow
+the design and testing focus.	 The Tapestry framework embraces the correct best-practices for managing
+client state on either a single server or a cluster of services.
+</p>
+
+<p>
+The point of server-side state is to ensure that information about the user acquired during the session
+is available later in the same session.  The canonical example is an application that requires some form of
+login to access some or all of its content; the identify of the user must be collected at some point (in
+a login page) and be generally available to other pages.
+</p>
+
+<p>
+The other aspect of server-side state concerns failover.  Failover is an aspect of highly-available computing
+where the processing of the application is spread across many servers.  A group of servers used
+in this way is referred to as a <em>cluster</em>.  
+Generally speaking (and this may vary significantly between vendor's implementations)
+requests from a particular client will be routed to the same server within the cluster.
+</p>
+
+<p>
+In the event that the particular server in question fails (crashes unexpectedly, or otherwise brought 
+out of service), future requests from the client will be routed to a different, surviving server
+within the cluster.  This failover event should occur in such a way that the client is unaware that
+anything exceptional has occured with the web application; and this means that any server-side state
+gathered by the original server must be available to the backup server.
+</p>
+
+<p>
+The main mechanism for handling this using the Java Servlet API is the HttpSession.  The session can store
+<em>attributes</em>, much like a Map.  Attributes are object values referenced with
+a string key.  In the event of a failover, all such attributes are expected to be available on the
+new, backup server, to which the client's requests are routed.
+</p>
+
+<p>
+Different application servers implement HttpSession replication and failover in different ways; the servlet API
+specification is delibrately non-specific on how this implementation should take place.  Tapestry
+follows the conventions of the most limited interpretation of the servlet specification; it assumes
+that attribute replication only occurs when the HttpSession <code>setAttribute()</code>	
+method is invoked.
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/> This is the replication strategy employed by BEA's WebLogic server. </p>
+
+
+<p>
+Attribute replication was envisioned as a way to replicate simple, immutable objects
+such as String or Integer.  Attempting to store mutable objects, such as List, Map or some user-defined
+class, can be problematic.  For example, modifying an attribute value after it has been stored into the 
+HttpSession may cause a failover error.  Effectively, the backup server sees a snapshot of the object
+at the time that <code>setAttribute()</code> was invoked; any later change to the object's
+internal state is <em>not</em> replicated to the other servers in
+the cluster!  This
+can result in strange and unpredictable behavior following a failover.
+</p>
+
+<p>
+Tapestry attempts to sort out the issues involving server-side state in such a way that they
+are invisible to the developer.  Most applications will not need to explicitly access the HttpSession at
+all, but may still have significant amounts of server-side state.  The following
+sections go into more detail about how Tapestry approaches these issues.	
+</p>
+
+
+</section>  <!-- state.general -->
+
+<section name="Persistent page properties">
+	
+	
+<p>
+Servlets, and by extension, JavaServer Pages, are inherently stateless.  That is, they will be used
+simultaneously by many threads and clients.  Because of this, they must not store (in instance variables)
+any properties or values that are specific to any single client.
+</p>
+
+<p>
+This creates a frustration for developers, because ordinary programming techniques must be avoided.
+Instead, client-specific state and data must be stored in the HttpSession or as HttpServletRequest attributes.
+This is an awkward and limiting way to handle both <em>transient</em> state (state that is only needed
+during the actual processing of the request) and
+<em>persistent</em> state (state that should be available during the processing of this
+and subsequent requests).
+</p>
+
+<p>
+Tapestry bypasses most of these issues by <em>not</em> sharing objects between threads and clients.
+Tapestry uses an <em>object pool</em> to store constructed page instances. As a page is needed, it is removed from the page pool.
+If there are no available pages in the pool, a fresh page instance is constructed.
+</p>
+
+<p>
+For the duration of a request, a page and all components within the page are reserved to the single request.
+There is no chance of conflicts because only the single thread processing the request will have access
+to the page.  At the end of the request cycle, the page is reset back to a pristine state and 
+returned to the shared pool,
+ready for reuse by the same client, or by a different client.
+</p>
+
+<p>
+In fact, even in a high-volume Tapestry application, there will rarely be more than a few instances of any
+particular page in the page pool.
+</p>
+
+<p>
+For this scheme to work it is important that, at the end of the request cycle, the page be returned
+to its <em>pristine state</em>.  The prisitine state is equivalent to a freshly created instance of the page.  In other words, any
+properties of the page that changed during the processing of the request must be returned to their initial values.
+</p>
+
+<p>
+The page is then returned to the page pool, where it will wait to be used in a future request. That request may be for 
+the same end user, or for another user entirely.	
+</p>
+
+<p>
+<strong>Warning:</strong>
+<br/>
+	Imagine a page containing a form in which a user enters their address and credit card information. When
+	the form is submitted, properties of the page will be updated with the values supplied by the user.
+	Those values must be cleared out before the page is stored into the page pool ... if not, then the <em>next</em>
+	user who accesses the page will see the previous user's address and credit card information as default
+	values for the form fields!
+</p>
+
+<p>
+Tapestry separates the persistent state of a page from any instance of the page. 
+This is very important, because
+from one request cycle to another, a different instance of the page may be used ... even when clustering is
+not used.  Tapestry has many copies of any page in a pool, and pulls an arbitrary instance out of the pool
+for each request.
+</p>
+
+<p>
+In Tapestry, a page may have many properties
+and may have many components, each with many properties, but only a tiny number of all those
+properties needs to persist between request cycles.
+On a later request, the same or different page instance may be used.  With a little
+assistance from the developer, 
+the Tapestry framework can create the illusion that the same page instance is being used in
+a later request, even though the request may use a different page instance (from the page pool) ... or
+(in a clustering environment) may be handled by a completely different server.
+</p>
+
+<p>
+Tapestry is flexible about how these properties are ultimately stored. Tapestry 3.0 and earlier were less so ... persistent page properties
+were always stored in the HttpSession.  Starting in release 4.0, persistent page properties may be stored in the session, or on the client.
+</p>
+
+<subsection name="Using Persistent Page Properties">
+  
+
+<p>
+Persistent properties make use of a <a href="spec.html#spec.property">&lt;property&gt;</a> element in the
+page or component specification.  Tapestry does something special when a component
+contains any such elements; it dynamically fabricates a subclass that provides the desired fields,
+methods and whatever extra initialization or cleanup is required.
+</p>
+
+<p>
+You may also, optionally, make your page or component class abstract, and define abstract accessor methods that will
+be filled in by Tapestry in the fabricated subclass.  This allows you to read and update properties inside
+your Java code, such as inside listener methods.
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/>
+	You only need to define abstract accessor methods if you are going to invoke those accesor methods
+	in your code, such as in a <a href="listenermethods.html">listener method</a>. Tapestry will create an enhanced subclass that contains
+	the new field, a getter method and a setter method, plus any necessary initialization methods.
+	If you are only going to access the property using OGNL expressions, then there's no need to define either
+	accessor 
+	method.
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/>
+Properties defined this way may be either transient or persistent. For transient properties (properties
+which do not persist between requests), it is only necessary to specify the property (with
+a <a href="spec.html#spec.property">&lt;property&gt;</a> element)
+if it has an initial value.  Tapestry scans the component class looking for abstract properties that don't
+match up against component parameters or <a href="spec.html#spec.property">&lt;property&gt;</a> elements; for each of these unclaimed properties,
+a concrete property is created. The property is a transient property, exactly as if a <a href="spec.html#spec.property">&lt;property&gt;</a> element <em>did</em>
+exist for it.
+</p>
+	
+<p>
+A page class that uses a specified property:
+</p>  
+<source xml:space="preserve">
+package mypackage;
+
+import org.apache.tapestry.html.BasePage;
+	
+public abstract class MyPage extends <a href="../tapestry/apidocs/org/apache/tapestry/html/BasePage.html">BasePage</a>
+{
+    abstract public int getItemsPerPage();
+	
+    abstract public void setItemsPerPage(int itemsPerPage);
+}
+</source>
+
+<p>
+This is combined with a <a href="spec.html#spec.property">&lt;property&gt;</a>  element
+in the page's specification:
+</p>
+
+<source xml:space="preserve">
+
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE page-specification PUBLIC 
+  "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
+  "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd"&gt;
+	
+&lt;page-specification class="mypackage.MyPage"&gt;
+
+  &lt;property
+    name="itemsPerPage"
+    persist="session"
+    initial-value="10"/&gt;
+
+&lt;/page-specification&gt;
+
+</source>
+
+<p>
+Again, making the class abstract, and defining abstract accessors is <em>optional</em>.
+It is only useful when a method within the class will need to read or update the property.  It
+is also valid to just implement one of the two accessors.  The enhanced subclass will
+always include both a getter and a setter.
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/>
+In Tapestry 3.0, many users were frustrated that they had to specify the type of property
+in both the Java code and in the page specification. This is a violation of the
+<a href="http://c2.com/cgi/wiki?DontRepeatYourself">Dont Repeat Yourself</a> principal -- requiring
+coordination is just an invitation for the two sides to get out of synchronization. Starting with Tapestry 4.0,
+there is no type attribute on the <a href="spec.html#spec.property">&lt;property&gt;</a> element; instead Tapestry matches the type to the
+property type of any existing accessor methods, and simply uses Object when there are no accessor methods.  In
+this example, the persistent itemsPerPage property will be type int, because of the abstract accessor methods.
+</p>
+
+<p>
+This exact same technique can be used with components as well as pages, the component specification also supports
+the <a href="spec.html#spec.property">&lt;property&gt;</a> element.
+</p>
+
+<p>
+When an initial-value is provided, it is evaluated once inside <code>finishLoad()</code>, but
+then again every time the page is detached (returned to pristine state) before being stored into
+the page pool for later re-use.  By default, it is an <a href="http://www.ognl.org">OGNL</a> expression, but this can be
+overriden by providing a <a href="bindings.html">binding reference</a> prefix.
+</p>
+
+
+<p>
+This means that you may perform initialization for the property inside
+<code>finishLoad()</code> (instead of providing an initial-value).  However,
+don't attempt to update the property from <code>initialize()</code> ... the order of operations
+when the page detaches is not defined and is subject to change.
+</p>
+
+<p>
+<strong>Warning:</strong>
+<br/>
+If the values stored as a persistent property is <em>mutable</em>   (for example, a List, or a Map, or some custom Java class), you should
+<em>not</em> modify its internal state once it has been stored into the persistent page property.  Changes to internal state of a persistent
+property, after it has been stored, may <em>not</em> be propogated to other servers in the cluster (this is really a function of how
+session replication is implemented by the application server, it has very little to do with Tapestry). Similar problems concerning mis-matched state can occur
+with client persistence.
+</p>
+
+</subsection> <!-- state.page-properties.using -->
+
+<subsection name="Persistence Types">
+  
+  
+<p>
+Tapestry defines two basic types of property persistence.  The type of persistence (internally known as the <em>property persistence strategy</em>) is
+defined by the value of the persist attribute (in the <a href="spec.html#spec.property">&lt;property&gt;</a> element).  Omitting the persist attribute, or not providing a <a href="spec.html#spec.property">&lt;property&gt;</a>
+element, indicates a <em>transient</em> page property, one which does not persist from request to request.
+</p>  
+
+<dl>
+  <dt>client</dt>
+  <dd>
+    Client properties are stored on the client, in the form of query parameters.  All persistent properties for each page
+    are encoded into a single query parameter, named <code>state:</code>
+<em>PageName</em>.  The query parameter value is
+    a MIME encoded byte stream.  This can get quite long if there are many client persistent properties on the page ... which
+    may quickly run into limitations on the maximum size of a URL (approximately 4000 characters is a good guideline).  This is less
+    a problem for forms.
+  </dd>
+  <dt>session</dt>
+  <dd>
+  The traditional style of property persistence (and the only kind available in Tapestry 3.0 and earlier). Each persistent property
+  is mapped to a HttpSession attribute.
+  </dd>
+</dl>
+
+<p>
+More such stategies are expected; these will give more control over the lifecycle of the page property.
+</p>
+  
+<p>
+<strong>Fixme:</strong>
+<br/>
+  Mind Bridge has added (or changed) these, adding a concept of "scope" for how long a property will persist. This documentation
+  needs to be updated.
+</p>  
+</subsection> <!-- state.page-properties.types -->
+
+</section> <!-- state.page-properties -->
+
+<section name="Application state objects">
+  
+  
+<p>
+What happens when you have objects that are needed by multiple pages?  For that, you need an
+<em>application state object</em>.  ASO's are global objects that can be 
+<a href="#state.aso.access">accessed</a> from any page
+or component in the application.  Each ASO has a unique name (the two default
+ASO's are called "visit" and "global" for historical reasons).  An ASO is created when first referenced by any page.
+ASO's with session scope are stored into the HttpSession at the end of the request (and 
+<a href="#state.stateless">may force the creation of
+the session</a>).  ASOs in the application scope are available to any and all users.
+</p>  
+
+<p>
+<strong>Note:</strong>
+<br/>
+Tapestry 3.0 had a more limited form of ASO:  The Visit object and the Global object. The Visit object is session scope, the Global object is
+application scope. This concept has been extended in Tapestry 4.0 to allow any number of ASOs with any desired scope, and lots
+of flexibility on how ASOs get created. The Visit and Global still exist in 4.0, as default ASOs you can use or override.
+</p>
+
+<subsection name="Defining new Application State Objects">
+  
+  
+<p>
+To create a new ASO, you must update your <a href="site:hivemind">HiveMind module deployment descriptor</a> and add a contribution to the
+<a href="../tapestry/hivedocs/config/tapestry.state.ApplicationObjects.html">tapestry.state.ApplicationObjects</a> configuration point:
+</p>  
+
+<source xml:space="preserve">
+&lt;contribution configuration-id="tapestry.state.ApplicationObjects"&gt;
+  &lt;state-object name="registration-data" scope="session"&gt;
+    &lt;create-instance class="org.example.registration.RegistrationData"/&gt;
+  &lt;/state-object&gt;  
+&lt;/contribution&gt;
+</source>
+  
+<p>
+This defines an ASO named registration-data that is session scoped (stored in the HttpSession once created). The first
+time it is referenced, an instance of RegistrationData is created and stored into the session.
+</p>  
+
+<p>
+If your data object can't be created using a simple constructor, then you can supply an &lt;invoke-factory&gt; element instead
+of &lt;create-instance&gt;.  &lt;invoke-factory&gt; allows you to reference an object or service that implements
+the <a href="../tapestry/apidocs/org/apache/tapestry/engine/state/StateObjectFactory.html">StateObjectFactory</a> interface.
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/>
+  The two default ASOs, "visit" and "global", are defined in the hivemind.state.FactoryObjects configuration point. Definitions
+  in the ApplicationObjects configuration point override definitions in FactoryObjects with the same name.
+</p>
+  
+</subsection> <!-- state.aso.defining -->
+
+<subsection name="Accessing Application State Objects">
+  
+  
+<p>
+Tapestry provides an <a href="spec.html#spec.inject">&lt;inject&gt;</a> element to support access to the application state objects. This
+element can be used in any page or component specification to create a new property.  Reading the property
+will obtain the corresponding state object (which will be created if necessary).  The property may be updated,
+which will store a new application state object, overwriting the automatically created one.  
+</p>  
+
+<p>
+For example:
+</p>
+
+<source xml:space="preserve">
+&lt;inject property="registration" type="state" object="registration-data"/&gt;
+</source>
+
+<p>
+This will create a <code>registration</code> property, which can be wired to components.  Your class may define
+accessors for this property, in which case you should be sure that the application state object is assignable.
+</p>
+  
+<p>
+<strong>Warning:</strong>
+<br/>
+The <a href="../tapestry/apidocs/org/apache/tapestry/IPage.html">IPage</a> interface defines two read-only properties: <code>visit</code> and <code>global</code>. These are both
+type Object. This is a holdover from Tapestry 3.0, which only supported these two application
+state objects.  If you want to access the visit or the global application state objects without needing casts,
+you will have to inject as a differently named property (say <code>appVisit</code> or <code>visitObject</code>).
+</p>
+  
+  
+</subsection>  <!-- state.aso.access -->
+
+<subsection name="Optimizing Storage">
+  
+  
+<p>
+  Normally, Tapestry has no way of knowing when the internal state of an ASO has changed. On any request
+  where the ASO is accessed, Tapestry assumes that its internal state has changed. The ASO is re-stored
+  at the end of the request. For session-scoped ASOs in a cluster, this is critical to ensure that
+  information is properly distributed around the cluster.
+</p>  
+
+<p>
+  However, it can also be expensive. Assuming that your application mostly <em>reads</em> information
+  out of the ASO, that means a lot of wasted resources needlessly copying the ASO around the cluster.
+</p>
+
+<p>
+  To control this, ASOs may <em>optionally</em> implement the <a href="../tapestry/apidocs/org/apache/tapestry/SessionStoreOptimized.html">SessionStoreOptimized</a> interface.
+  The method isStoreToSessionNeeded() will be checked; if it returns false, the object will 
+  <em>not</em> be stored.
+</p>
+
+<p>
+  Typically, the ASO will store a dirty flag, and will set the dirty flag on any change
+  to internal state. The flag will be returned by isStoreToSessionNeeded(). The ASO
+  will also implement the HttpSessionBindingListener interface, and clear
+  the flag in valueBound().
+</p>
+
+<p>
+  A base class, <a href="../tapestry/apidocs/org/apache/tapestry/BaseSessionStoreOptimized.html">BaseSessionStoreOptimized</a>, implements this behavior.
+</p>
+  
+</subsection>
+  
+</section>  <!-- state.aso -->
+
+<section name="Stateless applications">
+	
+	
+<p>
+In a Tapestry application, the framework acts as a buffer between the application code and
+the Servlet API ... in particular, it manages how data is stored into the HttpSession.
+In fact, the framework controls <em>when</em> the session is first created.
+</p>
+
+<p>
+This is important and powerful, because an application that runs, even just initially, without
+a session consumes far less resources than a stateful application.  This is even more important
+in a clustered environment with multiple servers; any data stored into the HttpSession will
+have to be replicated to other servers in the cluster, which can be expensive in terms of resources (CPU time,
+network bandwidth, and so forth).  Using
+less resources means better throughput and more concurrent clients, always a good thing
+in a web application.
+</p>
+
+<p>
+Tapestry defers creation of the HttpSession until one of two things happens:  When a session-scoped <a href="state.html#state.aso">application state object</a> is
+first created, or when the first persistent page property is recorded.  At this point,
+Tapestry will create the HttpSession to hold the object or property.
+</p>
+
+
+<p>
+For the most part, your application will be unaware of when it is stateful or stateless; statefulness
+just happens on its own.  Ideally, at least the first, or <code>Home</code> page, should be stateless (it should be
+organized in such a way that the Visit object is not created, and no persistent state is stored).  This will help
+speed the initial display of the application, since no processing time will be used in creating the HttpSession.
+</p>	
+
+<p>
+The <code>state:</code> <a href="bindings.html">binding reference</a> combined with the <a href="site:If">If</a> component makes it easy for you to skip
+portions of a page if a particular ASO does not already exist; this allows you to avoid accidentally forcing its
+creation on first reference.
+</p>
+
+<p>
+The application may be <em>stateless</em> even when it has persistent page properties, if those properties use the
+<em>client</em> persistence strategy (which encodes pesistent page data into URLs as query parameters). This can be a 
+very powerful approach, though it introduces its own problems:
+</p>
+
+<ul>
+  <li>The query parameters are an encoding of Java objects, and could be decoded to expose
+    privileged information.</li>
+  <li>The encoding of page state can result in very long strings included as part of URLs, possibly extending beyond the 3000 to 4000 character effective maximum
+    URL length.</li>
+</ul>	
+</section> <!-- state.stateless -->
+
+</body>
+</document>

Propchange: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/state.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/template.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/template.xml?rev=418665&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/template.xml (added)
+++ tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/template.xml Sun Jul  2 17:17:29 2006
@@ -0,0 +1,742 @@
+<?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.
+-->
+<document>
+<properties>
+<title>Page and component templates</title>
+</properties>
+<body>
+
+<p>
+Unlike many other web frameworks, such as 
+<a href="http://struts.apache.org/">Struts</a> or <a href="http://opensymphony.com/webwork/">WebWork</a>,
+Tapestry does not "plug into" an external templating system such as JavaServer Pages or
+<a href="http://jakarta.apache.org/velocity/">Velocity</a>.  Instead, Tapestry integrates its own templating system.
+	
+</p>
+
+<p>
+Tapestry templates are designed to look like valid HTML files (component HTML templates
+will just be snippets of HTML rather than complete pages). 
+Tapestry "hides" its extensions into special attributes of ordinary HTML elements.	
+	
+</p>
+
+<p>
+Don't be fooled by the terminology; we say "HTML templates" because that is the prevalent use of Tapestry ... but
+Tapestry is equally adept at WML or XML.
+</p>
+
+<section name="Template locations">
+	
+	
+	
+<p>
+The general rule of thumb is that a page's HTML template is simply an HTML file, stored in the context root directory. 
+That is, you'll have a <em>MyPage</em>.html HTML template,
+a WEB-INF/<em>MyPage</em>.page page specification,
+and a <em>MyPage</em> class, in some Java package.
+</p>
+
+<p>
+Tapestry always starts knowing the name of the page and the location of the page's specification when it
+searches for the page's HTML template.  Starting with this, it performs the following search:
+</p>
+
+<ul>
+<li>In the same location as the specification</li>
+<li>In the web application's context root directory (if the page is an application page, not a page from a component
+		library)	</li>
+</ul>
+
+<p>
+In addition, any HTML template in the web application context is considered a page, even if there is no matching
+page specification. For simple pages that don't need to have any page-specific logic or properties, there's no need
+for a page specification.  Such a page may still use the special Tapestry attributes 
+(described in the following sections).	
+</p>
+
+<p>
+Finally, with some <a href="configuration.html#configuration.search-path">minor configuration</a>
+it is possible to change the extension used for templates. For example, if you are developing a WML
+application, you may wish to name your application's template files with the extension .wml.
+</p>
+
+</section> <!-- template.locations -->
+
+<section name="Template Contents">
+		
+	
+<p>
+Tapestry templates contain a mix of the following elements:
+</p>
+
+<ul>
+  <li>Static HTML markup</li>
+  <li>Tapestry components</li>
+  <li>Localized messages</li>
+  <li>Special template directives</li>
+</ul>
+
+<p>
+Usually, about 90% of a template is ordinary HTML markup.  Hidden inside that markup are particular tags that
+are placeholders for Tapestry components; these tags are recognized by the presence of the jwcid attribute.  "JWC"
+is short for "Java Web Component", and was chosen as the "magic" attribute so as not to conflict with any real HTML attribute.	
+</p>
+
+
+<p>
+Tapestry's parser is quite flexible, accepting all kinds of invalid HTML markup. That is, attributes don't <em>have</em> to be
+quoted. Start and end tags don't have to balance.  Case is ignored when matching start and end tags.  Basically,
+the kind of ugly HTML you'll find "in the field" is accepted.
+</p>
+
+<p>
+The goal is to allow you to preview your HTML templates using a WYSIWYG HTML editor (or even an ordinary web browser).
+The editor will ignore the undefined HTML attributes (such as jwcid).	
+</p>
+
+<p>
+A larger goal is to support real project teams: The special markup for Tapestry is unobtrusive, even invisible.
+This allows an HTML designer to work on a template without breaking the dynamic portions of it.	Importantly, the designers can
+work with their normal tools and editors. This is completely unlike
+JSPs, where the changes to support dynamic output are extremely intrusive and result in a file that is meaningless to an HTML
+editor.
+</p>
+
+</section> <!-- template.contents -->
+
+<section name="Components in templates">
+	
+	
+<p>
+Components can be placed anywhere inside a template, simply  by adding the jwcid attribute to 
+any existing tag.  For example:
+</p>
+
+<source xml:space="preserve">&lt;html&gt;
+  &lt;head&gt;
+    &lt;title&gt;Example HTML Template&lt;/title&gt;
+  &lt;/head&gt;
+  &lt;body
+    &lt;span jwcid="border"&gt;
+    
+      Hello,
+      &lt;span jwcid="@Insert" value="ognl:user.name"&gt;Joe User&lt;/span&gt;
+    &lt;/span&gt;
+  &lt;/body&gt;
+&lt;/html&gt;</source>
+
+<p>
+The first span is a reference to a <em>declared component</em>; the type and parameters
+of the component are declared in the page's specification.
+</p>	
+
+<p>
+The second span is an <em>implicit component</em>; the type of the component is <a href="site:Insert">Insert</a>. The
+value parameter is bound to the <a href="http://www.ognl.org">OGNL</a> expression <code>user.name</code>.
+</p>	
+	
+<p>
+The point of all this is that the HTML template should preview properly in a WYSIWYG HTML editor. Unlike
+<a href="http://jakarta.apache.org/velocity/">Velocity</a> or JSPs, there are no strange directives to get in the way of a preview (or necessitate
+a special editting tool), Tapestry hides what's needed inside existing tags; at worst, it adds
+a few non-standard attributes (such as jwcid) to tags. This rarely causes a problem with most HTML editors.
+</p>
+
+<p>
+Templates may contain components using two different styles.  <em>Declared components</em>	 are
+little more than a placeholder; the type of the component is defined elsewhere, in the page (or component) 
+specification.
+</p>
+
+<p>
+Alternately, an <em>implicit component</em> can be defined in place, by preceding
+the component type with an "@" symbol.  Tapestry includes over forty components with the framework, additional components
+may be created as part of your application, or may be provided inside a component library.
+</p>	
+
+<p>
+In the above example, a &lt;span&gt;	 was used for both components. Tapestry
+doesn't care what tag is used for a component, as long as the start and end tags for components balance (it doesn't
+even care if the case of the start tag matches the case of the end tag). The example could just
+as easily use &lt;div&gt; or &lt;fred&gt;, the
+rendered page sent back to the client web browser will be the same.
+</p>
+
+<p>
+The default attribute name is <code>jwcid</code>, but there are occasions when that  is not desirable. The
+org.apache.tapestry.jwcid-attribute-name <a href="configuration.html#configuration.properties">configuration property</a> allows you to control the  template
+parser's behavior.
+</p>
+
+<subsection name="Component bodies">
+		
+		
+<p>
+In Tapestry, each component is responsible for rendering itself and its <em>body</em>. 
+A component's body is the portion of its page's template
+  that its tags encloses. The Tapestry HTML template parser is responsible for dividing up the  template
+  into chunks: blocks of static HTML, component start tags (recognized by the jwcid attribute) and matching
+  component end tags. It is quite forgiving about case, quotes (which may be single quotes, double quotes, or even
+  omitted), and missing close tags (except for components, which must be balanced).
+</p>		
+
+<p>
+<strong>Note:</strong>
+<br/>
+
+More correct would be to say "its container's template" as a component may be contained within
+another component. For simplicities sake, we'll describe this as if it was always a simple two-level
+heirarchy even though practical Tapestry applications can be many levels deep.
+
+</p>
+
+<img alt="Component templates and bodies" src="../images/UsersGuide/component-body.png"/>
+	
+<p>
+In most cases, a component will make use of its body; it simply controls if, when and how often its body
+is rendered (when rendering the HTML response sent to the client). Other components, such as <a href="site:Insert">Insert</a>,
+have no use for their bodies, which they discard.  Each component declares in its own specification (the
+allow-body	 attribute of the <a href="spec.html#spec.component-specification">&lt;component-specification&gt;</a>) whether is allows or
+discards its body.
+</p>
+
+<p>
+In the previous example, the <a href="site:Insert">Insert</a> component had a body, the text "Joe User". This supports WYSIWYG preview; the text
+will be displayed when previewing. Since the <a href="site:Insert">Insert</a> component discards its body,
+this text will not be used at runtime, instead the OGNL expression <code>user.name</code>	 will be evaluated
+and the result inserted into the response.
+</p>
+
+<p>
+<strong>Warning:</strong>
+<br/>
+	If you put a component inside the body of an <a href="site:Insert">Insert</a> (or any other component that discards
+	its body), then Tapestry will throw an exception. You aren't allowed to create a component
+	simply to discard it.	
+</p>
+
+</subsection> <!-- templates.components.body -->
+
+<subsection name="Component ids">
+	
+	
+<p>
+Every component in Tapestry has its own id.  In the above example, the first component has the id "border".  The second component
+is anonymous; the framework provides a unique id for the component since one was not supplied in the HTML template. The 
+framework provided id is built from the component's type; this component would have an id of
+<code>$Insert</code>; other <a href="site:Insert">Insert</a> components
+would have ids <code>$Insert$0</code>, <code>$Insert$1</code>, etc.
+</p>
+
+<p>
+A component's id must only be unique within its immediate container. 
+ Pages are top-level containers, but
+components may have their own templates, and so can also contain other components. 
+</p>
+
+
+<p>
+Implicit components can also have a specific id, by placing the id in front of the "@" symbol:
+</p>
+
+<source xml:space="preserve">
+  &lt;span jwcid="insert@Insert" value="ognl:user.name"&gt;Joe User&lt;/span&gt;
+</source>
+
+<p>
+The component is still implicit; nothing about the component would go in the specification, but the id
+of the component would be <code>insert</code>.	
+</p>
+
+<p>
+Providing explicit ids for your components is rarely required, but often beneficial. It is especially
+useful for form control components.
+</p>
+
+<p>
+Each component may only appear <em>once</em>	 in the template. You simply can't 
+use the same component
+repatedly ... but you can duplicate a component fairly easily; make the component a declared component,
+then use the copy-of attribute of the <a href="spec.html#spec.component">&lt;component&gt;</a> element to create clones of
+the component with new ids.
+</p>
+
+
+</subsection> <!-- templates.components.ids -->
+
+<subsection name="Specifying parameters">
+		
+		
+<p>
+Components are configured by <em>
+<a href="bindings.html">binding</a>
+</em> their parameters.  In
+a page or component specification, the <a href="spec.html#spec.binding">&lt;binding&gt;</a> element is used to
+bind component parameters.
+</p>
+
+<p>
+Inside an HTML template, attributes of the tag are used to bind parameters. This can be
+very succinct.  In some cases where an <a href="http://www.ognl.org">OGNL</a> expression is used, the
+value can become quite long or complex ... in which case, converting the component
+to be a declared component (that is, defined in the page or component specification) and
+using the <a href="spec.html#spec.binding">&lt;binding&gt;</a> element will be more manageable.
+</p>
+
+
+<p>
+Tapestry will <em>merge</em> together parameter bindings in the specification with
+those provided directly in the template.  Generally speaking, conflicts (the same
+parameter bound in both places) will be an error.  The exception
+is when the parameter bound in the HTML template, as an attribute, is a literal string
+value ... in which case, Tapestry assumes that the attribute value is
+there for WYSIWYG purposes and is quietly ignored.
+</p>
+
+
+<p>
+Components may have both <em>formal</em> and <em>informal</em> parameters.  The component
+specification defines each formal parameters using the <a href="spec.html#spec.parameter">&lt;parameter&gt;</a> element, and a component
+indicates whether it accepts or rejects informal parameters with
+the allow-informal-parameters attribute of the <a href="spec.html#spec.component-specification">&lt;component-specification&gt;</a> element.
+</p>
+
+<p>
+Informal parameters are <em>not</em> limited to simply strings; using 
+<a href="bindings.html">binding reference</a> prefixes, it is possible for them to be OGNL expressions, references to assets, or
+anything else.
+</p>
+
+<p>
+If a component does not allow informal parameters, then attempting to bind
+any parameters (beyond the formal set of parameters for the component) is an error.
+The exception to this is literal values in the template, which are (again)
+assumed to be there for WYSIWYG purposes, and quietly ignored.
+</p>
+
+<p>
+Two final notes about informal parameters:
+</p>
+
+<ul>
+  <li>Informal parameters in the template are assumed to be literal strings
+    unless they have a binding prefix (i.e., "ognl:", "message:", or
+    so forth).</li>
+  <li>
+    Informal parameters are normally converted to string values and
+    added as additional attributes in the output markup.  A special case
+    is when the value for an informal parameter is an <a href="../tapestry/apidocs/org/apache/tapestry/IAsset.html">IAsset</a>
+    (possibly specified with the "asset:" prefix), in which case the
+    attribute value will be the <em>URL</em> for the asset.
+  </li>
+</ul>
+
+<subsection name="Seperation of Concerns">
+	
+
+<p>
+Before Tapestry 3.0, there was a more clear separation of concerns. The template could only have declared
+components (not implicit), and any informal attributes in the template were always static values. The type
+of the component and all its formal parameters were always expressed in the specification. The template was very much
+focused on presentation, and the specification was very much focused on business logic. There were
+always minor exceptions to the rules, but in general, seperation of concerns was very good.
+</p>
+
+<p>
+With Tapestry 3.0, you can do more in the HTML template, and the specification file is much less
+important ... but the seperation of concerns is much more blurred together. It is very much acceptible to
+mix and match these approaches, even within a single page. In general, when learning Tapestry, or when prototyping, it
+is completely appopriate to do as much as possible in the HTML template. For large and complex
+applications, there are benefits to moving as much of the dynamic logic as possible out
+of the template and into the specification.
+</p>
+
+</subsection>
+
+</subsection> <!-- templates.components.parameters -->
+
+<subsection name="Formal and informal parameters">
+		
+		
+<p>
+Components may accept two types of parameters: <em>formal</em>
+and <em>informal</em>.  Formal parameters are those defined in the
+component's specification, using the <a href="spec.html#spec.parameter">&lt;parameter&gt;</a> element.
+Informal parameters are <em>additional</em> parameters, beyond those
+known when the component was created.
+</p>
+
+<p>
+The majority of components that accept informal parameters simply emit the informal
+parameters as additional attributes.  Why is that useful?  Because it allows you to
+specify common HTML attributes such as class	or id,
+or JavaScript event handlers, without requiring that each component define each possible 
+HTML attribute (the list of which expands all the time).
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/>
+If you are used to developing with JSPs and JSP tags, this will be quite a difference. JSP tags have
+the equivalent of	formal parameters (they are called "tag attributes"), but nothing like informal parameters. Often a relatively
+simply JSP tag must be bloated  with dozens of extra attributes, to support arbitrary
+HTML attributes.
+</p>
+
+<p>
+Informal and formal parameters can be specified in either the specification or in the template.
+Informal parameters <em>are not</em>	 limited to literal strings, you may use
+the <code>ognl:</code> and <code>message:</code> prefixes with them as well.
+</p>
+	
+
+<p>
+Not all components allow informal parameters; this is controlled by the
+allow-informal-parameters	 attribute of the
+<a href="spec.html#spec.component-specification">&lt;component-specification&gt;</a> element. Many components do not map directly to an HTML element,
+those are the ones that do not allow informal parameters. If a component forbids informal parameters,
+then any informal parameters in the specification or the template will result in errors, with one exception:
+static strings in the HTML template are simply ignored when informal parameters are forbidden; they
+are presumed to be there only to support WYSIWYG preview.
+</p>
+
+<p>
+Another conflict can occur when the HTML template specified an attribute that the component needs
+to render itself. For example, the <a href="site:DirectLink">DirectLink</a> component generates a <code>&lt;a&gt;</code> tag,
+and needs to control the href attribute. However, for preview purposes, it often will 
+be written into the HTML template as:
+</p>
+
+<source xml:space="preserve">
+  &lt;a jwcid="@DirectLink" listener="listener:. . ." href="#"&gt; . . . &lt;/a&gt;</source>
+
+
+<p>
+This creates a conflict: will the template href (the literal string "#")	 be used,
+or the dynamically generated URL produced by the <a href="site:DirectLink">DirectLink</a> component, or both? The answer is: 
+the component wins. The href attribute in the template is ignored.
+</p>
+
+<p>
+Each component declares a list of reserved names using the <a href="spec.html#spec.reserved-parameter">&lt;reserved-parameter&gt;</a> element; these
+are  names which are not allowed as informal parameters, because the component generates 
+the named attribute itself, and doesn't want the value it writes to be overriden by an informal
+parameter.   Case is ignored when comparing attribute names to reserved names.
+</p>
+
+</subsection> <!-- template.components.formal -->
+
+
+
+</section>  <!-- template.components -->
+
+<section name="Template directives">
+	
+
+<p>
+For the most part, a Tapestry page or component template consists of 
+just static HTML intermixed with tags representing components (containing the jwcid attribute).
+The overarching goal is to make the Tapestry extensions completely invisible.
+</p>	
+
+<p>
+Tapestry supports a limited number of additional directives that are not about component placement, but 
+instead address other concerns about integrating the 
+efforts of HTML developers with the Java developers responsible
+for the running application.
+</p>
+
+<subsection name="Localization">
+	 
+	 
+<p>
+Tapestry includes a number of <a href="localization.html">localization features</a>
+localization features.  As we've seen, it is possible to access the messages for a page or component using the
+<code>message:</code>	 prefix on a component parameter.
+</p>
+
+<p>
+What about the static text in the template itself?  How does that get translated?  One possibility
+would be to make use of the Insert component for each piece of text to be displayed, for example:
+</p>
+
+<source xml:space="preserve">
+  &lt;span jwcid="@Insert" value="message:hello"&gt;Hello&lt;/span&gt;</source>
+
+
+<p>
+This snippet will get the <code>hello</code> message from the page's  message catalog  
+and insert it into the response.  The text inside the &lt;span&gt;
+tag is useful for WYSIWYG preview, but will be discarded at runtime in favor of a message string
+from the catalog, such as "Hello", "Hola" or "Bonjour" (depending on the selected locale).
+</p>
+
+<p>
+Because, in an internationalized application, this  scenario
+will occur with great frequency, Tapestry includes
+a special directive to perform the equivalent function:
+</p>
+
+<source xml:space="preserve">
+  &lt;span key="hello"&gt;Hello&lt;/span&gt;</source>
+
+
+<p>
+This is not an <a href="site:Insert">Insert</a> component, but behaves in a similar way. The tag used <em>must be</em>
+&lt;span&gt;. You do not use the <code>message:</code> prefix
+on the message key (<code>hello</code>). You can't use OGNL expressions.
+</p>
+
+<p>
+Normally, the &lt;span&gt; does not render, just the message.
+However, if you specify any additional attributes in the &lt;span&gt; tag (such as, commonly,
+id, class, or style, to specify a CSS style),
+then the &lt;span&gt; will render around the message.  For example, the template:
+</p>
+
+<source xml:space="preserve">
+  &lt;span class="error" key="invalid-access"&gt;Invalid Access&lt;/span&gt;</source>
+
+<p>
+might render as:
+</p>
+
+<source xml:space="preserve">
+  &lt;span class="error"&gt;You do not have the necessary access.&lt;/span&gt;
+</source>
+
+
+<p>
+In this example, the placeholder text "Invalid Access" was replaced with a much
+longer message acquired from the message catalog.
+
+</p>
+
+<p>
+In rare cases, your message may have pre-formatted HTML inside it.  Normally, output is
+filtered, so that any reserved
+HTML characters in a message string are expanded to HTML entities.  For example,
+a &lt;	 will be expanded to &amp;lt; If this is not desired,
+add  the attribute value <code>raw="true"</code> to the &lt;span&gt;. 
+This defeats the filtering, and text in the message
+is passed through as-is.
+</p>
+
+	
+</subsection> <!-- template.directives.l10n -->
+	
+<subsection name="$remove$ jwcid&#10;&#9; ">
+	
+
+<p>
+HTML templates in Tapestry serve two purposes. On the one hand, they are used to dynamically render
+pages that end up in client web browsers. On the other hand, they allow HTML developers to use WYSIWYG editors
+to modify the pages without running the full application.	
+</p>
+
+<p>
+We've already seen two ways in which Tapestry accomidates WYSIWYG preview.  Informal component
+parameters may be quietly dropped
+if they conflict with reserved names defined by the component.	Components that discard their body may enclose
+static text used for WYSIWYG prefix.
+</p>
+
+<p>
+In some cases, we need even more direct control over the content of the template.  Consider, for example,
+the following HTML template:	
+</p>
+
+<source xml:space="preserve">
+&lt;table&gt;
+  &lt;tr&gt;
+    &lt;th&gt;First Name&lt;/th&gt;
+    &lt;th&gt;Last Name&lt;/h&gt;
+  &lt;/tr&gt;
+  &lt;tr jwcid="loop"&gt;
+    &lt;td&gt;&lt;span jwcid="insertFirstName"&gt;John&lt;/span&gt;&lt;/td&gt;
+    &lt;td&gt;&lt;span jwcid="insertLastName"&gt;Doe&lt;/span&gt;&lt;/td&gt;
+  &lt;/tr&gt;
+  &lt;tr&gt;
+    &lt;td&gt;Frank&lt;/td&gt;
+    &lt;td&gt;Smith&lt;/td&gt;
+  &lt;/tr&gt;
+  &lt;tr&gt;
+    &lt;td&gt;Jane&lt;/td&gt;
+    &lt;td&gt;Jones&lt;/td&gt;
+  &lt;/tr&gt;
+&lt;/table&gt;
+</source>
+
+<p>
+This is part of the HTML template that writes out the names of a list of people, perhaps from some kind of database.
+When this page renders, the <code>loop</code>	 component (presumably a <a href="site:Foreach">Foreach</a>, such details
+being in the page's specification)
+will render its body zero or more times. So we might see rows for "Frank Miller", "Alan Moore" and so forth
+(depending on the content of the database).
+However, every listing will also include "Frank Smith" and "Jane Jones" ... because the HTML developer left those
+two rows in, to ensure that the layout of the table was correct with more than one row.
+</p>
+
+<p>
+Tapestry allows a special jwcid, <code>$remove$</code>, for this case. A tag so marked is
+not a component, but is instead eliminated from the 
+template. It is used, as in this case, to mark sections of the template that are just there for WYSIWYG preview.
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/>
+Normally, <code>$remove$</code>	 would not be a valid component id, because it contains a dollar sign.
+</p>
+
+<p>
+With this in mind, the template can be rewritten:	
+</p>
+
+
+<source xml:space="preserve">
+&lt;table&gt;
+  &lt;tr&gt;
+    &lt;th&gt;First Name&lt;/th&gt;
+    &lt;th&gt;Last Name&lt;/h&gt;
+  &lt;/tr&gt;
+  &lt;tr jwcid="loop"&gt;
+    &lt;td&gt;&lt;span jwcid="insertFirstName"&gt;John&lt;/span&gt;&lt;/td&gt;
+    &lt;td&gt;&lt;span jwcid="insertLastName"&gt;Doe&lt;/span&gt;&lt;/td&gt;
+  &lt;/tr&gt;
+  &lt;tr jwcid="$remove$"&gt;
+    &lt;td&gt;Frank&lt;/td&gt;
+    &lt;td&gt;Smith&lt;/td&gt;
+  &lt;/tr&gt;
+  &lt;tr jwcid="$remove$"&gt;
+    &lt;td&gt;Jane&lt;/td&gt;
+    &lt;td&gt;Jones&lt;/td&gt;
+  &lt;/tr&gt;
+&lt;/table&gt;
+</source>
+<p>
+With the <code>$remove$</code> blocks in place, the output is as expected, one table row for each
+row read from the database,
+and "Frank Smith" and "Jane Jones" nowhere to be seen.
+</p>
+
+<p>
+<strong>Warning:</strong>
+<br/>
+	It's not allowed to put components inside a removed block. This is effectively the same rule that prevents
+	components from being put inside discarded component bodies. Tapestry will throw an exception if a template
+	violates this rule.	
+</p>
+	
+	
+</subsection> <!-- template.directives.remove -->
+
+<subsection name="$content$ jwcid">
+	
+	
+<p>
+In Tapestry, components can have their own templates. Because of how components integrate their own templates
+with their bodies (the portion from their container's template), you can do a lot of interesting things. It is very
+common for a Tapestry application to have a Border component: a component that produces the &lt;html&gt;,
+&lt;head&gt;, and &lt;body&gt; tags (along with additional tags
+to reference stylesheets), plus some form of navigational control (typically, a nested table and a collection of links and images).
+</p>	
+
+<p>
+Once again, maintaining the ability to use WYSIWYG preview is a problem.  Consider the following:
+</p>
+
+<source xml:space="preserve">
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;title&gt;Home page&lt;/title&gt;
+    &lt;link ref="stylesheet" href="style.css" type="text/css"/&gt;
+  &lt;/head&gt;
+  &lt;body&gt;
+    &lt;span jwcid="border"&gt;
+    
+      &lt;!-- Page specific content: --&gt;
+      
+      &lt;form jwcid=". . ."&gt;
+        . . .
+      &lt;/form&gt;
+    &lt;/span&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+</source>
+
+
+
+<p>
+It is quite common for Tapestry applications to have a <em>Border</em>	
+component, a component that is used by pages to provide the
+&lt;html&gt;, &lt;head&gt;, and
+&lt;body&gt; tags, plus common navigational features (menus,
+copyrights, and so forth). In this example, it is presumed that the <code>border</code>
+component is a reference to just such as component.
+</p>
+
+<p>
+When this page renders, the page template will provide the &lt;html&gt;, &lt;head&gt; and &lt;body&gt; tags.
+Then when the <code>border</code> component renders, it will <em>again</em>
+render those tags (possibly with different attributes, and mixed in with much other stuff).
+</p>
+
+<p>
+If we put a <code>$remove$</code>	on the &lt;html&gt; tag in the page template, the entire page will
+be removed, causing runtime exceptions.
+</p>
+
+<p>
+Instead, we want to identify that the portion of the template <em>inside</em>
+the &lt;body&gt; tag (on the page template) as the only part that should be used. The <code>$content$</code>
+component id is used for this purpose:
+</p>
+
+<source xml:space="preserve">
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;title&gt;Home page&lt;/title&gt;
+    &lt;link ref="stylesheet" href="style.css" type="text/css"/&gt;
+  &lt;/head&gt;
+  &lt;body jwcid="$content$"&gt;
+    &lt;span jwcid="border"&gt;
+    
+      &lt;!-- Page specific content: --&gt;
+      
+      &lt;form jwcid=". . ."&gt;
+        . . .
+      &lt;/form&gt;
+    &lt;/span&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+</source>
+
+
+<p>
+The &lt;body&gt; tag, the text preceding its open tag, the &lt;/body&gt;	tag, and the text following
+it are all removed.  It's as if the template consisted only of the &lt;span&gt; tag for the <code>border</code> component.
+</p>
+
+</subsection> <!-- template.directives.content -->
+
+	
+</section>  <!-- template.directives -->
+
+</body>
+</document>

Propchange: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/template.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/upgrade.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/upgrade.xml?rev=418665&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/upgrade.xml (added)
+++ tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/upgrade.xml Sun Jul  2 17:17:29 2006
@@ -0,0 +1,412 @@
+<?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.
+-->
+<document>
+<properties>
+<title>Upgrading from Tapestry 3.0</title>
+</properties>
+<body>
+ 
+<p>
+One goal of Tapestry 4.0 is to make upgrading from release 3.0 as painless as possible.  
+</p>
+ 
+<p>
+Tapestry 4.0 still supports the Tapestry 3.0 DTDs (with minor exceptions). 
+</p>
+
+<section name="Defining the servlet path">
+  
+  
+<p>
+In Tapestry 3.0, the framework could automatically determine the servlet path (used when constructing new URLs), because there was only a
+single mapping.  The convention was to map the servlet to "/app", but any path-based mapping would automatically work.
+</p>  
+
+<p>
+Because of <a href="friendly-urls.html">friendly URLs</a>, there are any number of
+possible servlet mappings in Tapestry 4.0, so you must inform Tapestry what the correct
+mapping is.  It is necessary to define, to Tapestry, what this mapping is,
+using the org.apache.tapestry.servlet-path <a href="configuration.html#configuration.properties">configuration property</a>.
+</p>
+  
+</section> <!-- upgrade.servlet-path -->
+
+<section name="Defining Engine Services">
+  
+  
+<p>
+Tapestry 3.0 allowed engine services to be defined in the application specification using
+a &lt;service&gt; element. This is no longer supported in the 4.0 DTD.
+</p>
+  
+<p>
+Engine services are now defined using HiveMind, in the <code>tapestry.services.ApplicationServices</code> configuration point.
+The following is the chart service from the Workbench example:
+</p>
+
+<source xml:space="preserve">
+  &lt;contribution configuration-id="tapestry.services.ApplicationServices"&gt;
+    &lt;service name="chart" object="service:Chart"/&gt;
+  &lt;/contribution&gt;
+
+  &lt;service-point id="Chart" interface="org.apache.tapestry.engine.IEngineService"&gt;
+    &lt;invoke-factory&gt;
+      &lt;construct class="chart.ChartService"&gt;
+        &lt;set-object property="exceptionReporter" value="infrastructure:requestExceptionReporter"/&gt;
+        &lt;set-object property="response" value="infrastructure:response"/&gt;
+        &lt;set-object property="linkFactory" value="infrastructure:linkFactory"/&gt;
+      &lt;/construct&gt;
+    &lt;/invoke-factory&gt;
+  &lt;/service-point&gt;
+</source>
+
+<p>
+The &lt;service&gt; element in a Tapestry 3.0 DTD is now <strong>ignored</strong>.
+</p>
+
+<p>
+The <a href="../tapestry/apidocs/org/apache/tapestry/engine/IEngineService.html">IEngineService</a> interface has changed in non-backwards compatible ways. If your application created
+custom engine services, you will have to make changes to your code. If your custom service was
+based on the <code>org.apache.tapestry.engine.AbstractService</code> class, that class has been removed
+so you will have significant rewrites. As a suggested course of action, find the service
+that the original service was based on, and build a new service based on that Tapestry service.
+For example, if the original service was based on <code>org.apache.tapestry.asset.AssetService</code>, then
+get the source for the AssetService, and model your service after the new implementation.
+</p>
+
+</section>  <!-- upgrade.service -->
+
+<section name="Component Parameters">
+  
+  
+<p>
+Tapestry 4.0 has greatly streamlined  <a href="components.html#components.parameters">component parameters</a>.
+</p>
+
+<subsection name="Parameter Type">
+  
+
+<p>
+In Tapestry 3.0, the <a href="spec.html#spec.parameter">&lt;parameter&gt;</a> element included a type attribute. This has been removed in Tapestry 4.0.  
+</p>
+
+<p>
+The parameter type is now determined from the Java class, by examining the accessor methods for the property.
+</p>
+
+<p>
+Tapestry 3.0 required an exact match on values bound to parameters. The bound value had to be assignable to the parameter's type.
+In Tapestry 4.0, parameters include built-in <em>coercion</em>; Tapestry will attempt to coerce the value extracted from the bound property 
+into the correct type.
+This is especially useful when using literal bindings for numeric properties.  For example, an HTML template may specify a numeric value
+to an attribute as a simple string:
+</p>
+  
+<source xml:space="preserve">
+  &lt;span jwcid="@MyComponent" intParam="50"/&gt;
+</source>
+
+<p>
+The type of the parameter is determined from the accessor method:
+</p>
+
+<source xml:space="preserve">
+public abstract class MyComponent . . .
+
+  public abstract int getIntParam();
+</source>
+  
+<p>
+Tapestry will convert the string value to an integer automatically.
+</p>  
+
+<p>
+The coercion rules are driven by a number of configuration points and services, starting with
+the <code>tapestry.coerce.ValueConverter</code> service.
+</p>
+
+</subsection>
+  
+  
+<subsection name="Parameter Direction">
+  
+
+
+<p>
+In Tapestry 3.0, it was necessary to inform Tapestry of how and when a component parameter property was accessed -- this
+was parameter direction.
+Parameter direction is now ignored; Tapestry 4.0 now generates smart, caching accessor methods for parameter properties that work properly
+in all cases.  In effect, all parameters are now of direction auto (but its a smarter, more flexible version of direction
+auto than was available in Tapestry 3.0).
+</p>
+
+<p>
+This may be of concern if your component used the custom parameter direction. In Tapestry 3.0, direction custom meant that your code
+would directly access the <a href="../tapestry/apidocs/org/apache/tapestry/IBinding.html">IBinding</a> object for the parameter, and no property for the parameter would be created.  In Tapestry 4.0, 
+a property <em>will</em> be created ... even if you continue to use the 3.0 DTD and specify direction custom.
+</p>
+
+<p>
+<strong>Warning:</strong>
+<br/>
+  You should search for all component parameters that use direction custom and update the Java class.
+</p>
+
+<p>
+For example, if you had a Tapestry 3.0 specification for a listener parameter:
+</p>
+
+<source xml:space="preserve">
+  &lt;parameter name="listener" direction="custom" type="org.apache.tapestry.IActionListener"/&gt;  
+</source>
+
+<p>
+Then your 3.0 source code might look like:
+</p>
+
+<source xml:space="preserve">
+  public abstract IBinding getListenerBinding();
+  
+  public void someMethod(. . .)
+  {
+    IBinding binding = getListenerBinding();
+    
+    if (binding != null)
+    {
+      IActionListener listener = (IActionListener) binding.getObject("listener", IActionListener.class);
+      
+      if (listener != null)
+        listener.actionTriggered(this, cycle);
+    }
+    
+    . . .      
+</source>
+
+<p>
+In Tapestry 4.0, the specification is much simpler:
+</p>
+
+<source xml:space="preserve">
+  &lt;parameter name="listener"/&gt;
+</source>
+
+<p>
+As is the Java code:
+</p>
+
+<source xml:space="preserve">
+  public abstract IActionListener getListener();
+  
+  public void someMethod(. . .)
+  {
+    IActionListener listener = getListener();
+    
+    if (listener != null)
+      listener.actionTriggered(this, cycle);
+  }
+  
+  . . .
+</source>
+
+<p>
+Tapestry takes care of de-referencing the binding (if the parameter is bound), along with type checks or coercions.
+</p>
+
+</subsection>
+
+<subsection name="Accessing binding objects">
+  
+  
+<p>
+In Tapestry 3.0, it was possible to access a <a href="../tapestry/apidocs/org/apache/tapestry/IBinding.html">IBinding</a> object for a parameter by defining an additional property in your component's
+Java code:
+</p>
+
+<source xml:space="preserve">
+  public abstract IBinding getListenerBinding();
+</source>
+
+<p>
+This is no longer supported; the correct way to obtain a binding object is via the getBinding() method.  
+</p>
+
+<p>
+<strong>Note:</strong>
+<br/>
+Because of the other improvements to parameters, it is virtually never necessary to obtain a binding object.
+</p>
+  
+</subsection>
+
+<subsection name="Default value">
+  
+  
+<p>
+In the Tapestry 3.0 DTD, the optional default-value attribute was used to provide an OGNL expression to use for a parameter, if the
+parameter is not otherwise bound.  In the Tapestry 4.0 DTD, the default-value attribute is a <a href="bindings.html">binding reference</a>.  The following are
+equivalent:
+</p>
+
+<source xml:space="preserve">
+  &lt;parameter name="foo" type="int" default-value="bar.baz"/&gt;  &lt;!-- 3.0 --&gt;
+  
+  &lt;parameter name="foo" default-value="bar.baz"/&gt;             &lt;!-- 4.0 --&gt;
+</source>
+  
+
+<source xml:space="preserve">
+  &lt;parameter name="bar" type="java.lang.String" 
+    default-value="messages.getMessage('default-bar')"/&gt;      &lt;!-- 3.0 --&gt;
+  
+  &lt;parameter name="bar" default-value="message:default-bar"/&gt; &lt;!-- 4.0 --&gt; 
+</source>
+  
+  
+  
+  
+</subsection>
+
+<subsection name="Inherited binding">
+  
+  
+<p>
+Tapestry 3.0 included an &lt;inherited-binding&gt; element, this was a way to directly pass the <a href="../tapestry/apidocs/org/apache/tapestry/IBinding.html">IBinding</a> object for a component parameter
+to a parameter of a nested component. This is no longer supported in Tapestry 4.0; instead, the property for the component parameter should be 
+bound to the nested component parameter:
+</p>
+
+<source xml:space="preserve">
+
+  &lt;!-- 3.0 --&gt;
+  
+  &lt;parameter name="itemCount" type="int"/&gt;
+
+  &lt;component id="nested" type="Nested"&gt;
+    &lt;inherited-binding name="count" parameter-name="itemCount"/&gt;
+  &lt;/component&gt;
+  
+  &lt;!-- 4.0 --&gt;
+  
+  &lt;parameter name="itemCount"/&gt;
+  
+  &lt;component id="nested" type="Nested"&gt;
+    &lt;binding name="count" value="itemCount"/&gt;
+  &lt;/component&gt;
+
+</source>
+
+<p>
+<strong>Warning:</strong>
+<br/>
+  inherited-binding may make a comeback in Tapestry 4.0!
+</p>
+  
+</subsection>
+  
+</section> <!-- upgrade.parameters -->
+
+
+<section name="Specified Properties">
+  
+  
+<p>
+Property specifications in Tapestry 4.0 have been simplified.  The specification element has changed
+from &lt;property-specification&gt; to the simpler, <a href="spec.html#spec.property">&lt;property&gt;</a>.
+</p>
+
+<p>
+In Tapestry 3.0, it was necessary to specify the type of the property; this is no longer necessary or possible. The type
+attribute has been removed, and the type is determined from the Java code (and defaults to Object if 
+the Java code does not define abstract accessors).
+</p>
+  
+<p>
+In addition, any abstract properties in the Java code will be converted into transient properties, even if there is no
+matching <a href="spec.html#spec.property">&lt;property&gt;</a> element.  Typically, the <a href="spec.html#spec.property">&lt;property&gt;</a> element is only used when the property is either
+not referenced inside Java code (such as a listener method), or when when the property must be persistent.
+</p>
+
+<p>
+In the 3.0 DTDs, properties could have an initial value set. The initial-value attribute was an OGNL expression used to
+initial the property when the page is first constructed, and when the page is detached (at the end of a request cycle). The initial value
+may instead be specified as the enclosed character data of the &lt;property-specification&gt; element.
+</p>
+
+<p>
+Using the 4.0 DTDs, this is still true, but the initial-value attribute (or the enclosed character data) is a <a href="bindings.html">binding reference</a> with
+a default prefix of "ognl:".
+</p>
+  
+</section> <!-- upgrade.property -->
+
+<section name="Managed beans">
+  
+  
+<p>
+The <a href="spec.html#spec.bean">&lt;bean&gt;</a> element is used to define managed beans. In Tapestry 3.0, it could contain &lt;set-property&gt; and &lt;set-message-property&gt;
+elements to configure the properties of the bean.
+</p>
+  
+<p>
+In Tapestry 4.0, these two elements have been replaced by the <a href="spec.html#spec.set">&lt;set&gt;</a> element, which uses a <a href="bindings.html">binding reference</a> to provide the 
+value.
+</p>
+
+</section>  <!-- upgrade.bean -->
+
+<section name="Dependency Changes">
+  
+  
+<p>
+Part of the transition to Tapestry 4.0, and targetting (in a later release) a minimum JDK of 1.5, is the <em>removal</em> of support for the
+Jakarta commons-lang library.  commons-lang defined an Enum class that makes it impossible to compile code for JDK 1.5 ("enum" is a reserved word
+in JDK 1.5).  With the loss of that dependency, so goes org.apache.tapestry.form.EnumPropertySelectionModel, an <a href="../tapestry/apidocs/org/apache/tapestry/form/IPropertySelectionModel.html">IPropertySelectionModel</a> implementation.
+</p>
+  
+</section>
+
+<section name="Other code changes">
+  
+  
+<p>
+A number of more subtle, and more rarely used, changes exist between the 3.0 and 4.0 releases.
+</p>  
+
+<p>
+The contract for <a href="../tapestry/apidocs/org/apache/tapestry/resolver/ISpecificationResolverDelegate.html">ISpecificationResolverDelegate</a> has changed.  The specifications returned by the delegate are now cached by Tapestry
+exactly as if they had been read from files on the classpath or web context.
+</p>
+  
+</section>
+
+<section name="Changes to Components">
+  
+  
+  <subsection name="Image and Rollover">
+    
+    
+    <p>
+      The border parameter of the <a href="site:Image">Image</a> and <a href="site:Rollover">Rollover</a> components has been removed, for XHTML compliance.
+      You may still specify a value for border as an informal parameter ... or better yet, handle this using CSS.
+    </p>
+      
+  </subsection>
+  
+</section>
+
+</body>
+</document>

Propchange: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/upgrade.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/validation.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/validation.xml?rev=418665&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/validation.xml (added)
+++ tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/validation.xml Sun Jul  2 17:17:29 2006
@@ -0,0 +1,422 @@
+<?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.
+-->
+<document>
+<properties>
+<title>Input Validation</title>
+</properties>
+<body>
+
+<p>
+  The tapestry validation system provides a very powerful means of validating data intuitively on most
+  of the form element components, such as <a href="site:TextField">TextField</a>, <a href="site:TextArea">TextArea</a>, <a href="site:Checkbox">Checkbox</a>, and so forth.  All of these
+  components implement the interface
+  <a href="../tapestry/apidocs/org/apache/tapestry/form/IFormComponent.html">IFormComponent</a>, and include the necessary hooks to fit into
+  the overall validation framework.
+</p>
+<p>
+  Localization, server-side, and client side validation are handled by the framework,
+  as well as the ability to extend or override most of the built in functionality to suit your purposes as
+  you see fit.
+</p>
+
+  <p>
+    Validation has evolved over time (the first attempt at proper validation using Tapestry occured back in 2001).
+    Through Tapestry 3, validation was limited to the <a href="site:ValidField">ValidField</a> component (which is now deprecated).
+    For Tapestry 4, the APIs related to validation were effectively rewritten, resulting in a more powerful, more
+    extensible approach that can be used with all kinds of form element components. 
+  </p>
+
+<section name="FieldLabel component">
+  
+  <p>
+Generally speaking, every form input component (<a href="site:TextField">TextField</a>, etc.) will be paired with a <a href="site:FieldLabel">FieldLabel</a> component.
+The FieldLabel is responsible for generating the HTML &lt;label&gt; element, which is extremely effective for
+accessible user interfaces (user interfaces that work for people with visual disabilities).  Typical usage:
+  </p>
+  
+<source xml:space="preserve">
+&lt;tr&gt;
+   &lt;td&gt;&lt;label jwcid="@FieldLabel" field="component:userName"&gt;User Name&lt;/label&gt;&lt;/td&gt;
+   &lt;td&gt;&lt;input jwcid="userName@TextField" value="ognl:userName" validators="validators:required" displayName="User Name" size="30"/&gt;
+&lt;/tr&gt;
+</source>  
+  
+ 
+  <p>
+    At runtime, this may render as:
+  </p> 
+ 
+  <source xml:space="preserve">
+&lt;tr&gt;
+   &lt;td&gt;&lt;label for="userName"&gt;User Name&lt;/label&gt;&lt;/td&gt;
+   &lt;td&gt;&lt;input name="userName" id="userName" value="" size="30"/&gt;
+&lt;/tr&gt;
+</source> 
+  
+  <p>
+    However, this is not all there is to FieldLabel.  An important part of validation is <em>decoration</em> of fields, to mark
+    when they contain errors.  This is one of the responsibilities <a href="../tapestry/apidocs/org/apache/tapestry/valid/IValidationDelegate.html">IValidationDelegate</a> ... decorating fields and labels.
+  </p>  
+  
+  <p>
+    If the above form is submitted without specifying a user name, the userName field will be in error. The page will be redisplayed
+    to show the user the error message and the decorated fields and labels.  The <em>default</em> decoration is primitive, but effective:
+  </p>
+  
+  
+  <source xml:space="preserve">
+&lt;tr&gt;
+   &lt;td&gt;&lt;font color="red"&gt;&lt;label for="userName"&gt;User Name&lt;/label&gt;&lt;/font&gt;&lt;/td&gt;
+   &lt;td&gt;&lt;input name="userName" id="userName" value="" size="30"/&gt;&amp;nbsp;&lt;font color="red"&gt;**&lt;/font&gt;
+&lt;/tr&gt;
+</source> 
+  
+  <p>
+   By subclassing the default implementation of <a href="../tapestry/apidocs/org/apache/tapestry/valid/IValidationDelegate.html">IValidationDelegate</a> (the <a href="../tapestry/apidocs/org/apache/tapestry/valid/ValidationDelegate.html">ValidationDelegate</a> class), you can change how these
+   decorations are rendered. It then becomes a matter of providing this custom validation delegate to the <a href="site:Form">Form</a> component, via
+   its delegate parameter. This is covered in more detail shortly.
+  </p>
+  
+  </section> <!-- validation.fieldlabel -->
+  
+  <section name="Field validation">
+    
+    
+    <p>
+      Validation for form element components, such as <a href="site:TextField">TextField</a>, is controlled by two common component parameters
+      provided by all such components: validators and displayName.
+    </p>
+    
+    <p>
+      The validators parameter provides a list of validator objects, objects that implement the <a href="../tapestry/apidocs/org/apache/tapestry/form/validator/Validator.html">Validator</a> interface.
+      Why a list?  Unlike Tapestry 3 validation, each individual validator checks just a single <em>constraint</em>.
+      Contraints are things like minimum string length, maximum string length, minimum numeric  value, etc.  This is a very fine
+      grained approach, and one that is easily extensible to new contraints.
+    </p>
+    
+    <p>
+      The displayName parameter is used to provide the label for the component (perhaps some day, this parameter will be renamed to "label"; why
+      it has such a cumbersome name has been forgotten). In any case, this label is used by the matching <a href="site:FieldLabel">FieldLabel</a> component,
+      and is also incorporated into an error messages created for the component.
+    </p>
+    
+  <subsection name="validators: binding prefix">
+    
+
+    
+    <p>
+      The validators: binding prefix is a powerful shorthand for
+      constructing a list of configured <a href="../tapestry/apidocs/org/apache/tapestry/form/validator/Validator.html">Validator</a> objects. It allows a very declarative style; for
+      example, to state that a field is required with a minimum length of four characters,
+      the following parameter binding could be used (in a page or component specification): 
+      </p>
+    <source xml:space="preserve">
+&lt;binding name="validators" value="validators:required,minLength=4"/&gt;    
+    </source>
+    
+    <p>
+      Notice that the actual type of the data isn't specified in this instance, it is implied by which parameters
+      you specify. A specification is a comma-seperated list of entries. Each entry is in one of the following forms:
+    </p>
+    
+    <ul>
+      <li>
+<em>name</em>
+</li>
+      <li>
+<em>name</em>=<em>value</em>
+</li>
+      <li>
+<em>name[<em>message</em>]</em>
+</li>
+      <li>
+<em>name</em>=<em>value</em>[<em>message</em>]</li>
+      <li>$<em>name</em>
+</li>
+    </ul>
+    
+    <p>
+      Most validator classes are <em>configurable</em>: they have a property that matches their
+      name. For example, <a href="../tapestry/apidocs/org/apache/tapestry/form/validator/MinDate.html">MinDate</a> (which is named "minDate"
+      has a <code>minDate</code> property. A few validators are not configurable ("required" =&gt;
+      <a href="../tapestry/apidocs/org/apache/tapestry/form/validator/Required.html">Required</a>, for example).
+    </p>
+    <p>
+      Validators are expected to have a public no-args constructor. They are also expected to have a
+      <code>message</code> property which is set from the value in brackets.
+      The message is either a literal string, or may be prefixed with a '%' character, to indicate
+      a localized key, resolved using the component's message catalog.
+    </p>
+    <p>
+      When the name is prefixed with a dollary sign, it indicates a reference to a <a href="spec.html#spec.bean">&lt;bean&gt;</a>
+      with the given name.
+    </p>
+    <p>
+      A full validator specification might be:
+      <code>required,email[%email-format],minLength=20[Email addresses must be at least 20 characters long.]</code>
+    </p>
+    
+    <p>
+      Here is a partial list of the validator classes provided and their configurable attributes.
+    </p>
+    <p>
+<strong>Fixme:</strong>
+<br/>
+      Fill in all of the possible attributes started in the table below.
+    </p>
+    <table>
+      <tr>
+        <th>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/Validator.html">Validator</a>
+</th>
+        <th>attributes</th>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/BaseValidator.html">BaseValidator</a>
+</td>
+        <td>
+<code>message</code>
+</td>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/Email.html">Email</a>
+</td>
+        <td>
+<code>none, uses standard email regexp "^\\w[-._\\w]*\\w@\\w[-._\\w]*\\w\\.\\w{2,6}$"</code>
+</td>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/Max.html">Max</a>
+</td>
+        <td>
+<code>max=&lt;maximum value, 10&gt;</code>
+</td>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/MaxDate.html">MaxDate</a>
+</td>
+        <td>
+<code>maxDate=&lt;maximum date, 06/09/2010&gt;</code>
+</td>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/MaxLength.html">MaxLength</a>
+</td>
+        <td>
+<code>maxLength=&lt;maximum length, 23&gt;</code>
+</td>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/Min.html">Min</a>
+</td>
+        <td>
+<code>min=&lt;minimum value, 0.718&gt;</code>
+</td>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/MinDate.html">MinDate</a>
+</td>
+        <td>
+<code>minDate=&lt;minimum date, 04/23/05&gt;</code>
+</td>
+      </tr>
+      <tr>
+        <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/form/validator/MinLength.html">MinLength</a>
+</td>
+        <td>
+<code>minLength=&lt;minmum length, 15&gt;</code>
+</td>
+      </tr>
+    </table>
+    
+    <p>
+<strong>Fixme:</strong>
+<br/>
+      Examples!
+    </p>
+    
+    <p>
+<strong>Fixme:</strong>
+<br/>
+      Write about how the validation constraints specified with the above syntax are universally
+      applied on both the client and server-side, as well as how to override the default behaviour
+      for displaying client-side validation messages via subclassing the Tapestry.default_invalid_field_handler
+      javascript prototyped method.
+    </p>
+    
+  </subsection> <!-- validation.validators -->
+  
+  </section> <!-- validation.fields -->
+    
+    
+  <section name="Extending ValidationDelegate">
+          
+   
+   <p>
+      There are a lot of scenerios where you may wish to do something more than that provided by the 
+      default, like apply a CSS class to labels in error, or even provide the ability to render the error 
+      message directly in or around the label or field.
+      </p>
+      
+      <p>
+      Below is a typical subclass of ValidationDelegate that provides more application-specific decorations:
+      </p>
+      
+      <source xml:space="preserve">
+/**
+ * Provides more intelligent validation delegate support.
+ */
+public class MyValidationDelegate extends ValidationDelegate {
+
+/**
+ * This method is overwritten so that the error message generated during 
+ * server-side validation actually appears next to the field in question.
+ *
+ * Don't be confused by the method names, there is a complimenting writeSuffix
+ * for fields, as well as a pair of writeLabelSuffix/writeLabelPrefix methods to
+ * do the same to labels.
+ * {@inheritDoc}
+ */
+ public void writePrefix(IMarkupWriter writer, IRequestCycle cycle, 
+         IFormComponent component, IValidator validator)
+ {
+     IFieldTracking ft = getCurrentFieldTracking();
+     //there is a default error renderer for fields which simply
+     //writes the message, which is what we want to have happen in this case
+     if (ft != null &amp;&amp; ft.getErrorRenderer() != null) 
+         ft.getErrorRenderer().render(writer, cycle);
+ }
+ 
+ /**
+  * Adds a class style attribute to the label if in error
+  * {@inheritDoc}
+  */
+ public void writeLabelAttributes(IMarkupWriter writer, IRequestCycle cycle, IFormComponent component) {
+      if (isInError(component))
+      {
+         writer.attribute("class", "labelError");
+      }
+ }
+ 
+ }</source>
+  </section> <!-- validation.delegate -->
+  
+  
+  <section name="ValidField component">
+    
+    <p>
+<strong>Warning:</strong>
+<br/>
+      The ValidField component and it's associated validators under org.apache.tapestry.valid should be considered
+      deprecated in favor of the new system found under org.apache.tapestry.form.validator. 
+    </p>
+    
+    <subsection name="validator: binding prefix ">
+      
+      
+      <p>
+        For <a href="site:ValidField">ValidField</a>, validation is specified through a single parameter, validator.  
+        The validator parameter is an object that implements the <a href="../tapestry/apidocs/org/apache/tapestry/valid/IValidator.html">IValidator</a> interface. In Tapestry 3.0, it was necessary to
+        provide a configured Java object as the validator, using Java code, or
+        the specification's &lt;bean&gt; element.
+      </p>
+      
+      <p>
+        Although the ValidField component is deprecated in release 4.0 (and likely to be removed in a later release),
+        some legacy support for ValidField was added in release 4.0 ... a special binding prefix, "validator:", that streamlines
+        the process of assembling a validator object for the validator parameter. 
+      </p>
+      
+      <p>The validator: <a href="bindings.html">binding prefix</a> is a powerful shorthand for specifying validators.
+        The string provided does two things:  it identifies (by a short logical name) the Java class of the validator to create, and
+        it specifies (as a comma seperated list) the properties of the validator to set.   The form of the string is:
+      </p>
+      
+      <source xml:space="preserve">
+        validator:<em>name</em>[,<em>property</em>[=<em>value</em>]]*
+      </source>
+      
+      <p>
+        The name corresponds to contributions to the tapestry.valid.Validators configuration point.  After the name is a list of properties to set.
+        A simple conversion from string value to actual data type is performed.  For boolean properties, the value can be skipped and will default to true. 
+        Alternatively, the value can be prefixed with an exclamation point, and the property will be set to false.  Example:
+      </p>
+      
+      <source xml:space="preserve">
+        validator:string,required,minimumLength=5
+      </source> 
+      
+      <p>
+        In some cases, this is insufficiently powerful to set the properties of the validator instance, in which case the <a href="spec.html#spec.bean">&lt;bean&gt;</a> element can be used
+        instead.
+      </p> 
+      
+      <p>
+        The following validator names are defined:
+      </p>
+      
+      <table>
+        <tr>
+          <th>Name</th>
+          <th>
+<a href="../tapestry/apidocs/org/apache/tapestry/valid/IValidator.html">IValidator</a> implementation class</th>
+        </tr>
+        <tr>
+          <td>string</td> <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/valid/StringValidator.html">StringValidator</a>
+</td>
+        </tr>
+        <tr>
+          <td>date</td>
+          <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/valid/DateValidator.html">DateValidator</a>
+</td>
+        </tr>
+        <tr>
+          <td>email</td>
+          <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/valid/EmailValidator.html">EmailValidator</a>
+</td>
+        </tr>
+        <tr>
+          <td>url</td> 
+          <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/valid/UrlValidator.html">UrlValidator</a>
+</td>
+        </tr>
+        <tr>
+          <td>int</td>
+          <td>
+<a href="../tapestry/apidocs/org/apache/tapestry/valid/IntValidator.html">IntValidator</a>
+</td>
+        </tr>
+      </table>
+      
+    </subsection> <!-- validation.validfield -->
+  </section> <!-- validation.validfield -->
+  
+
+</body>
+</document>

Propchange: tapestry/tapestry4/trunk/src/site/xdoc/UsersGuide/validation.xml
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message