Modified: websites/production/tapestry/content/page-life-cycle.html
==============================================================================
--- websites/production/tapestry/content/page-life-cycle.html (original)
+++ websites/production/tapestry/content/page-life-cycle.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">Page Life Cycle</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">Page Life Cycle</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -54,43 +67,76 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><div class="aui-label" 
style="float:right" title="Related Articles"><h3>Related Articles</h3><ul 
class="content-by-label"><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="page-navigation.html">Page Navigation</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="page-life-cycle.html">Page Life Cycle</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="component-rendering.html">Component Rendering</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="component-events.html">Component Events</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="component-events-faq.html">Component Events FAQ</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="request-processing.html">Request Processing</a> 
-  </div> </li></ul></div><div class="confluence-information-macro 
confluence-information-macro-note"><span class="aui-icon aui-icon-small 
aui-iconfont-warning confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>This is an advanced topic. Most 
users won't ever need to know anything about the page life 
cycle.</p></div></div><p>&#160;</p><p>In Tapestry, you are free to develop your 
presentation objects, page and components classes, as ordinary objects, 
complete with instance variables and so forth.</p><p>This is somewhat 
revolutionary in terms of web development in Java. By comparison, using 
traditional servlets, or Struts, your presentation objects (Servlets, or Struts 
Actions, or the equivalent in other frameworks) are <em>stateless 
singletons</em>. That is, a <em>single</em> instance is created, and all 
incoming requests are threaded through that single instance. Because multiple 
requests are handled by many different threads, this means that 
 the singleton's instance variables are useless ... any value written into an 
instance variable would immediately be overwritten by a different thread. Thus, 
it is necessary to use the Servlet API's HttpServletRequest object to store 
per-request data, and the HttpSession object to store data between 
requests.</p><p>Tapestry takes a very different approach.</p><p>In Tapestry, 
each page is a singleton, but with a <em>per thread</em> map of field names 
&amp; values that Tapestry invisibly manages for you.</p><p>With this approach, 
all the difficult, ugly issues related to multi-threading go by the wayside. 
Instead, familiar, simple coding practices (using ordinary methods and fields) 
can be used.</p><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>Tapestry 5.0 and 5.1 used page 
pooling, rather than a singleto
 n page with a per-thread map, to achieve the same 
effect.</p></div></div><p>The page life cycle is quite simple:</p><ol><li>When 
first needed, a page is loaded. Loading a page involves instantiating the 
components of the page and connecting them together.</li><li>Once a page is 
loaded, it is <em>attached</em> to the current request. Remember that there 
will be many threads, each handling its own request to the same 
page.</li><li>At the end of a request, after a response has been sent to the 
client, the page is <em>detached</em> from the request. This is a chance to 
perform any cleanup needed for the page.</li></ol><h2 
id="PageLifeCycle-PageLifeCycleMethods">Page Life Cycle Methods</h2><p>There 
are rare occasions where it is useful for a component to perform some 
operations, usually some kind of initialization or caching, based on the life 
cycle of the page.</p><p>As with <a  href="component-rendering.html">component 
rendering</a>, you have the ability to make your components "aware"
  of these events by telling Tapestry what methods to invoke for 
each.</p><p>Page life cycle methods should take no parameters and return 
void.</p><p>You have the choice of attaching an annotation to a method, or 
simply using the method naming conventions:</p><div class="table-wrap"><table 
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Annotation</p></th><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Method Name</p></th><th colspan="1" rowspan="1" 
class="confluenceTh"><p>When Called</p></th></tr><tr><td colspan="1" 
rowspan="1" class="confluenceTd"><p>@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/PageLoaded.html";>PageLoaded</a></p></td><td
 colspan="1" rowspan="1" class="confluenceTd"><p>pageLoaded()</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>After the page is fully 
loaded</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>@<a 
 class="external-l
 ink" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/PageAttached.html";>PageAttached</a></p></td><td
 colspan="1" rowspan="1" class="confluenceTd"><p>pageAttached()</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>After the page is attached to 
the request.</p></td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd">@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/PageReset.html";>PageReset</a></td><td
 colspan="1" rowspan="1" class="confluenceTd">pageReset()</td><td colspan="1" 
rowspan="1" class="confluenceTd">After the page is <em>activated</em>, except 
when requesting the same page</td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd"><p>@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/PageDetached.html";>PageDetached</a></p></td><td
 colspan="1" rowspan="1" class="confluenceTd"><p>pageDetached()</p></td><td c
 olspan="1" rowspan="1" class="confluenceTd"><p>AFter the page is detached from 
the request.</p></td></tr></tbody></table></div><p>The @PageReset life cycle 
(only for Tapestry 5.2 and later) is invoked on a page render request when the 
page is linked to from some <em>other</em> page of the application (but 
<em>not</em> on a link to the same page), or upon a reload of the page in the 
browser. This is to allow the page to reset its state, if any, when a user 
returns to the page from some other part of the application.</p><h2 
id="PageLifeCycle-ComparisontoJavaServerPages">Comparison to JavaServer 
Pages</h2><p>JSPs also act as singletons. However, the individual JSP tags are 
pooled.</p><p>This is one of the areas where Tapestry can significantly 
outperform JSPs. Much of the code inside a compiled JSP class concerns getting 
tags from a tag pool, configuring the properties of the tag instance, using the 
tag instance, then cleaning up the tag instance and putting it back in the 
pool.</p><p>
 The operations Tapestry does once per request are instead executed dozens or 
potentially hundreds of times (depending the complexity of the page, and if any 
nested loops occur).</p><p>Pooling JSP tags is simply the wrong 
granularity.</p><p>Tapestry can also take advantage of its more coarse grained 
caching to optimize how data moves, via parameters, between components. This 
means that Tapestry pages will actually speed up after they render the first 
time.</p><h2 id="PageLifeCycle-PagePoolConfiguration">Page Pool 
Configuration</h2><div class="confluence-information-macro 
confluence-information-macro-note"><span class="aui-icon aui-icon-small 
aui-iconfont-warning confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>This related to versions of 
Tapestry prior to 5.2. Modern Tapestry uses an alternate approach that allows a 
single page instance to be shared across many request processing 
threads.</p></div></div><p>In Tapestry 5.0 and 5.1, a page poo
 l is used to store page instances. The pool is "keyed" on the name of the page 
