Modified: websites/production/tapestry/content/clustering-issues.html
==============================================================================
--- websites/production/tapestry/content/clustering-issues.html (original)
+++ websites/production/tapestry/content/clustering-issues.html Sat Feb  3 
16:21:22 2018
@@ -36,13 +36,26 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div></div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div>
+
+</div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form 
enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";> 
- <input type="text" name="q"> 
- <input type="submit" value="Search"> 
-</form></div><div class="emblem" style="float:left"><p><a  
href="index.html"><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div><div
 class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Clustering Issues</h1></div></div>
+            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";>
+  <input type="text" name="q">
+  <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a  href="index.html"><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Clustering Issues</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -54,33 +67,7 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><h2 
id="ClusteringIssues-ClusteringIssues">Clustering Issues</h2>
-
-<p>The Servlet API was designed with the intention that there would be only a 
modest amount of server-side state, and that the stored values would be 
individual numbers and strings, and thus, immutable.</p>
-
-<p>However, many web applications do not use the HttpSession this way, instead 
storing large, mutable objects in the session. This is not a problem for single 
servers, but in a cluster, anything stored in the session must be serialized to 
a bytestream and distributed to other servers within the cluster, and restored 
there.</p>
-
-<p>Most application servers perform that serialization and distribution 
whenever HttpSession.setAttribute() is called. This creates a data consistency 
problem for mutable objects, because if you read a mutable session object, 
change its state, but <em>don't</em> invoke setAttribute(), the changes will be 
isolated to just a single server in the cluster.</p>
-
-<p>Tapestry attempts to solve this: any session-persisted object that is read 
during a request will be re-stored back into the HttpSession at the end of the 
request. This ensures that changed internal state of those mutable objects is 
properly replicated around the cluster.</p>
-
-<p>But while this solution solves the data consistency problem, it does so at 
the expense of performance, since all of those calls to setAttribute() result 
in extra session data being replicated needlessly if the internal state of the 
mutable object hasn't changed.</p>
-
-<p>Tapestry has solutions to this, too:</p>
-
-<h3 
id="ClusteringIssues-@ImmutableSessionPersistedObjectAnnotation">@ImmutableSessionPersistedObject
 Annotation</h3>
-
-<p>Tapestry knows that Java's String, Number and Boolean classes are 
immutable. Immutable objects do not require a re-store into the session.</p>
-
-<p>You can mark your own session objects as immutable (and thus not requiring 
session replication) using the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ImmutableSessionPersistedObject.html";>ImmutableSessionPersistedObject</a>
 annotation.</p>
-
-<h3 
id="ClusteringIssues-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject
 Interface</h3>
-
-<p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/OptimizedSessionPersistedObject";>OptimizedSessionPersistedObject</a>
 interface allows an object to control this behavior. An object with this 
interface can track when its mutable state changes. Typically, you should 
extend from the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.html";>BaseOptimizedSessionPersistedObject</a>
 base class.</p>
-
-<h3 
id="ClusteringIssues-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer
 Service</h3>
-
-<p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.html";>SessionPersistedObjectAnalyzer</a>
 service is ultimately responsible for determining whether a session persisted 
object is dirty or not (dirty meaning in need of a restore into the session). 
This is an extensible service where new strategies, for new classes, can be 
introduced.</p></div>
+                <div id="ConfluenceContent"><h2 
id="ClusteringIssues-ClusteringIssues">Clustering Issues</h2><p>The Servlet API 
was designed with the intention that there would be only a modest amount of 
server-side state, and that the stored values would be individual numbers and 
strings, and thus, immutable.</p><p>However, many web applications do not use 
the HttpSession this way, instead storing large, mutable objects in the 
session. This is not a problem for single servers, but in a cluster, anything 
stored in the session must be serialized to a bytestream and distributed to 
other servers within the cluster, and restored there.</p><p>Most application 
servers perform that serialization and distribution whenever 
HttpSession.setAttribute() is called. This creates a data consistency problem 
for mutable objects, because if you read a mutable session object, change its 
state, but <em>don't</em> invoke setAttribute(), the changes will be isolated 
to just a single server in the cluster.
 </p><p>Tapestry attempts to solve this: any session-persisted object that is 
read during a request will be re-stored back into the HttpSession at the end of 
the request. This ensures that changed internal state of those mutable objects 
is properly replicated around the cluster.</p><p>But while this solution solves 
the data consistency problem, it does so at the expense of performance, since 
all of those calls to setAttribute() result in extra session data being 
replicated needlessly if the internal state of the mutable object hasn't 
changed.</p><p>Tapestry has solutions to this, too:</p><h3 
id="ClusteringIssues-@ImmutableSessionPersistedObjectAnnotation">@ImmutableSessionPersistedObject
 Annotation</h3><p>Tapestry knows that Java's String, Number and Boolean 
classes are immutable. Immutable objects do not require a re-store into the 
session.</p><p>You can mark your own session objects as immutable (and thus not 
requiring session replication) using the <a  class="external-link" href="
 
http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ImmutableSessionPersistedObject.html";>ImmutableSessionPersistedObject</a>
 annotation.</p><h3 
id="ClusteringIssues-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject
 Interface</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/OptimizedSessionPersistedObject";>OptimizedSessionPersistedObject</a>
 interface allows an object to control this behavior. An object with this 
interface can track when its mutable state changes. Typically, you should 
extend from the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.html";>BaseOptimizedSessionPersistedObject</a>
 base class.</p><h3 
id="ClusteringIssues-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer
 Service</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/or
 
g/apache/tapestry5/services/SessionPersistedObjectAnalyzer.html">SessionPersistedObjectAnalyzer</a>
 service is ultimately responsible for determining whether a session persisted 
object is dirty or not (dirty meaning in need of a restore into the session). 
This is an extensible service where new strategies, for new classes, can be 
introduced.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/component-classes.html
==============================================================================
--- websites/production/tapestry/content/component-classes.html (original)
+++ websites/production/tapestry/content/component-classes.html Sat Feb  3 
16:21:22 2018
@@ -145,7 +145,7 @@
 </div>
 
 
-<p>In most cases, each component class will have a corresponding <a  
href="component-templates.html">component template</a>. However, it is also 
possible for a component class to emit all of its markup itself, without using 
a template.</p><p><em>For Tapestry 4 Users: Component classes in Tapestry 5 are 
much easier than in Tapestry 4. There are no base classes to extend from, the 
classes are concrete (not abstract), and there's no XML file. There is still a 
bit of configuration in the form of Java annotations, but those now go directly 
onto fields of your class, rather than on abstract getters and 
setters.</em></p><h2 id="ComponentClasses-CreatingaTrivialComponent">Creating a 
Trivial Component</h2><p>Creating a page or component in Tapestry 5 is a 
breeze. There are only a few constraints:</p><ul><li>There must be a public 
Java class.</li><li>The class must be in the correct package (see 
below).</li><li>The class must have a public, no-arguments constructor. (The 
default one provided 
 by the compiler is fine.)</li></ul><p>Here's a minimal component that outputs 