(such as "start") and the <em>locale</em> for the page (such as "en" or 
"fr").</p><p>Within each key, Tapestry tracks the number of page instances that 
have been created, as well as the number that are in use (currently attached to 
a request).</p><p>When a page is first accessed in a request, it is taken from 
the pool. Tapestry has some <a  href="configuration.html">configuration 
values</a> that control the details of how and when page instances are 
created.</p><ul><li>If a free page instance is available, the page is marked in 
use and attached to the request.</li><li>If there are fewer page instances than 
the <em>soft limit</em>, then a new page instance is simply created and 
attached to the request.</li><li>If the soft limit has been reached, Tapestry 
will wait for a short period of time for a page instance to become available 
before creating a new page instance.</li><li>If the hard limit has been reach
 ed, Tapestry will throw an exception rather than create a new page 
instance.</li><li>Otherwise, Tapestry will create a new page instance.<br 
clear="none"> Thus a busy application will initially create pages up-to the 
soft limit (which defaults to five page instances). If the application 
continues to be pounded with requests, it will slow its request processing, 
using the soft wait time in an attempt to reuse an existing page 
instance.</li></ul><p>A truly busy application will continue to create new page 
instances as needed until the hard limit is reached.</p><p>Remember that all 
these configuration values are per key: the combination of page name and 
locale. Thus even with a hard limit of 20, you may eventually find that 
Tapestry has created 20 start page instances for locale "en" <em>and</em> 20 
start page instances for locale "fr" (if your application is configured to 
support both English and French). Likewise, you may have 20 instances for the 
start page, and 20 instances for the
  newaccount page.</p><p>Tapestry periodically checks its cache for page 
instances that have not been used recently (within a configurable window). 
Unused page instances are release to the garbage collector.</p><p>The end 
result is that you have quite a degree of tuning control over the process. If 
memory is a limitation and throughput can be sacrificed, try lowering the soft 
and hard limit and increasing the soft wait.</p><p>If performance is absolute 
and you have lots of memory, then increase the soft and hard limit and reduce 
the soft wait. This encourages Tapestry to create more page instances and not 
wait as long to re-use existing instances.</p></div>
+                <div id="ConfluenceContent"><div class="aui-label" 
style="float:right" title="Related Articles">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="page-navigation.html">Page Navigation</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="page-life-cycle.html">Page Life Cycle</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-rendering.html">Component 
Rendering</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-events.html">Component Events</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-events-faq.html">Component Events 
FAQ</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="request-processing.html">Request 
Processing</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div>
+
+
+<div class="confluence-information-macro 
confluence-information-macro-note"><span class="aui-icon aui-icon-small 
aui-iconfont-warning confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>This is an advanced topic. Most 
users won't ever need to know anything about the page life 
cycle.</p></div></div><p>&#160;</p><p>In Tapestry, you are free to develop your 
presentation objects, page and components classes, as ordinary objects, 
complete with instance variables and so forth.</p><p>This is somewhat 
revolutionary in terms of web development in Java. By comparison, using 
traditional servlets, or Struts, your presentation objects (Servlets, or Struts 
Actions, or the equivalent in other frameworks) are <em>stateless 
singletons</em>. That is, a <em>single</em> instance is created, and all 
incoming requests are threaded through that single instance. Because multiple 
requests are handled by many different threads, this means that the singleton's 
instance 
 variables are useless ... any value written into an instance variable would 
immediately be overwritten by a different thread. Thus, it is necessary to use 
the Servlet API's HttpServletRequest object to store per-request data, and the 
HttpSession object to store data between requests.</p><p>Tapestry takes a very 
different approach.</p><p>In Tapestry, each page is a singleton, but with a 
<em>per thread</em> map of field names &amp; values that Tapestry invisibly 
manages for you.</p><p>With this approach, all the difficult, ugly issues 
related to multi-threading go by the wayside. Instead, familiar, simple coding 
practices (using ordinary methods and fields) can be used.</p><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>Tapestry 5.0 and 5.1 used page 
pooling, rather than a singleton page with a per-thread 
 map, to achieve the same effect.</p></div></div><p>The page life cycle is 
quite simple:</p><ol><li>When first needed, a page is loaded. Loading a page 
involves instantiating the components of the page and connecting them 
together.</li><li>Once a page is loaded, it is <em>attached</em> to the current 
request. Remember that there will be many threads, each handling its own 
request to the same page.</li><li>At the end of a request, after a response has 
been sent to the client, the page is <em>detached</em> from the request. This 
is a chance to perform any cleanup needed for the page.</li></ol><h2 
id="PageLifeCycle-PageLifeCycleMethods">Page Life Cycle Methods</h2><p>There 
are rare occasions where it is useful for a component to perform some 
operations, usually some kind of initialization or caching, based on the life 
cycle of the page.</p><p>As with <a  href="page-life-cycle.html">component 
rendering</a>, you have the ability to make your components "aware" of these 
events by telling T
 apestry what methods to invoke for each.</p><p>Page life cycle methods should 
take no parameters and return void.</p><p>You have the choice of attaching an 
annotation to a method, or simply using the method naming conventions:</p><div 
class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" 
rowspan="1" class="confluenceTh"><p>Annotation</p></th><th colspan="1" 
rowspan="1" class="confluenceTh"><p>Method Name</p></th><th colspan="1" 
rowspan="1" class="confluenceTh"><p>When Called</p></th></tr><tr><td 
colspan="1" rowspan="1" class="confluenceTd"><p>@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/PageLoaded.html";>PageLoaded</a></p></td><td
 colspan="1" rowspan="1" class="confluenceTd"><p>pageLoaded()</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>After the page is fully 
loaded</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>@<a 
 class="external-link" href="http://tapestry.ap
 
ache.org/current/apidocs/org/apache/tapestry5/annotations/PageAttached.html">PageAttached</a></p></td><td
 colspan="1" rowspan="1" class="confluenceTd"><p>pageAttached()</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>After the page is attached to 
the request.</p></td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd">@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/PageReset.html";>PageReset</a></td><td
 colspan="1" rowspan="1" class="confluenceTd">pageReset()</td><td colspan="1" 
rowspan="1" class="confluenceTd">After the page is <em>activated</em>, except 
when requesting the same page</td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd"><p>@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/PageDetached.html";>PageDetached</a></p></td><td
 colspan="1" rowspan="1" class="confluenceTd"><p>pageDetached()</p></td><td 
colspan="1" rowspan="1" class=
 "confluenceTd"><p>AFter the page is detached from the 
request.</p></td></tr></tbody></table></div><p>The @PageReset life cycle (only 
for Tapestry 5.2 and later) is invoked on a page render request when the page 
is linked to from some <em>other</em> page of the application (but <em>not</em> 
on a link to the same page), or upon a reload of the page in the browser. This 
is to allow the page to reset its state, if any, when a user returns to the 
page from some other part of the application.</p><h2 
id="PageLifeCycle-ComparisontoJavaServerPages">Comparison to JavaServer 
Pages</h2><p>JSPs also act as singletons. However, the individual JSP tags are 
pooled.</p><p>This is one of the areas where Tapestry can significantly 
outperform JSPs. Much of the code inside a compiled JSP class concerns getting 
tags from a tag pool, configuring the properties of the tag instance, using the 
tag instance, then cleaning up the tag instance and putting it back in the 
pool.</p><p>The operations Tapestry does 
 once per request are instead executed dozens or potentially hundreds of times 
(depending the complexity of the page, and if any nested loops 
occur).</p><p>Pooling JSP tags is simply the wrong granularity.</p><p>Tapestry 
can also take advantage of its more coarse grained caching to optimize how data 
moves, via parameters, between components. This means that Tapestry pages will 
actually speed up after they render the first time.</p><h2 
id="PageLifeCycle-PagePoolConfiguration">Page Pool Configuration</h2><div 
class="confluence-information-macro confluence-information-macro-note"><span 
class="aui-icon aui-icon-small aui-iconfont-warning 
confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>This related to versions of 
Tapestry prior to 5.2. Modern Tapestry uses an alternate approach that allows a 
single page instance to be shared across many request processing 
threads.</p></div></div><p>In Tapestry 5.0 and 5.1, a page pool is used to 
store page insta
 nces. The pool is "keyed" on the name of the page (such as "start") and the 
<em>locale</em> for the page (such as "en" or "fr").</p><p>Within each key, 
Tapestry tracks the number of page instances that have been created, as well as 
the number that are in use (currently attached to a request).</p><p>When a page 
is first accessed in a request, it is taken from the pool. Tapestry has some <a 
 href="page-life-cycle.html">configuration values</a> that control the details 
of how and when page instances are created.</p><ul><li>If a free page instance 
is available, the page is marked in use and attached to the request.</li><li>If 
there are fewer page instances than the <em>soft limit</em>, then a new page 
instance is simply created and attached to the request.</li><li>If the soft 
limit has been reached, Tapestry will wait for a short period of time for a 
page instance to become available before creating a new page 
instance.</li><li>If the hard limit has been reached, Tapestry will throw an 
 exception rather than create a new page instance.</li><li>Otherwise, Tapestry 
will create a new page instance.<br clear="none"> Thus a busy application will 
initially create pages up-to the soft limit (which defaults to five page 
instances). If the application continues to be pounded with requests, it will 
slow its request processing, using the soft wait time in an attempt to reuse an 
existing page instance.</li></ul><p>A truly busy application will continue to 
create new page instances as needed until the hard limit is 
reached.</p><p>Remember that all these configuration values are per key: the 
combination of page name and locale. Thus even with a hard limit of 20, you may 
eventually find that Tapestry has created 20 start page instances for locale 
"en" <em>and</em> 20 start page instances for locale "fr" (if your application 
is configured to support both English and French). Likewise, you may have 20 
instances for the start page, and 20 instances for the newaccount 
page.</p><p>Tap
 estry periodically checks its cache for page instances that have not been used 
recently (within a configurable window). Unused page instances are release to 
the garbage collector.</p><p>The end result is that you have quite a degree of 
tuning control over the process. If memory is a limitation and throughput can 
be sacrificed, try lowering the soft and hard limit and increasing the soft 
wait.</p><p>If performance is absolute and you have lots of memory, then 
increase the soft and hard limit and reduce the soft wait. This encourages 
Tapestry to create more page instances and not wait as long to re-use existing 
instances.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/page-navigation.html
==============================================================================
--- websites/production/tapestry/content/page-navigation.html (original)
+++ websites/production/tapestry/content/page-navigation.html Sat Feb  3 
16:21:22 2018
@@ -27,6 +27,16 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' 
rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' 
type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushJava.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushPlain.js' 
type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,20 +77,109 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><parameter 
ac:name="style">float:right</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter 
ac:name="class">aui-label</parameter><rich-text-body><parameter 
ac:name="showLabels">false</parameter><parameter 
ac:name="showSpace">false</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter ac:name="cql">label in 
("request-processing","rendering") and space = 
currentSpace()</parameter></rich-text-body><p>In essence, a Tapestry 
application is a number of related pages, working together. To some degree, 
each page is like an application unto itself.</p><p>Any individual request will 
be targeted at a single page. Requests come in two 
forms:&#160;</p><ul><li><em>component event</em> requests target a specific 
component on a specific page, triggering an event within that 
component</li><li><em>render</em> requests target a specific page, and stream 
the HTML markup for that page back to the client</li></ul><
 p>This dichotomy between component event requests and render requests 