a fixed message, using a <a  href="component-templates.html">template</a> with 
a matching file name:</p><div class="sectionColumnWrapper"><div 
class="sectionMacro"><div class="sectionMacroRow"><div class="columnMacro"><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 
1px;"><b>HelloWorld.java</b></div><div class="codeContent panelContent pdl">
+<p>In most cases, each component class will have a corresponding <a  
href="component-classes.html">component template</a>. However, it is also 
possible for a component class to emit all of its markup itself, without using 
a template.</p><p><em>For Tapestry 4 Users: Component classes in Tapestry 5 are 
much easier than in Tapestry 4. There are no base classes to extend from, the 
classes are concrete (not abstract), and there's no XML file. There is still a 
bit of configuration in the form of Java annotations, but those now go directly 
onto fields of your class, rather than on abstract getters and 
setters.</em></p><h2 id="ComponentClasses-CreatingaTrivialComponent">Creating a 
Trivial Component</h2><p>Creating a page or component in Tapestry 5 is a 
breeze. There are only a few constraints:</p><ul><li>There must be a public 
Java class.</li><li>The class must be in the correct package (see 
below).</li><li>The class must have a public, no-arguments constructor. (The 
default one provided by
  the compiler is fine.)</li></ul><p>Here's a minimal component that outputs a 
fixed message, using a <a  href="component-classes.html">template</a> with a 
matching file name:</p><div class="sectionColumnWrapper"><div 
class="sectionMacro"><div class="sectionMacroRow"><div class="columnMacro"><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 
1px;"><b>HelloWorld.java</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package org.example.myapp.components;
 public class HelloWorld
 {
@@ -171,13 +171,13 @@ public class HelloWorld
     }
 }
 </pre>
-</div></div><p>In this example, just like the first one, the component's only 
job is to write out a fixed message. The @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/BeginRender.html";>BeginRender</a>
 annotation is a type of <em><a  href="component-rendering.html">render phase 
annotation</a></em>, a method annotation that instructs Tapestry when and under 
what circumstances to invoke methods of your class.</p><p>These methods are not 
necessarily public; they can have any access level you like (unlike in Tapestry 
4). By convention they usually have package-private access level (the 
default).</p><h2 id="ComponentClasses-ComponentPackages">Component 
Packages</h2><p>Component classes must exist within an appropriate package 
(this is necessary for runtime code transformation and class reloading to 
operate).</p><p>These packages exist under the application's root package, as 
follows:</p><ul><li>For pages, place classes in <em>ro
 ot</em>.<strong>pages</strong>. Page names are mapped to classes within this 
package.</li><li>For mixins, place classes in 
<em>root</em>.<strong>mixins</strong>. Mixin types are mapped to classes within 
this package.</li><li>For other components, place classes in 
<em>root</em>.<strong>components</strong>. Component types are mapped to 
classes within this package.</li></ul><p>In addition, it is common for an 
application to have base classes, often <em>abstract</em> base classes, that 
should not be directly referenced. These should <em>not</em> go in the 
<strong>pages</strong>, <strong>components</strong> or <strong>mixins</strong> 
packages, because they then look like valid pages, components or mixins. 
Instead, use the <em>root</em>.<strong>base</strong> package to store such base 
classes.</p><div class="confluence-information-macro 
confluence-information-macro-warning"><span class="aui-icon aui-icon-small 
aui-iconfont-error confluence-information-macro-icon"></span><div class="confl
 uence-information-macro-body"><p>Only component classes should go in any of 
these controlled packages; classes representing data, or interfaces, or 
anything that isn't precisely a component class, must go elsewhere. Any 
top-level class in any of the controlled packages will be transformed at 
runtime. The only exception is inner classes (anonymous or not), which are 
loaded by the same class loader as the component class loader, but not 
transformed as components.</p></div></div><h2 
id="ComponentClasses-Sub-Folders/Sub-Packages">Sub-Folders / 
Sub-Packages</h2><p>Classes do not have to go directly inside the package 
(pages, components, mixins, etc.). It is valid to create a sub-package to store 
some of the classes. The sub-package name becomes part of the page name or 
component type. Thus you might define a page component 
<code>com.example.myapp.pages.admin.CreateUser</code> and the logical page name 
(which often shows up inside URLs) will be 
<strong>admin/CreateUser</strong>.</p><p>Tap
 estry performs some simple optimizations of the logical page name (or 
component type, or mixin type). It checks to see if the package name is either 
a prefix or a suffix of the unqualified class name (case insensitively, of 
course) and removes the prefix or suffix if so. The net result is that a class 
name such as <code>com.example.myapp.pages.user.EditUser</code> will have a 
page name of <code>user/Edit</code> (instead of user<code>/EditUser</code>). 
The goal here is to provide shorter, more natural URLs.</p><h2 
id="ComponentClasses-IndexPages">Index Pages</h2><p>One special simplification 
exists for Index pages: if the logical page name is Index after removing the 
package name from the unqualified class name, it will map to the root of that 
folder. A class such as <code>com.example.myapp.pages.user.IndexUser</code> or 
<code>com.example.myapp.pages.user.UserIndex</code> will have a page name of 
<code>user/</code>.</p><p>In previous versions of Tapestry there was also the 
concept of
  a start page configured with the <code><a  
href="configuration.html">tapestry.start-page-name</a></code> configuration 
symbol (defaults to "start"). If a page with a name as configured with that 
symbol exists at the root level, this page is used as the root URL. This has 
precedence over an existing Index page. If for example you have a page class 
<code>com.example.myapp.pages.Start</code> it will map to 
<code>/</code>.</p><div class="confluence-information-macro 
confluence-information-macro-warning"><span class="aui-icon aui-icon-small 
aui-iconfont-error confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Use of start-pages is discouraged 
and support for it will eventually be removed. Use an Index page 
instead.</p></div></div><h2 id="ComponentClasses-Pagesvs.Components">Pages vs. 
Components</h2><p>The distinction between pages and component is very, very 
small. The primary difference is the package name: 
<em>root</em>.<strong>pages</strong>.<
 em>PageName</em> for pages, and 
<em>root</em>.<strong>components</strong>.<em>ComponentType</em> for 
components. Conceptually, page components are simply the <em>root 
component</em> of a page's component tree.</p><p><em>For Tapestry 4 users: 
there was a much greater distinction in Tapestry 4 between pages and 
components, which showed up as separate interfaces and a hierarchy of abstract 
implementations to extend your classes from.</em></p><h2 
id="ComponentClasses-ClassTransformation">Class Transformation</h2><p>Tapestry 
uses your class as a starting point. It <em>transforms</em> your class at 
runtime. This is necessary for a number of reasons, including to address how 
Tapestry shares pages between requests.</p><p>For the most part, these 
transformations are both sensible and invisible. In a few limited cases, they 
comprise a marginally&#160;<a  class="external-link" 
href="http://www.joelonsoftware.com/printerFriendly/articles/LeakyAbstractions.html";
 rel="nofollow">leaky abstraction<
 /a>&#160;&#8211; for instance, the scope restrictions on instance variables 
described below &#8211; but the programming model in general supports a very 
high level of developer productivity.</p><p>Because transformation doesn't 
occur until <em>runtime</em>, the build stage of your application is not 
affected by the fact that you are creating a Tapestry application. Further, 
your classes are absolutely simple POJOs during unit testing.</p><h2 
id="ComponentClasses-LiveClassReloading">Live Class Reloading</h2><p>Main 
Article: <a  href="class-reloading.html">Class Reloading</a></p><p>Component 
classes are monitored for changes by the framework. <a  
href="class-reloading.html">Classes are reloaded when changed</a>. This allows 
you to build your application with a speed approaching that of a scripting 
environment, without sacrificing any of the power of the Java 
platform.</p><p>And it's fast! You won't even notice that this magic class 
reloading has occurred.</p><p>The net result: super p
 roductivity &#8212; change your class, see the change instantly. This is 
designed to be a blend of the best of scripting environments (such as Python or 
Ruby) with all the speed and power of Java backing it up.</p><p>However, class 
reloading <em>only</em> applies to component classes (pages, components and 
mixins) and, starting in 5.2, Tapestry IOC-based service implementations (with 
some restrictions). Other classes, such as service interfaces, entity/model 
classes, and other data objects, are loaded by the normal class loader and not 
subject to live class reloading.</p><h2 
id="ComponentClasses-InstanceVariables">Instance Variables</h2><p>Tapestry 
components may have instance variables (unlike Tapestry 4, where you had to use 
<em>abstract properties</em>).</p><p>Since release 5.3.2, instance variables 
may be protected, or package private (that is, no access modifier). Under 
specific circumstances they may even be public (public fields must either be 
final, or have the @<a  class="e
 xternal-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Retain.html";>Retain</a>&#160;annotation).</p><p><span
 style="line-height: 1.4285715;">Be aware that you will need to either provide 
getter and setter methods to access your classes' instance variables, or else 
annotate the fields with</span><span style="line-height: 
1.4285715;">&#160;@</span><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Property.html";
 style="line-height: 1.4285715;">Property</a>.</p><h2 
id="ComponentClasses-TransientInstanceVariables">Transient Instance 
Variables</h2><p>Unless an instance variable is decorated with an annotation, 
it will be a <em>transient</em> instance variable. This means that its value 
resets to its default value at the end of reach request (when the <a  
href="page-life-cycle.html">page is detached from the request</a>).</p><div 
class="confluence-information-macro confluence-information-macr
 o-note"><p class="title">About initialization</p><span class="aui-icon 
aui-icon-small aui-iconfont-warning 
confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Never initialize an instance field 
to a <em>mutable</em> object at the point of declaration. If this is done, the 
instance created from that initializer becomes the default value for that field 
and is reused inside the component on every request. This could cause state to 
inadvertently be shared between different sessions in an 
application.</p></div></div>
+</div></div><p>In this example, just like the first one, the component's only 
job is to write out a fixed message. The @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/BeginRender.html";>BeginRender</a>
 annotation is a type of <em><a  href="component-classes.html">render phase 
annotation</a></em>, a method annotation that instructs Tapestry when and under 
what circumstances to invoke methods of your class.</p><p>These methods are not 
necessarily public; they can have any access level you like (unlike in Tapestry 
4). By convention they usually have package-private access level (the 
default).</p><h2 id="ComponentClasses-ComponentPackages">Component 
Packages</h2><p>Component classes must exist within an appropriate package 
(this is necessary for runtime code transformation and class reloading to 
operate).</p><p>These packages exist under the application's root package, as 
follows:</p><ul><li>For pages, place classes in <em>root
 </em>.<strong>pages</strong>. Page names are mapped to classes within this 
package.</li><li>For mixins, place classes in 
<em>root</em>.<strong>mixins</strong>. Mixin types are mapped to classes within 
this package.</li><li>For other components, place classes in 
<em>root</em>.<strong>components</strong>. Component types are mapped to 
classes within this package.</li></ul><p>In addition, it is common for an 
application to have base classes, often <em>abstract</em> base classes, that 
should not be directly referenced. These should <em>not</em> go in the 
<strong>pages</strong>, <strong>components</strong> or <strong>mixins</strong> 
packages, because they then look like valid pages, components or mixins. 
Instead, use the <em>root</em>.<strong>base</strong> package to store such base 
classes.</p><div class="confluence-information-macro 
confluence-information-macro-warning"><span class="aui-icon aui-icon-small 
aui-iconfont-error confluence-information-macro-icon"></span><div class="conflue
 nce-information-macro-body"><p>Only component classes should go in any of 
these controlled packages; classes representing data, or interfaces, or 
anything that isn't precisely a component class, must go elsewhere. Any 
top-level class in any of the controlled packages will be transformed at 
runtime. The only exception is inner classes (anonymous or not), which are 
loaded by the same class loader as the component class loader, but not 
transformed as components.</p></div></div><h2 
id="ComponentClasses-Sub-Folders/Sub-Packages">Sub-Folders / 
Sub-Packages</h2><p>Classes do not have to go directly inside the package 
(pages, components, mixins, etc.). It is valid to create a sub-package to store 
some of the classes. The sub-package name becomes part of the page name or 
component type. Thus you might define a page component 
<code>com.example.myapp.pages.admin.CreateUser</code> and the logical page name 
(which often shows up inside URLs) will be 
<strong>admin/CreateUser</strong>.</p><p>Tapes
 try performs some simple optimizations of the logical page name (or component 
type, or mixin type). It checks to see if the package name is either a prefix 
or a suffix of the unqualified class name (case insensitively, of course) and 
removes the prefix or suffix if so. The net result is that a class name such as 
<code>com.example.myapp.pages.user.EditUser</code> will have a page name of 
<code>user/Edit</code> (instead of user<code>/EditUser</code>). The goal here 
is to provide shorter, more natural URLs.</p><h2 
id="ComponentClasses-IndexPages">Index Pages</h2><p>One special simplification 
exists for Index pages: if the logical page name is Index after removing the 
package name from the unqualified class name, it will map to the root of that 
folder. A class such as <code>com.example.myapp.pages.user.IndexUser</code> or 
<code>com.example.myapp.pages.user.UserIndex</code> will have a page name of 
<code>user/</code>.</p><p>In previous versions of Tapestry there was also the 
concept of a
  start page configured with the <code><a  
href="component-classes.html">tapestry.start-page-name</a></code> configuration 
symbol (defaults to "start"). If a page with a name as configured with that 
symbol exists at the root level, this page is used as the root URL. This has 
precedence over an existing Index page. If for example you have a page class 
<code>com.example.myapp.pages.Start</code> it will map to 
<code>/</code>.</p><div class="confluence-information-macro 
confluence-information-macro-warning"><span class="aui-icon aui-icon-small 
aui-iconfont-error confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Use of start-pages is discouraged 
and support for it will eventually be removed. Use an Index page 
instead.</p></div></div><h2 id="ComponentClasses-Pagesvs.Components">Pages vs. 
Components</h2><p>The distinction between pages and component is very, very 
small. The primary difference is the package name: 
<em>root</em>.<strong>pages</strong>
 .<em>PageName</em> for pages, and 
<em>root</em>.<strong>components</strong>.<em>ComponentType</em> for 
components. Conceptually, page components are simply the <em>root 
component</em> of a page's component tree.</p><p><em>For Tapestry 4 users: 
there was a much greater distinction in Tapestry 4 between pages and 
components, which showed up as separate interfaces and a hierarchy of abstract 
implementations to extend your classes from.</em></p><h2 
id="ComponentClasses-ClassTransformation">Class Transformation</h2><p>Tapestry 
uses your class as a starting point. It <em>transforms</em> your class at 
runtime. This is necessary for a number of reasons, including to address how 
Tapestry shares pages between requests.</p><p>For the most part, these 
transformations are both sensible and invisible. In a few limited cases, they 
comprise a marginally&#160;<a  class="external-link" 
href="http://www.joelonsoftware.com/printerFriendly/articles/LeakyAbstractions.html";
 rel="nofollow">leaky abstractio
 n</a>&#160;&#8211; for instance, the scope restrictions on instance variables 
described below &#8211; but the programming model in general supports a very 
high level of developer productivity.</p><p>Because transformation doesn't 
occur until <em>runtime</em>, the build stage of your application is not 
affected by the fact that you are creating a Tapestry application. Further, 
your classes are absolutely simple POJOs during unit testing.</p><h2 
id="ComponentClasses-LiveClassReloading">Live Class Reloading</h2><p>Main 
Article: <a  href="component-classes.html">Component 
Classes</a></p><p>Component classes are monitored for changes by the framework. 
<a  href="component-classes.html">Classes are reloaded when changed</a>. This 
allows you to build your application with a speed approaching that of a 
scripting environment, without sacrificing any of the power of the Java 
platform.</p><p>And it's fast! You won't even notice that this magic class 
reloading has occurred.</p><p>The net result:
  super productivity &#8212; change your class, see the change instantly. This 
is designed to be a blend of the best of scripting environments (such as Python 
or Ruby) with all the speed and power of Java backing it up.</p><p>However, 
class reloading <em>only</em> applies to component classes (pages, components 
and mixins) and, starting in 5.2, Tapestry IOC-based service implementations 
(with some restrictions). Other classes, such as service interfaces, 
entity/model classes, and other data objects, are loaded by the normal class 
loader and not subject to live class reloading.</p><h2 
id="ComponentClasses-InstanceVariables">Instance Variables</h2><p>Tapestry 
components may have instance variables (unlike Tapestry 4, where you had to use 
<em>abstract properties</em>).</p><p>Since release 5.3.2, instance variables 
may be protected, or package private (that is, no access modifier). Under 
specific circumstances they may even be public (public fields must either be 
final, or have the @<a  
 class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Retain.html";>Retain</a>&#160;annotation).</p><p><span>Be
 aware that you will need to either provide getter and setter methods to access 
your classes' instance variables, or else annotate the fields 
with</span><span>&#160;@</span><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Property.html";>Property</a>.</p><h2
 id="ComponentClasses-TransientInstanceVariables">Transient Instance 
Variables</h2><p>Unless an instance variable is decorated with an annotation, 
it will be a <em>transient</em> instance variable. This means that its value 
resets to its default value at the end of reach request (when the <a  
href="component-classes.html">page is detached from the request</a>).</p><div 
class="confluence-information-macro confluence-information-macro-note"><p 
class="title">About initialization</p><span class="aui-icon aui-icon-small 
 aui-iconfont-warning confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Never initialize an instance field 
to a <em>mutable</em> object at the point of declaration. If this is done, the 
instance created from that initializer becomes the default value for that field 
and is reused inside the component on every request. This could cause state to 
inadvertently be shared between different sessions in an 
application.</p></div></div>
 
 <div class="confluence-information-macro 
confluence-information-macro-warning"><p class="title">Deprecated since 
5.2</p><span class="aui-icon aui-icon-small aui-iconfont-error 
confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body">
 </div></div>
 <div class="error"><span class="error">Unknown macro: {div}</span> 
 <p>For Tapestry 5.1 and earlier, in the rare event that you have a variable 
that can keep its value between requests and you would like to defeat that 
reset logic, then you can add a @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Retain.html";>Retain</a>
 annotation to the field. You should take care that no client-specific data is 
stored into such a field, since on a later request the same page 
<em>instance</em> may be used for a different user. Likewise, on a later 
request for the <em>same</em> client, a <em>different</em> page instance may be 
used.</p>
-</div><p>Use <a  href="persistent-page-data.html">persistent fields</a> to 
hold client-specific information from one request to the next.</p><p>Further, 
final fields are (in fact) final, and will not be reset between 
requests.</p><h2 
id="ComponentClasses-Constructors">Constructors</h2><p>Tapestry will 
instantiate your class using the default, no arguments constructor. Other 
constructors will be ignored.</p><h2 
id="ComponentClasses-Injection">Injection</h2><p>Main Article: <a  
href="injection.html">Injection</a></p><p>Injection of dependencies occurs at 
the field level, via additional annotations. At runtime, fields that contain 
injections become read-only.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div><p>Use <a  href="component-classes.html">persistent fields</a> to hold 
client-specific information from one request to the next.</p><p>Further, final 
fields are (in fact) final, and will not be reset between requests.</p><h2 
id="ComponentClasses-Constructors">Constructors</h2><p>Tapestry will 
instantiate your class using the default, no arguments constructor. Other 
constructors will be ignored.</p><h2 
id="ComponentClasses-Injection">Injection</h2><p>Main Article: <a  
href="component-classes.html">Component Classes</a></p><p>Injection of 
dependencies occurs at the field level, via additional annotations. At runtime, 
fields that contain injections become read-only.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Inject // inject a resource
 private ComponentResources componentResources;
 
@@ -191,7 +191,7 @@ private Asset banner;
 @Inject // inject a service
 private AjaxResponseRenderer ajaxResponseRenderer;
 </pre>
-</div></div><h2 id="ComponentClasses-Parameters">Parameters</h2><p>Main 
Article: <a  href="component-parameters.html">Component 
Parameters</a></p><p>Component parameters are private fields of your component 
class annotated with @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Parameter.html";>Parameter</a>.
 Component parameters represent a two-way binding of a field of your component 
and a property or resource of its containing component or page.</p><h2 
id="ComponentClasses-PersistentFields">Persistent Fields</h2><p>Main Article: 
<a  href="persistent-page-data.html">Persistent Page Data</a></p><p>Most fields 
in component classes are automatically cleared at the end of each request. 
However, fields may be annotated so that they retain their value across 
requests, using the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html";>Persist</a>
 annotation.</p><h2 i
 d="ComponentClasses-Embedded_ComponentsEmbeddedComponents"><span 
class="confluence-anchor-link" 
id="ComponentClasses-Embedded_Components"></span>Embedded 
Components</h2><p>Components often contain other components. Components inside 
another component's template are called <em>embedded components</em>. The 
containing component's <a  href="component-templates.html">template</a> will 
contain special elements, in the Tapestry namespace, identifying where the the 
embedded components go.</p><p>You can define the type of component inside 
template, or you can create an instance variable for the component and use the 
@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html";>Component</a>
 annotation to define the component type and parameters.</p><p>Example:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
+</div></div><h2 id="ComponentClasses-Parameters">Parameters</h2><p>Main 
Article: <a  href="component-classes.html">Component 
Classes</a></p><p>Component parameters are private fields of your component 
class annotated with @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Parameter.html";>Parameter</a>.
 Component parameters represent a two-way binding of a field of your component 
and a property or resource of its containing component or page.</p><h2 
id="ComponentClasses-PersistentFields">Persistent Fields</h2><p>Main Article: 
<a  href="component-classes.html">Component Classes</a></p><p>Most fields in 
component classes are automatically cleared at the end of each request. 
However, fields may be annotated so that they retain their value across 
requests, using the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html";>Persist</a>
 annotation.</p><h2 id="Component
 Classes-Embedded_ComponentsEmbeddedComponents"><span 
class="confluence-anchor-link" 
id="ComponentClasses-Embedded_Components"></span>Embedded 
Components</h2><p>Components often contain other components. Components inside 
another component's template are called <em>embedded components</em>. The 
containing component's <a  href="component-classes.html">template</a> will 
contain special elements, in the Tapestry namespace, identifying where the the 
embedded components go.</p><p>You can define the type of component inside 
template, or you can create an instance variable for the component and use the 
@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html";>Component</a>
 annotation to define the component type and parameters.</p><p>Example:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package org.example.app.pages;
 
 import org.apache.tapestry5.annotations.Component;

Modified: websites/production/tapestry/content/component-events.html
==============================================================================
--- websites/production/tapestry/content/component-events.html (original)
+++ websites/production/tapestry/content/component-events.html Sat Feb  3 
16:21:22 2018
@@ -154,7 +154,7 @@
     &lt;/div&gt;
 &lt;/t:loop&gt;
 </pre>
-</div></div><p>Notice that Review.tml contains an ActionLink component in a 
loop. For each rendering within the loop, the ActionLink component creates a 
component event request URL, with the event type set to "action". In this case, 
each URL might look like:</p><p><code><span 
class="external-link">&#160;&#160;&#160; 
http://localhost:8080/review.edit/3</span></code></p><p>This URL identifies the 
<strong>page</strong> that contains the component ("review"), 
the&#160;<strong>Component id</strong> of the component within the page 
("edit"), and the <strong>context</strong> value ("3", the "id" property of the 
document). <em>Additional context values, if any, are appended to the 
path.</em> (The URL may also contain the <strong>event name</strong>, unless, 
as here, it is "action".)</p><p>There's no direct mapping from URL to a piece 
of code. Instead, when the user clicks on the link, the ActionLink component 
triggers events. And then Tapestry ensures that the correct bits of code (your 
eve
 nt handler method, see below) get invoked for those events.</p><p>This 
demonstrates a critical difference between Tapestry and a more traditional, 
action oriented framework. The URL doesn't say what happens when the link is 
clicked, it identifies <em>which component is responsible</em> when the link is 
clicked.</p><p>Often, a navigation request (originating with the user) will 
spawn a number of flow-of-control requests. For example, a form component may 
trigger an action event, which will then trigger notification events to 
announce when the form submission is about to be processed, and whether it was 
successful or not, and those event could be further handled by the page 
component.</p><h1 id="ComponentEvents-EventHandlerMethods">Event Handler 
Methods</h1><p>When a component event occurs, Tapestry invokes any event 
handler methods that you have identified for that event. You can identify your 
event handler methods via a naming convention (see Method Naming Convention 
below), or via 
 the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/OnEvent.html";>OnEvent</a>
 annotation.</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
+</div></div><p>Notice that Review.tml contains an ActionLink component in a 
loop. For each rendering within the loop, the ActionLink component creates a 
component event request URL, with the event type set to "action". In this case, 
each URL might look like:</p><p><code><span 
class="external-link">&#160;&#160;&#160; <a  class="external-link" 
href="http://localhost:8080/review.edit/3"; 
rel="nofollow">http://localhost:8080/review.edit/3</a></span></code></p><p>This 
URL identifies the <strong>page</strong> that contains the component 
("review"), the&#160;<strong>Component id</strong> of the component within the 
page ("edit"), and the <strong>context</strong> value ("3", the "id" property 
of the document). <em>Additional context values, if any, are appended to the 
path.</em> (The URL may also contain the <strong>event name</strong>, unless, 
as here, it is "action".)</p><p>There's no direct mapping from URL to a piece 
of code. Instead, when the user clicks on the link, the ActionLink comp
 onent triggers events. And then Tapestry ensures that the correct bits of code 
(your event handler method, see below) get invoked for those events.</p><p>This 
demonstrates a critical difference between Tapestry and a more traditional, 
action oriented framework. The URL doesn't say what happens when the link is 
clicked, it identifies <em>which component is responsible</em> when the link is 
clicked.</p><p>Often, a navigation request (originating with the user) will 
spawn a number of flow-of-control requests. For example, a form component may 
trigger an action event, which will then trigger notification events to 
announce when the form submission is about to be processed, and whether it was 
successful or not, and those event could be further handled by the page 
component.</p><h1 id="ComponentEvents-EventHandlerMethods">Event Handler 
Methods</h1><p>When a component event occurs, Tapestry invokes any event 
handler methods that you have identified for that event. You can identify your 
eve
 nt handler methods via a naming convention (see Method Naming Convention 
below), or via the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/OnEvent.html";>OnEvent</a>
 annotation.</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@OnEvent(component="edit")
 void editDocument(int docId)
 {
@@ -187,7 +187,7 @@ void editDocument(int docId)
     // do something with the document here
 }
 </pre>
-</div></div><div class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Many people prefer the naming 
convention approach, reserving the annotation just for situations that don't 
otherwise fit.</p></div></div><h2 
id="ComponentEvents-MethodReturnValues">Method Return Values</h2><p>Main 
Article: <a  href="page-navigation.html">Page Navigation</a></p><p>For page 
navigation events (originating in components such as EventLink, ActionLink and 
Form), the value returned from an event handler method determines how Tapestry 
will render a response.</p><ul><li><strong>Null</strong>: For no value, or 
null, the current page (the page containing the component) will render the 
response.</li><li><strong>Page</strong>: For the name of a page, or a page 
class or page instance, a render request URL will be constructed and sent to 
the c
 lient as a redirect to that page.</li><li><strong>URL</strong>: For a 
java.net.URL, a redirect will be sent to the client. (In Tapestry 5.3.x and 
earlier, this only works for non-Ajax requests.)</li><li><strong>Zone 
body</strong>: In the case of an Ajax request to update a zone, the component 
event handler will return the new zone body, typically via an injected 
component or block.</li><li><strong>HttpError</strong>: For an <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpError.html";>HttpError</a>,
 an error response is sent to the client.</li><li><strong>Link</strong>: For a 
<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Link.html";>Link</a>,
 a redirect is sent to the client.</li><li><strong>Stream</strong>: For a <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/StreamResponse.html";>StreamResponse</a>,
 a stream of data is sent to 
 the client</li><li><strong>boolean:</strong> <em>true</em> prevents the event 
from bubbling up further; <em>false</em> lets it bubble up. See Event Bubbling, 
below.</li></ul><p>See <a  href="page-navigation.html">Page Navigation</a> for 
more details.</p><h2 id="ComponentEvents-MultipleMethodMatches">Multiple Method 
Matches</h2><p>In some cases, there may be multiple event handler methods 
matching a single event. In that case, Tapestry invokes them in the following 
order:</p><ul><li>Base class methods before sub-class methods.</li><li>Matching 
methods within a class in alphabetical order.</li><li>For a single method name 
with multiple overrides, by number of parameters, descending.</li></ul><p>Of 
course, ordinarily would you <em>not</em> want to create more than one method 
to handle an event.</p><p>When a sub-class overrides an event handler method of 
a base class, the event handler method is only invoked once, along with any 
other base class methods. The subclass can change the <em>
 implementation</em> of the base class method via an override, but can't change 
the <em>timing</em> of when that method is invoked. See <a  
class="external-link" 
href="https://issues.apache.org/jira/browse/TAP5-51";>issue TAP5-51</a>.</p><h2 
id="ComponentEvents-EventContext">Event Context</h2><p>The context values (the 
context parameter to the EventLink or ActionLink component) can be any object. 
However, only a simple conversion to string occurs. (This is in contrast to 
Tapestry 4, which had an elaborate type mechanism with the odd name 
"DataSqueezer".)</p><p>Again, whatever your value is (string, number, date), it 
is converted into a plain string. This results in a more readable URL.</p><p>If 
you have multiple context values (by binding a list or array of objects to the 
<em>context</em> parameter of the EventLink or ActionLink), then each one, in 
order, will be added to the URL.</p><p>When an event handler method is invoked, 
the strings are converted back into values, or even object
 s. A <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ValueEncoder.html";>ValueEncoder</a>
 is used to convert between client-side strings and server-side objects. The <a 
 class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ValueEncoderSource.html";>ValueEncoderSource</a>
 service provides the necessary value encoders.</p><p>As shown in the example 
above, most of the parameters passed to the event handler method are derived 
from the values provided in the event context. Each successive method parameter 
matches against a value provided in the event context (the context parameter of 
the ActionLink component; though many components have a similar context 
parameter).</p><p>In many cases it is helpful to have direct access to the 
context (for example, to adapt to cases where there are a variable number of 
context values). The context values may be passed to an event handler method as 
parameter of 
 the following types:</p><ul><li><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/EventContext.html";>EventContext</a></li><li>Object[]</li><li>List&lt;Object&gt;</li></ul><p>The
 latter two should be avoided, they may be removed in a future release. In all 
of these cases, the context parameter acts as a freebie; it doesn't match 
against a context value as it represents <em>all</em> context values.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
+</div></div><div class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Many people prefer the naming 
convention approach, reserving the annotation just for situations that don't 
otherwise fit.</p></div></div><h2 
id="ComponentEvents-MethodReturnValues">Method Return Values</h2><p>Main 
Article: <a  href="component-events.html">Component Events</a></p><p>For page 
navigation events (originating in components such as EventLink, ActionLink and 
Form), the value returned from an event handler method determines how Tapestry 
will render a response.</p><ul><li><strong>Null</strong>: For no value, or 
null, the current page (the page containing the component) will render the 
response.</li><li><strong>Page</strong>: For the name of a page, or a page 
class or page instance, a render request URL will be constructed and sent to the
  client as a redirect to that page.</li><li><strong>URL</strong>: For a <a  
class="external-link" href="http://java.net"; rel="nofollow">java.net</a>.URL, a 
redirect will be sent to the client. (In Tapestry 5.3.x and earlier, this only 
works for non-Ajax requests.)</li><li><strong>Zone body</strong>: In the case 
of an Ajax request to update a zone, the component event handler will return 
the new zone body, typically via an injected component or 
block.</li><li><strong>HttpError</strong>: For an <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpError.html";>HttpError</a>,
 an error response is sent to the client.</li><li><strong>Link</strong>: For a 
<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Link.html";>Link</a>,
 a redirect is sent to the client.</li><li><strong>Stream</strong>: For a <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5
 /StreamResponse.html">StreamResponse</a>, a stream of data is sent to the 
client</li><li><strong>boolean:</strong> <em>true</em> prevents the event from 
bubbling up further; <em>false</em> lets it bubble up. See Event Bubbling, 
below.</li></ul><p>See <a  href="component-events.html">Component Events</a> 
for more details.</p><h2 id="ComponentEvents-MultipleMethodMatches">Multiple 
Method Matches</h2><p>In some cases, there may be multiple event handler 
methods matching a single event. In that case, Tapestry invokes them in the 
following order:</p><ul><li>Base class methods before sub-class 
methods.</li><li>Matching methods within a class in alphabetical 
order.</li><li>For a single method name with multiple overrides, by number of 
parameters, descending.</li></ul><p>Of course, ordinarily would you 
<em>not</em> want to create more than one method to handle an event.</p><p>When 
a sub-class overrides an event handler method of a base class, the event 
handler method is only invoked once, a
 long with any other base class methods. The subclass can change the 
<em>implementation</em> of the base class method via an override, but can't 
change the <em>timing</em> of when that method is invoked. See <a  
class="external-link" 
href="https://issues.apache.org/jira/browse/TAP5-51";>issue TAP5-51</a>.</p><h2 
id="ComponentEvents-EventContext">Event Context</h2><p>The context values (the 
context parameter to the EventLink or ActionLink component) can be any object. 
However, only a simple conversion to string occurs. (This is in contrast to 
Tapestry 4, which had an elaborate type mechanism with the odd name 
"DataSqueezer".)</p><p>Again, whatever your value is (string, number, date), it 
is converted into a plain string. This results in a more readable URL.</p><p>If 
you have multiple context values (by binding a list or array of objects to the 
<em>context</em> parameter of the EventLink or ActionLink), then each one, in 
order, will be added to the URL.</p><p>When an event handler metho
 d is invoked, the strings are converted back into values, or even objects. A 
<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ValueEncoder.html";>ValueEncoder</a>
 is used to convert between client-side strings and server-side objects. The <a 
 class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ValueEncoderSource.html";>ValueEncoderSource</a>
 service provides the necessary value encoders.</p><p>As shown in the example 
above, most of the parameters passed to the event handler method are derived 
from the values provided in the event context. Each successive method parameter 
matches against a value provided in the event context (the context parameter of 
the ActionLink component; though many components have a similar context 
parameter).</p><p>In many cases it is helpful to have direct access to the 
context (for example, to adapt to cases where there are a variable number of 
context values). The 
 context values may be passed to an event handler method as parameter of the 
following types:</p><ul><li><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/EventContext.html";>EventContext</a></li><li>Object[]</li><li>List&lt;Object&gt;</li></ul><p>The
 latter two should be avoided, they may be removed in a future release. In all 
of these cases, the context parameter acts as a freebie; it doesn't match 
against a context value as it represents <em>all</em> context values.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">Object onActionFromEdit(EventContext context)
 {
     if (context.getCount() &gt; 0) {
@@ -198,7 +198,7 @@ void editDocument(int docId)
         return null;
     }
 }</pre>
-</div></div><h2 id="ComponentEvents-AccessingRequestQueryParameters">Accessing 
Request Query Parameters</h2><p>A parameter may be annotated with the 
@RequestParameter annotation; this allows query parameters 
(?name1=value1&amp;name2=value2, etc) to be extracted from the request, 
converted to the correct type, and passed to the method. Again, this doesn't 
count against the event context values.</p><p>See the example in the <a  
href="link-components-faq.html">Link Components FAQ</a>.</p><h2 
id="ComponentEvents-MethodMatching">Method Matching</h2><p>An event handler 
method will only be invoked <em>if the context contains at least as many values 
as the method has parameters</em>. Methods with too many parameters will be 
silently skipped.</p><p>Tapestry will silently skip over a method if there are 
insufficient values in the context to satisfy the number of parameters 
requested.</p><p>EventContext parameters, and parameters annotated with 
@RequestParameter, do not count against this limi
 t.</p><h2 id="ComponentEvents-MethodOrdering">Method Ordering</h2><p>When 
multiple methods match within the same class, Tapestry will invoke them in 
ascending alphabetical order. When there are multiple overrides of the same 
method name, Tapestry invokes them in descending order by number of parameters. 
In general, these situations don't happen ... in most cases, only a single 
method is required to handle a specific event form a specific 
component.</p><p>An event handler method may return the value <code>true</code> 
to indicate that the event has been handled; this immediately stops the search 
for additional methods in the same class (or in base classes) or in containing 
components.</p><h1 id="ComponentEvents-EventBubbling">Event Bubbling</h1><p>The 
event will bubble up the component hierarchy, first to the containing 
component, then <em>that</em> component's containing component or page, and so 
on, until it is <em>aborted</em> by an event handler method returning 
<em>true</em> or a
  non-null value.</p><p>Returning a boolean value from an event handler method 
is special. Returning <em>true</em> will abort the event with no result; use 
this when the event is fully handled without a return value and no further 
event handlers (in the same component, or in containing components) should be 
invoked.</p><p>Returning <em>false</em> is the same as returning null; event 
processing will continue to look for more event handlers, in the same component 
or its parent.</p><p>When an event bubbles up from a component to its 
container, the origin of the event is changed to be the component. For example, 
a Form component inside a BeanEditForm component may trigger a success event. 
The page containing the BeanEditForm may listen for that event, but it will be 
from the BeanEditForm component (which makes sense, because the id of the Form 
inside the BeanEditForm is part of the BeanEditForm's implementation, not its 
public interface).</p><p>If you want to handle events that have bubb
 led up from nested component, you'll soon find that you don't have easy access 
to the component ID of the firing component. In practical terms this means that 
you'll want to trigger custom events for the events triggered by those nested 
components (see Triggering Events, below), and use that custom event name in 
your event handler method.</p><h1 
id="ComponentEvents-EventMethodExceptions">Event Method Exceptions</h1><p>Event 
methods are allowed to throw any exception (not just runtime exceptions). If an 
event method does throw an exception, Tapestry will catch the thrown exception 
and ultimately display the exception report page.</p><p>In other words, there's 
no need to do this:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
+</div></div><h2 id="ComponentEvents-AccessingRequestQueryParameters">Accessing 
Request Query Parameters</h2><p>A parameter may be annotated with the 
@RequestParameter annotation; this allows query parameters 
(?name1=value1&amp;name2=value2, etc) to be extracted from the request, 
converted to the correct type, and passed to the method. Again, this doesn't 
count against the event context values.</p><p>See the example in the <a  
href="component-events.html">Component Events</a>.</p><h2 
id="ComponentEvents-MethodMatching">Method Matching</h2><p>An event handler 
method will only be invoked <em>if the context contains at least as many values 
as the method has parameters</em>. Methods with too many parameters will be 
silently skipped.</p><p>Tapestry will silently skip over a method if there are 
insufficient values in the context to satisfy the number of parameters 
requested.</p><p>EventContext parameters, and parameters annotated with 
@RequestParameter, do not count against this limit.</p>
 <h2 id="ComponentEvents-MethodOrdering">Method Ordering</h2><p>When multiple 
methods match within the same class, Tapestry will invoke them in ascending 
alphabetical order. When there are multiple overrides of the same method name, 
Tapestry invokes them in descending order by number of parameters. In general, 
these situations don't happen ... in most cases, only a single method is 
required to handle a specific event form a specific component.</p><p>An event 
handler method may return the value <code>true</code> to indicate that the 
event has been handled; this immediately stops the search for additional 
methods in the same class (or in base classes) or in containing 
components.</p><h1 id="ComponentEvents-EventBubbling">Event Bubbling</h1><p>The 
event will bubble up the component hierarchy, first to the containing 
component, then <em>that</em> component's containing component or page, and so 
on, until it is <em>aborted</em> by an event handler method returning 
<em>true</em> or a non-n
 ull value.</p><p>Returning a boolean value from an event handler method is 
special. Returning <em>true</em> will abort the event with no result; use this 
when the event is fully handled without a return value and no further event 
handlers (in the same component, or in containing components) should be 
invoked.</p><p>Returning <em>false</em> is the same as returning null; event 
processing will continue to look for more event handlers, in the same component 
or its parent.</p><p>When an event bubbles up from a component to its 
container, the origin of the event is changed to be the component. For example, 
a Form component inside a BeanEditForm component may trigger a success event. 
The page containing the BeanEditForm may listen for that event, but it will be 
from the BeanEditForm component (which makes sense, because the id of the Form 
inside the BeanEditForm is part of the BeanEditForm's implementation, not its 
public interface).</p><p>If you want to handle events that have bubbled up
  from nested component, you'll soon find that you don't have easy access to 
the component ID of the firing component. In practical terms this means that 
you'll want to trigger custom events for the events triggered by those nested 
components (see Triggering Events, below), and use that custom event name in 
your event handler method.</p><h1 
id="ComponentEvents-EventMethodExceptions">Event Method Exceptions</h1><p>Event 
methods are allowed to throw any exception (not just runtime exceptions). If an 
event method does throw an exception, Tapestry will catch the thrown exception 
and ultimately display the exception report page.</p><p>In other words, there's 
no need to do this:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  void onActionFromRunQuery()
   {
     try
@@ -227,7 +227,7 @@ void editDocument(int docId)
     return this;
   }
 </pre>
-</div></div><p>The return value of the exception event handler 
<em>replaces</em> the return value of original event handler method. For the 
typical case (an exception thrown by an "activate" or "action" event), this 
will be a <a  href="page-navigation.html">navigational response</a> such as a 
page instance or page name.</p><p>This can be handy for handling cases where 
the data in the URL is incorrectly formatted.</p><p>In the above example, the 
navigational response is the page itself.</p><p>If there is no exception event 
handler, or the exception event handler returns null (or is void), then the 
exception will be passed to the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestExceptionHandler.html";>RequestExceptionHandler</a>
 service, which (in the default configuration) will render the exception 
page.</p><h1 id="ComponentEvents-TriggeringEvents">Triggering 
Events</h1><p></p><div class="navmenu" style="float:right; backg
 round:#eee; margin:3px; padding:0 1em">
+</div></div><p>The return value of the exception event handler 
<em>replaces</em> the return value of original event handler method. For the 
typical case (an exception thrown by an "activate" or "action" event), this 
will be a <a  href="component-events.html">navigational response</a> such as a 
page instance or page name.</p><p>This can be handy for handling cases where 
the data in the URL is incorrectly formatted.</p><p>In the above example, the 
navigational response is the page itself.</p><p>If there is no exception event 
handler, or the exception event handler returns null (or is void), then the 
exception will be passed to the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestExceptionHandler.html";>RequestExceptionHandler</a>
 service, which (in the default configuration) will render the exception 
page.</p><h1 id="ComponentEvents-TriggeringEvents">Triggering 
Events</h1><p></p><div class="navmenu" style="float:right; back
 ground:#eee; margin:3px; padding:0 1em">
 <p>    <strong>JumpStart Demo:</strong><br clear="none">
     <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart/together/ajaxcomponentscrud/persons";
 rel="nofollow">AJAX Components CRUD</a></p></div>If you want your own 
component to trigger events, just call the <a  rel="nofollow">triggerEvent</a> 
method of <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentResources.html";>ComponentResources</a>
 from within the component class.<p>For example, the following triggers an 
"updateAll" event. A containing component can then respond to it, if desired, 
with an "onUpdateAll()" method in its own component class.</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>Your component class 
(partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Inject

Modified: websites/production/tapestry/content/component-mixins.html
==============================================================================
--- websites/production/tapestry/content/component-mixins.html (original)
+++ websites/production/tapestry/content/component-mixins.html Sat Feb  3 
16:21:22 2018
@@ -101,7 +101,7 @@
                 <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a  href="legacy-javascript.html">Legacy JavaScript</a>
+                        <a  href="component-templates.html">Component 
Templates</a>
                 
                         
                     </div>
@@ -110,7 +110,7 @@
                 <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a  href="component-templates.html">Component 
Templates</a>
+                        <a  href="legacy-javascript.html">Legacy JavaScript</a>
                 
                         
                     </div>
@@ -136,7 +136,7 @@
 </div>
 
 
-<p>You can think of a mixin as a kind of mashup for a component; it combines 
the new behavior of the mixin with the existing behavior of the component, and 
bundles it all in one place. Mixins may be used to add specialized validation 
to user input fields, dynamically modify the HTML output of a component, or to 
add Ajax effects and behaviors of all sorts to components.</p><p>Tapestry comes 
with several mixins, such as the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/mixins/Autocomplete.html";>Autocomplete
 mixin</a> which adds autocomplete behavior to an ordinary TextField Component. 
In addition, you can easily create your own.</p><h2 
id="ComponentMixins-MixinClasses">Mixin Classes</h2><p>Mixin classes are stored 
in the <code>mixins</code> sub-package of your application, below the 
application (or library) root package. This parallels where your component and 
page classes are stored.</p><p>Other than that, mixin classes are th
 e same as any other component class.</p><h2 
id="ComponentMixins-MixinLimitations">Mixin Limitations</h2><p>Currently, 
mixins are allowed to do anything a component can do, including having 
parameters and render phase methods.</p><p>Mixins may not have a template. They 
integrate with the component strictly in terms of invoking render phase 
methods.</p><p>Mixins may have persistent fields, but currently, this is not 
implemented perfectly (there is a potential for a name clash between a mixin 
and the component or another mixin). Use persistent fields with mixins with 
care ... or better yet, delegate persistence to the container using 
parameters.</p><p>Mixins may not, themselves, have mixins.</p><h2 
id="ComponentMixins-UsingMixins">Using Mixins</h2><p>Mixins are used in two 
different scenarios: <em>Instance mixins</em> and <em>Implementation 
mixins</em>.</p><h3 id="ComponentMixins-InstanceMixins">Instance 
Mixins</h3><p>An instance mixin is a mixin applied to a specific 
<em>instance</em>
  of a component. This can be done in the <a  
href="component-templates.html">component template</a> with the 
<code>mixins</code> attribute of the component tag. This is a comma-separated 
list of mixin names.</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
+<p>You can think of a mixin as a kind of mashup for a component; it combines 
the new behavior of the mixin with the existing behavior of the component, and 
bundles it all in one place. Mixins may be used to add specialized validation 
to user input fields, dynamically modify the HTML output of a component, or to 
add Ajax effects and behaviors of all sorts to components.</p><p>Tapestry comes 
with several mixins, such as the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/mixins/Autocomplete.html";>Autocomplete
 mixin</a> which adds autocomplete behavior to an ordinary TextField Component. 
In addition, you can easily create your own.</p><h2 
id="ComponentMixins-MixinClasses">Mixin Classes</h2><p>Mixin classes are stored 
in the <code>mixins</code> sub-package of your application, below the 
application (or library) root package. This parallels where your component and 
page classes are stored.</p><p>Other than that, mixin classes are th
 e same as any other component class.</p><h2 
id="ComponentMixins-MixinLimitations">Mixin Limitations</h2><p>Currently, 
mixins are allowed to do anything a component can do, including having 
parameters and render phase methods.</p><p>Mixins may not have a template. They 
integrate with the component strictly in terms of invoking render phase 
methods.</p><p>Mixins may have persistent fields, but currently, this is not 
implemented perfectly (there is a potential for a name clash between a mixin 
and the component or another mixin). Use persistent fields with mixins with 
care ... or better yet, delegate persistence to the container using 
parameters.</p><p>Mixins may not, themselves, have mixins.</p><h2 
id="ComponentMixins-UsingMixins">Using Mixins</h2><p>Mixins are used in two 
different scenarios: <em>Instance mixins</em> and <em>Implementation 
mixins</em>.</p><h3 id="ComponentMixins-InstanceMixins">Instance 
Mixins</h3><p>An instance mixin is a mixin applied to a specific 
<em>instance</em>
  of a component. This can be done in the <a  
href="component-mixins.html">component template</a> with the 
<code>mixins</code> attribute of the component tag. This is a comma-separated 
list of mixin names.</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">&lt;t:textfield t:id="accountName" 
t:mixins="Autocomplete,DefaultFromCookie" /&gt;
 </pre>
 </div></div><p>Alternately, when the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html";>Component</a>
 annotation is used to define the component type, you may specify the mixins in 
two ways:</p><ul><li>The @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Mixins.html";>Mixins</a>
 annotation allows a list of mixin names to be specified.</li><li>The @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/MixinClasses.html";>MixinClasses</a>
 annotation allows a set of mixin classes to be specified 
directly.</li></ul><p>The former is often less verbose, and allows core mixins 
to be overridden with application-specific mixins. The later format is more 
specific and more refactor-safe (renaming a mixin class will rename the entry 
in the MixinClasses annotation as well).</p><p>Example:</p><div class="code pane
 l pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
@@ -217,7 +217,7 @@ private TextField userId;
   ...
 }
 </pre>
-</div></div><p>"MyMixin" can be used on a textfield (principalObject is bound 
to "value"), on BeanEditor or BeanDisplay (principalObject is bound to 
"object"), or on Grid or Loop (principalObject is bound to "source").</p><h2 
id="ComponentMixins-RenderPhaseOrdering">Render Phase Ordering</h2><p>All 
mixins for a component execute their render phase methods <em>before</em> the 
component's render phase methods for most phases. However, in the later phases 
(AfterRender, CleanupRender) the order of executing is 
reversed.</p><p>Exception: A mixins whose class is annotated with @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/MixinAfter.html";>MixinAfter</a>
 is ordered <em>after</em> the component, not before.</p><p>Withing a given 
phase and class (@MixinAfter vs. mixin before), mixin ordering is determined by 
the ordering constraints specified in the mixin definitions. The constraint 
definitions follow the same conventions as <a  
 href="ordering-by-constraints.html">ordered service configurations</a>. How 
you specify the constraints depends on how the mixin is specified.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 1px;"><b>As an Implementation 
Mixin</b></div><div class="codeContent panelContent pdl">
+</div></div><p>"MyMixin" can be used on a textfield (principalObject is bound 
to "value"), on BeanEditor or BeanDisplay (principalObject is bound to 
"object"), or on Grid or Loop (principalObject is bound to "source").</p><h2 
id="ComponentMixins-RenderPhaseOrdering">Render Phase Ordering</h2><p>All 
mixins for a component execute their render phase methods <em>before</em> the 
component's render phase methods for most phases. However, in the later phases 
(AfterRender, CleanupRender) the order of executing is 
reversed.</p><p>Exception: A mixins whose class is annotated with @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/MixinAfter.html";>MixinAfter</a>
 is ordered <em>after</em> the component, not before.</p><p>Withing a given 
phase and class (@MixinAfter vs. mixin before), mixin ordering is determined by 
the ordering constraints specified in the mixin definitions. The constraint 
definitions follow the same conventions as <a  
 href="component-mixins.html">ordered service configurations</a>. How you 
specify the constraints depends on how the mixin is specified.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 1px;"><b>As an Implementation 
Mixin</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  
@Mixin("Autocomplete",order={"before:DiscardBody","after:RenderDisabled"}
   private TextField userId;
 </pre>


Reply via email to