alleviates a number of problems in traditional web applications related to the 
browser back button, or to the user hitting the refresh button in their 
browser.</p><p><br clear="none"><span style="color: rgb(83,145,38);font-size: 
20.0px;line-height: 1.5;">Logical Page Name Shortening</span></p><p>In certain 
cases, Tapestry will shorten the the logical name of a page. For example, the 
page class org.example.pages.address.CreateAddress will be given a logical name 
of "address/Create" (the redundant "Address" is removed as a suffix). However, 
this only affects how the page is referenced in URLs; the template file will 
still be CreateAddress.tml, whether on the classpath, or as 
address/CreateAddress.tml (in the web context).</p><p><span>Tapestry actually 
creates multiple names for the name page: "address/Create" and 
"address/CreateAddress" are both synonymous. You can user either in Java code 
that refers to a page by n
 ame, or as the page parameter of a PageLink.</span></p><h2 
id="PageNavigation-ComponentEventRequests&amp;Responses">Component Event 
Requests &amp; Responses</h2><p>Main Article: <a  
href="component-events.html">Component Events</a></p><p>Component event 
requests may take the form of hyperlinks (<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/EventLink.html";>EventLink</a>
 or <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/ActionLink.html";>ActionLink</a>)
 or form submissions (<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html";>Form</a>).</p><p>The
 value returned from an <a  href="component-events.html">event handler 
method</a> controls the response sent to the client web browser.</p><p>The URL 
for a component event request identifies the name of the page, the nested id of 
the comp
 onent, and the name of the event to trigger on the component (specified by the 
"event" parameter of EventLink, or "action" for an ActionLink). Further, a 
component event request may contain additional context information, which will 
be provided to the event handler method.</p><p>These URLs expose a bit of the 
internal structure of the application. Over time, as an application grows and 
is maintained, the ids of components may change. This means that component 
event request URLs should not be bookmarked. Fortunately, users will rarely 
have the chance to do so (see below).</p><h3 
id="PageNavigation-1.Nullresponse">1. Null response</h3><p>If the event handler 
method returns no value, or returns null, then the current page (the page 
containing the component) will render the response.</p><p>A page render URL for 
the current page is created and sent to the client as a client side redirect. 
The client browser will automatically submit a new request to generate the 
page.</p><p>The user will
  see the newly generated content in their browser. In addition, the URL in the 
browser's address bar will be a render request URL. Render request URLs are 
shorter and contain less application structure (for instance, they don't 
include component ids or event types). Render requests URLs are what your users 
will bookmark. The component event request URLs are transitory, meaningful only 
while the application is actively engaged, and not meant to be used in later 
sessions.</p><plain-text-body>public Object onAction(){
+                <div id="ConfluenceContent"><div class="aui-label" 
style="float:right" title="Related Articles">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="content-type-and-markup.html">Content Type 
and Markup</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="page-navigation.html">Page Navigation</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="page-life-cycle.html">Page Life Cycle</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-rendering.html">Component 
Rendering</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-events.html">Component Events</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-events-faq.html">Component Events 
FAQ</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="request-processing.html">Request 
Processing</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div>
+
+
+<p>In essence, a Tapestry application is a number of related pages, working 
together. To some degree, each page is like an application unto 
itself.</p><p>Any individual request will be targeted at a single page. 
Requests come in two forms:&#160;</p><ul><li><em>component event</em> requests 
target a specific component on a specific page, triggering an event within that 
component</li><li><em>render</em> requests target a specific page, and stream 
the HTML markup for that page back to the client</li></ul><p>This dichotomy 
between component event requests and render requests alleviates a number of 
problems in traditional web applications related to the browser back button, or 
to the user hitting the refresh button in their browser.</p><p><br 
clear="none"><span style="color: rgb(83,145,38);">Logical Page Name 
Shortening</span></p><p>In certain cases, Tapestry will shorten the the logical 
name of a page. For example, the page class 
org.example.pages.address.CreateAddress will be given a l
 ogical name of "address/Create" (the redundant "Address" is removed as a 
suffix). However, this only affects how the page is referenced in URLs; the 
template file will still be CreateAddress.tml, whether on the classpath, or as 
address/CreateAddress.tml (in the web context).</p><p><span>Tapestry actually 
creates multiple names for the name page: "address/Create" and 
"address/CreateAddress" are both synonymous. You can user either in Java code 
that refers to a page by name, or as the page parameter of a 
PageLink.</span></p><h2 
id="PageNavigation-ComponentEventRequests&amp;Responses">Component Event 
Requests &amp; Responses</h2><p>Main Article: <a  
href="page-navigation.html">Page Navigation</a></p><p>Component event requests 
may take the form of hyperlinks (<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/EventLink.html";>EventLink</a>
 or <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apa
 che/tapestry5/corelib/components/ActionLink.html">ActionLink</a>) or form 
submissions (<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html";>Form</a>).</p><p>The
 value returned from an <a  href="page-navigation.html">event handler 
method</a> controls the response sent to the client web browser.</p><p>The URL 
for a component event request identifies the name of the page, the nested id of 
the component, and the name of the event to trigger on the component (specified 
by the "event" parameter of EventLink, or "action" for an ActionLink). Further, 
a component event request may contain additional context information, which 
will be provided to the event handler method.</p><p>These URLs expose a bit of 
the internal structure of the application. Over time, as an application grows 
and is maintained, the ids of components may change. This means that component 
event request URLs should not be bookmarked. Fortunately, users
  will rarely have the chance to do so (see below).</p><h3 
id="PageNavigation-1.Nullresponse">1. Null response</h3><p>If the event handler 
method returns no value, or returns null, then the current page (the page 
containing the component) will render the response.</p><p>A page render URL for 
the current page is created and sent to the client as a client side redirect. 
The client browser will automatically submit a new request to generate the 
page.</p><p>The user will see the newly generated content in their browser. In 
addition, the URL in the browser's address bar will be a render request URL. 
Render request URLs are shorter and contain less application structure (for 
instance, they don't include component ids or event types). Render requests 
URLs are what your users will bookmark. The component event request URLs are 
transitory, meaningful only while the application is actively engaged, and not 
meant to be used in later sessions.</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;">public Object onAction(){
   return null;
-}</plain-text-body><h3 id="PageNavigation-2.Stringresponse">2. String 
response</h3><p>When a string is returned, it is expected to be the logical 
name of a page (as opposed to the page's fully qualified class name). As 
elsewhere, the name of the page is case insensitive.</p><p>Again, a render 
request URL will be constructed and sent to the client as a 
redirect.</p><plain-text-body>public String onAction(){
+}</pre>
+</div></div><h3 id="PageNavigation-2.Stringresponse">2. String 
response</h3><p>When a string is returned, it is expected to be the logical 
name of a page (as opposed to the page's fully qualified class name). As 
elsewhere, the name of the page is case insensitive.</p><p>Again, a render 
request URL will be constructed and sent to the client as a redirect.</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;">public String onAction(){
   return "Index";
-}</plain-text-body><h3 id="PageNavigation-3.Classresponse">3. Class 
response</h3><p>When a class is returned, it is expected to be a page class. 
Returning a page class from an event handler is safer for refactoring than 
returning a page name.</p><p>As with other response types, a render request URL 
will be constructed and sent to the client as a 
redirect.</p><plain-text-body>public Object onAction(){
+}</pre>
+</div></div><h3 id="PageNavigation-3.Classresponse">3. Class 
response</h3><p>When a class is returned, it is expected to be a page class. 
Returning a page class from an event handler is safer for refactoring than 
returning a page name.</p><p>As with other response types, a render request URL 
will be constructed and sent to the client as a redirect.</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;">public Object onAction(){
   return Index.class
-}</plain-text-body><h3 id="PageNavigation-4.Pageresponse">4. Page 
response</h3><p>You may also return an instance of a page, rather than the name 
or class of a page.</p><p>A page may be injected via the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/InjectPage.html";>InjectPage</a>
 annotation.</p><p>Often, you will configure the page in some way before 
returning the page (examples below).</p><p>You can also return a component 
within the page, but this will generate a runtime warning (unless you are doing 
a partial-page update via <a  
href="ajax-and-zones.html">Ajax</a>).</p><plain-text-body>@InjectPage
+}</pre>
+</div></div><h3 id="PageNavigation-4.Pageresponse">4. Page response</h3><p>You 
may also return an instance of a page, rather than the name or class of a 
page.</p><p>A page may be injected via the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/InjectPage.html";>InjectPage</a>
 annotation.</p><p>Often, you will configure the page in some way before 
returning the page (examples below).</p><p>You can also return a component 
within the page, but this will generate a runtime warning (unless you are doing 
a partial-page update via <a  href="page-navigation.html">Ajax</a>).</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;">@InjectPage
 private Index index;
 
 public Object onAction(){
   return index;
-}</plain-text-body><h3 id="PageNavigation-5.HttpError">5. HttpError</h3><p>An 
event handler method may return a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpError.html";>HttpError</a>
 instance to send an error response to the client.</p><plain-text-body>public 
Object onAction(){
+}</pre>
+</div></div><h3 id="PageNavigation-5.HttpError">5. HttpError</h3><p>An event 
handler method may return a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpError.html";>HttpError</a>
 instance to send an error response to the client.</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;">public Object onAction(){
   return new HttpError(302, "The Error message);
-}</plain-text-body><h3 id="PageNavigation-6.Linkresponse">6. Link 
response</h3><p>An event handler method may return a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Link.html";>Link</a>
 instance directly. The Link is converted into a URL and a client redirect to 
that URL is sent to the client.</p><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentResources.html";>ComponentResources</a>
 object that is injected into your pages (and components) has methods for 
creating component links.</p><p>The&#160;<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PageRenderLinkSource.html";>PageRenderLinkSource</a>
 service can be injected to allow links to other pages to be created (though 
that is rarely necessary, given the other options listed above).</p><h3 
id="PageNavigation-7.Streamresponse">7. Stream response</h3><p>An event handler 
 can also return a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/StreamResponse.html";>StreamResponse</a>
 object, which encapsulates a stream to be sent directly to the client browser. 
This is useful for components that want to, say, generate an image or PDF and 
provide it to the client:</p><plain-text-body>public Object onAction(){
+}</pre>
+</div></div><h3 id="PageNavigation-6.Linkresponse">6. Link response</h3><p>An 
event handler method may return a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Link.html";>Link</a>
 instance directly. The Link is converted into a URL and a client redirect to 
that URL is sent to the client.</p><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentResources.html";>ComponentResources</a>
 object that is injected into your pages (and components) has methods for 
creating component links.</p><p>The&#160;<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PageRenderLinkSource.html";>PageRenderLinkSource</a>
 service can be injected to allow links to other pages to be created (though 
that is rarely necessary, given the other options listed above).</p><h3 
id="PageNavigation-7.Streamresponse">7. Stream response</h3><p>An event handler 
can als
 o return a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/StreamResponse.html";>StreamResponse</a>
 object, which encapsulates a stream to be sent directly to the client browser. 
This is useful for components that want to, say, generate an image or PDF and 
provide it to the client:</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;">public Object onAction(){
     return new StreamResponse() {
         @Override
         public String getContentType() {
@@ -95,24 +194,29 @@ public Object onAction(){
             response.setHeader("Content-Disposition", "attachment; 
filename=\"" + myFileName + "\"");
         }
     };
-}</plain-text-body><p>&#160;</p><h3 id="PageNavigation-8.URLresponse">8. URL 
response</h3><p>A java.net.URL response is handled as a client redirect to an 
external URL. (In Tapestry 5.3.x and earlier this only works for non-Ajax 
requests.)</p><h3 id="PageNavigation-9.Objectresponse">9. Object 
response</h3><p>Any other type of object returned from an event handler method 
is an error.</p><h2 id="PageNavigation-PageRenderRequests">Page Render 
Requests</h2><p>Render requests are simpler in structure and behavior than 
component event requests. In the simplest case, the URL is simply the logical 
name of the page.</p><p>Pages may have an <em>activation context</em>. The 
activation context represents persistent information about the state of the 
page. In practical terms, the activation context is usually the id of some 
database-persistent object.</p><p>When a page has an activation context, the 
values of the context are appended to the URL path. For example, 
in&#160;<code>http://www.example
 .com/myapp/foo/bar</code> the "myapp" part is the servlet context (usually the 
name of your app), and the "foo/bar" part is the activation context, with "foo" 
being the first activation parameter and "bar" being the second.</p><p>It is 
common for most pages to not have any activation context.</p><p>The activation 
context may be explicitly set when the render request link is created (the 
PageLink component has a context parameter for this purpose).</p><p>When no 
explicit activation context is provided, the page itself is queried for its 
activation context. This querying takes the form of an event trigger. The event 
name is "passivate" (as we'll see shortly, there's a corresponding "activate"). 
The return value of the method is used as the context. For 
example:</p><parameter ac:name="">java</parameter><plain-text-body>public class 
ProductDetail
+}</pre>
+</div></div><p>&#160;</p><h3 id="PageNavigation-8.URLresponse">8. URL 
response</h3><p>A <a  class="external-link" href="http://java.net"; 
rel="nofollow">java.net</a>.URL response is handled as a client redirect to an 
external URL. (In Tapestry 5.3.x and earlier this only works for non-Ajax 
requests.)</p><h3 id="PageNavigation-9.Objectresponse">9. Object 
response</h3><p>Any other type of object returned from an event handler method 
is an error.</p><h2 id="PageNavigation-PageRenderRequests">Page Render 
Requests</h2><p>Render requests are simpler in structure and behavior than 
component event requests. In the simplest case, the URL is simply the logical 
name of the page.</p><p>Pages may have an <em>activation context</em>. The 
activation context represents persistent information about the state of the 
page. In practical terms, the activation context is usually the id of some 
database-persistent object.</p><p>When a page has an activation context, the 
values of the context are appended t
 o the URL path. For example, in&#160;<code><a  class="external-link" 
href="http://www.example.com/myapp/foo/bar"; 
rel="nofollow">http://www.example.com/myapp/foo/bar</a></code> the "myapp" part 
is the servlet context (usually the name of your app), and the "foo/bar" part 
is the activation context, with "foo" being the first activation parameter and 
"bar" being the second.</p><p>It is common for most pages to not have any 
activation context.</p><p>The activation context may be explicitly set when the 
render request link is created (the PageLink component has a context parameter 
for this purpose).</p><p>When no explicit activation context is provided, the 
page itself is queried for its activation context. This querying takes the form 
of an event trigger. The event name is "passivate" (as we'll see shortly, 
there's a corresponding "activate"). The return value of the method is used as 
the context. For example:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeCon
 tent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public class ProductDetail
 {
   private Product product;
   . . .
   long onPassivate() { return product.getId(); }
 }
-</plain-text-body><p>The activation context may consist of a series of values, 
in which case the return value of the method should be an array or a 
List.</p><rich-text-body><p>Note: If you are using the <a  
href="hibernate-user-guide.html">tapestry-hibernate</a> integration library and 
your passivate context is a Hibernate entity, then you can just use the entity 
itself, not its id. Tapestry will automatically extract the entity's id into 
the URL, and convert it back for the "activate" event handler 
method.</p></rich-text-body><h2 id="PageNavigation-Pageactivation">Page 
activation</h2><p>When a page render request arrives, the page is 
<em>activated</em> before it is 
rendered.<plain-text-body>{float:right|background=#eee|padding=0 1em}
-    *JumpStart Demos:*
-    [onActivate and 
onPassivate|http://jumpstart.doublenegative.com.au/jumpstart/examples/navigation/onactivateandonpassivate/3]
-    [Handling A Bad 
Context|http://jumpstart.doublenegative.com.au/jumpstart/examples/infrastructure/handlingabadcontext/1]
-{float}</plain-text-body>Activation serves two purposes:</p><ul><li>It allows 
the page to restore its internal state from data encoded into the URL (the 
activation context discussed above).</li><li>It provides coarse approach to 
validating access to the page.</li></ul><p>The later case &#8211; 
validation&#160;&#8211; is generally concerned with user identity and access; 
if you have pages that may only be accessed by certain users, you may use the 
page's activate event handler for verifying that access.</p><p>Page activation 
uses Tapestry's <em>Component Event</em> mechanism. See <a  
href="component-events.html">Component Events</a> for details.</p><p>A page's 
activate event handler mirrors its passivate handler:</p><parameter 
ac:name="">java</parameter><plain-text-body>  private Product product;
+</pre>
+</div></div><p>The activation context may consist of a series of values, in 
which case the return value of the method should be an array or a List.</p><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>Note: If you are using the <a  
href="page-navigation.html">tapestry-hibernate</a> integration library and your 
passivate context is a Hibernate entity, then you can just use the entity 
itself, not its id. Tapestry will automatically extract the entity's id into 
the URL, and convert it back for the "activate" event handler 
method.</p></div></div><h2 id="PageNavigation-Pageactivation">Page 
activation</h2><p>When a page render request arrives, the page is 
<em>activated</em> before it is rendered.</p><div class="navmenu" 
style="float:right; background:#eee; margin:3px; padding:0 1em">
+<p>    <strong>JumpStart Demos:</strong><br clear="none">
+    <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/navigation/onactivateandonpassivate/3";
 rel="nofollow">onActivate and onPassivate</a><br clear="none">
+    <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/infrastructure/handlingabadcontext/1";
 rel="nofollow">Handling A Bad Context</a></p></div>Activation serves two 
purposes:<ul><li>It allows the page to restore its internal state from data 
encoded into the URL (the activation context discussed above).</li><li>It 
provides coarse approach to validating access to the page.</li></ul><p>The 
later case &#8211; validation&#160;&#8211; is generally concerned with user 
identity and access; if you have pages that may only be accessed by certain 
users, you may use the page's activate event handler for verifying that 
access.</p><p>Page activation uses Tapestry's <em>Component Event</em> 
mechanism. See <a  href="page-navigation.html">Page Navigation</a> for 
details.</p><p>A page's activate event handler mirrors its passivate 
handler:</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;">  private Product product;
   . . .
   void onActivate(long productId)
   {
      product = productDAO.getById(productId);
   }
   . . .
-</plain-text-body><p>Here's the relevant part: when the page renders, it is 
likely to include more component event request URLs (links and forms). The 
component event requests for those links and forms will <em>also</em> start by 
activating the page, before performing other work. This forms an unbroken chain 
of requests that include the same activation context.</p><p>To some degree, 
this same effect could be accomplished using a <a  
href="persistent-page-data.html">persistent page value</a>, but that requires 
an active servlet session, and the result is not bookmarkable.</p><p>Your 
activate event handler, like any event handler, may also return a value, which 
is treated identically to a return value of a component event method. This 
technique is commonly used as a simple access validation mechanism.</p><p>You 
sometimes need to handle multiple page activation scenarios in one page class. 
You could create multiple activate event handler methods with different 
arguments (see the "Multi
 ple Method Matches" section at <a  href="component-events.html">Component 
Events</a> for details), but if you do so, you should generally 
return&#160;<code>true</code> from each to avoid having more than one 
activation event handler method from being called for each page request. 
However, a better approach is to create one method with an EventContext 
argument. Tapestry will populate the EventContext argument with all of the 
activation parameters, and the EventContext's&#160;<code>get</code> method will 
retrieve and coerce each parameter to the desired type. For 
example:</p><parameter ac:name="">java</parameter><plain-text-body>  . . .
+</pre>
+</div></div><p>Here's the relevant part: when the page renders, it is likely 
to include more component event request URLs (links and forms). The component 
event requests for those links and forms will <em>also</em> start by activating 
the page, before performing other work. This forms an unbroken chain of 
requests that include the same activation context.</p><p>To some degree, this 
same effect could be accomplished using a <a  
href="page-navigation.html">persistent page value</a>, but that requires an 
active servlet session, and the result is not bookmarkable.</p><p>Your activate 
event handler, like any event handler, may also return a value, which is 
treated identically to a return value of a component event method. This 
technique is commonly used as a simple access validation mechanism.</p><p>You 
sometimes need to handle multiple page activation scenarios in one page class. 
You could create multiple activate event handler methods with different 
arguments (see the "Multiple Method 
 Matches" section at <a  href="page-navigation.html">Page Navigation</a> for 
details), but if you do so, you should generally return&#160;<code>true</code> 
from each to avoid having more than one activation event handler method from 
being called for each page request. However, a better approach is to create one 
method with an EventContext argument. Tapestry will populate the EventContext 
argument with all of the activation parameters, and the 
EventContext's&#160;<code>get</code> method will retrieve and coerce each 
parameter to the desired type. For 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;">  . . .
 
   void onActivate(EventContext eventContext) {
 
@@ -131,10 +235,14 @@ public Object onAction(){
   }
 
   . . .
-</plain-text-body><h2 id="PageNavigation-PageNavigationPatterns">Page 
Navigation Patterns</h2><p>This combination of action links and context and 
page context can be put together in any number of ways.</p><p>Let's take a 
typical master/detail relationship using the concept of a product catalog page. 
In this example, the ProductListing page is a list of products, and the 
ProductDetails page must display the details for a specific product.</p><h3 
id="PageNavigation-Pattern1:Componenteventrequests/PersistentData">Pattern 1: 
Component event requests / Persistent Data</h3><p>In this pattern, the 
ProductListing page uses action events and a persistent field on the 
ProductDetails page.</p><parameter ac:name="">java</parameter><parameter 
ac:name="title">ProductListing.html</parameter><plain-text-body>  &lt;t:loop 
source="products" value="product"&gt;
+</pre>
+</div></div><h2 id="PageNavigation-PageNavigationPatterns">Page Navigation 
Patterns</h2><p>This combination of action links and context and page context 
can be put together in any number of ways.</p><p>Let's take a typical 
master/detail relationship using the concept of a product catalog page. In this 
example, the ProductListing page is a list of products, and the ProductDetails 
page must display the details for a specific product.</p><h3 
id="PageNavigation-Pattern1:Componenteventrequests/PersistentData">Pattern 1: 
Component event requests / Persistent Data</h3><p>In this pattern, the 
ProductListing page uses action events and a persistent field on the 
ProductDetails page.</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>ProductListing.html</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  &lt;t:loop source="products" value="product"&gt;
     &lt;a t:type="actionlink" t:id="select" 
context="product.id"&gt;${product.name}&lt;/a&gt;
   &lt;/t:loop&gt;
-</plain-text-body><parameter ac:name="">java</parameter><parameter 
ac:name="title">ProductListing.java</parameter><plain-text-body>  @InjectPage
+</pre>
+</div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>ProductListing.java</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @InjectPage
   private ProductDetails details;
 
   Object onActionFromSelect(long productId)
@@ -143,7 +251,9 @@ public Object onAction(){
 
     return details;
   }
-</plain-text-body><parameter ac:name="">java</parameter><parameter 
ac:name="title">ProductDetails.java</parameter><plain-text-body>  @Inject
+</pre>
+</div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>ProductDetails.java</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Inject
   private ProductDAO dao;
 
   private Product product;
@@ -157,7 +267,9 @@ public Object onAction(){
   {
     product = dao.getById(productId);
   }
-</plain-text-body><p>This is a minimal approach, perhaps good enough for a 
prototype.</p><p>When the user clicks a link, the component event request URL 
will initially be something like "http://.../productlisting.select/99"; and the 
final render request URL will be something like "http://.../productdetails";. 
Notice that the product id ("99") does not appear in the render request 
URL.</p><p>This pattern has the following drawbacks:</p><ul><li>It requires a 
session (to store the productId field between requests).</li><li>It may fail if 
the ProductDetails page is accessed before a valid product id is 
set.</li><li>The URL does not indicate the identity of the product; if the user 
bookmarks the URL and comes back later, they will trigger the previous case (no 
valid product id).</li></ul><p><parameter 
ac:name="">activationpattern</parameter></p><h3 
id="PageNavigation-Pattern2:ComponentEventRequests/NoPersistentData">Pattern 2: 
Component Event Requests / No Persistent Data</h3><p>We can imp
 rove the previous example without changing the ProductListing page, using a 
passivation and activation context to avoid the session and make the links more 
bookmarkable.</p><parameter ac:name="">java</parameter><parameter 
ac:name="title">ProductDetails.java</parameter><plain-text-body>  @Inject
+</pre>
+</div></div><p>This is a minimal approach, perhaps good enough for a 
prototype.</p><p>When the user clicks a link, the component event request URL 
will initially be something like "http://.../productlisting.select/99"; and the 
final render request URL will be something like "http://.../productdetails";. 
Notice that the product id ("99") does not appear in the render request 
URL.</p><p>This pattern has the following drawbacks:</p><ul><li>It requires a 
session (to store the productId field between requests).</li><li>It may fail if 
the ProductDetails page is accessed before a valid product id is 
set.</li><li>The URL does not indicate the identity of the product; if the user 
bookmarks the URL and comes back later, they will trigger the previous case (no 
valid product id).</li></ul><p><span class="confluence-anchor-link" 
id="PageNavigation-activationpattern"></span></p><h3 
id="PageNavigation-Pattern2:ComponentEventRequests/NoPersistentData">Pattern 2: 
Component Event Requests / No Persiste
 nt Data</h3><p>We can improve the previous example without changing the 
ProductListing page, using a passivation and activation context to avoid the 
session and make the links more bookmarkable.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>ProductDetails.java</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Inject
   private ProductDAO dao;
 
   private Product product;
@@ -174,11 +286,17 @@ public Object onAction(){
   }
 
   long onPassivate() { return productId; }
-</plain-text-body><p>This change ensures that the render request URL will 
include the product id, i.e., "http://.../productdetails/99";.</p><p>It has the 
advantage that the connection from page to page occurs in type-safe Java code, 
inside the onActionFromSelect method of ProductListing. It has the disadvantage 
that clicking a link requires two round trips to the server.</p><h3 
id="PageNavigation-Pattern3:RenderRequestsOnly">Pattern 3: Render Requests 
Only</h3><p>This is the most common version of this master/detail 
relationship.</p><parameter ac:name="">java</parameter><parameter 
ac:name="title">ProductListing.html</parameter><plain-text-body>  &lt;t:loop 
source="products" value="product"&gt;
+</pre>
+</div></div><p>This change ensures that the render request URL will include 
the product id, i.e., "http://.../productdetails/99";.</p><p>It has the 
advantage that the connection from page to page occurs in type-safe Java code, 
inside the onActionFromSelect method of ProductListing. It has the disadvantage 
that clicking a link requires two round trips to the server.</p><h3 
id="PageNavigation-Pattern3:RenderRequestsOnly">Pattern 3: Render Requests 
Only</h3><p>This is the most common version of this master/detail 
relationship.</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>ProductListing.html</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  &lt;t:loop source="products" value="product"&gt;
     &lt;a t:type="pagelink" page="productdetails" 
context="product.id"&gt;${product.name}&lt;/a&gt;
   &lt;/t:loop&gt;
-</plain-text-body><parameter ac:name="">java</parameter><parameter 
ac:name="title">ProductListing.java</parameter><plain-text-body>No code is 
needed to support the link.
-</plain-text-body><parameter ac:name="">java</parameter><parameter 
ac:name="title">ProductDetails.java</parameter><plain-text-body>  @Inject
+</pre>
+</div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>ProductListing.java</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">No code is needed to support the link.
+</pre>
+</div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>ProductDetails.java</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Inject
   private ProductDAO dao;
 
   private Product product;
@@ -193,7 +311,8 @@ public Object onAction(){
   }
 
   long onPassivate() { return productId; }
-</plain-text-body><p>The setProductId() method is no longer needed.</p><h3 
id="PageNavigation-Limitations">Limitations</h3><p>As your application's 
workflow expands, you may find that there is not a reasonable way to avoid 
storing some data persistently between requests, outside of the page activation 
context. For example, if from the ProductDetails page, the user is allowed to 
navigate to related pages and then back to ProductDetails, it starts to become 
necessary to keep passing that product id around from page to page to 
page.</p><p>At some point, persistent values make more sense. Tapestry has 
several persistence strategies available, including one that stores data in URL 
query parameters. See <a  href="persistent-page-data.html">Persistent Page 
Data</a> for details.</p></div>
+</pre>
+</div></div><p>The setProductId() method is no longer needed.</p><h3 
id="PageNavigation-Limitations">Limitations</h3><p>As your application's 
workflow expands, you may find that there is not a reasonable way to avoid 
storing some data persistently between requests, outside of the page activation 
context. For example, if from the ProductDetails page, the user is allowed to 
navigate to related pages and then back to ProductDetails, it starts to become 
necessary to keep passing that product id around from page to page to 
page.</p><p>At some point, persistent values make more sense. Tapestry has 
several persistence strategies available, including one that stores data in URL 
query parameters. See <a  href="page-navigation.html">Page Navigation</a> for 
details.</p></div>
       </div>
 
       <div class="clearer"></div>


Reply via email to