Modified: websites/production/tapestry/content/page-navigation.html
==============================================================================
--- websites/production/tapestry/content/page-navigation.html (original)
+++ websites/production/tapestry/content/page-navigation.html Wed Sep 20 
12:29:16 2017
@@ -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);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.addr
 ess.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 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="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://tapest
 
ry.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 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="ajax-and-zones.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 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/my
 app/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><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 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="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></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="component-events.html">Component Events</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="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 "Multiple Me
 thod 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><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="persistent-page-data.html">Persistent Page 
Data</a> for details.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/parallel-execution.html
==============================================================================
--- websites/production/tapestry/content/parallel-execution.html (original)
+++ websites/production/tapestry/content/parallel-execution.html Wed Sep 20 
12:29:16 2017
@@ -27,6 +27,14 @@
       </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>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,7 +75,11 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/ParallelExecutor.html";>ParallelExecutor</a>
 service allows a computation to occur in parallel.</p><p>It can be used in two 
ways. First, with an explicit <a  class="external-link" 
href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html";
 rel="nofollow">Future</a>:</p><parameter 
ac:name="">java</parameter><plain-text-body>   Future&lt;String&gt; future = 
executor.invoke(new Invokable&lt;String&gt;() { ... });</plain-text-body><p>The 
executor will submit the Invokable to a thread pool for execution in the 
background.</p><p>The ultimate value of the Invokable is available by invoking 
<code>get()</code> on the Future; this will block until the value is 
ready.</p><p>Other methods on Future can cancel the execution, or get the value 
only if it is ready within a timeout.</p><p>The thread pool is started automat
 ically as needed, and will shutdown when the Registry itself is 
shutdown.</p><p>Another alternative will return an object proxy, not a 
Future:</p><parameter ac:name="">java</parameter><plain-text-body>  RSSFeed 
feed = executor.invoke(RSSFeed.class, new Invokable&lt;RSSFeed&gt;() { ... 
});</plain-text-body><p>This only works if the type is an interface. A proxy 
for the interface is created around the Future object; any invocation on the 
proxy will invoke get() on the Future (that is, will block until the value is 
computed).</p><h1 id="ParallelExecution-Configuration">Configuration</h1><p>The 
behavior of the ParallelExecutor can be tuned with global configuration 
symbols.</p><p>Java constants for the configuration symbols are defined in <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/IOCSymbols.html";>IOCSymbols</a>.</p><h3
 
id="ParallelExecution-tapestry.thread-pool-enabled">tapestry.thread-pool-enabled</h3><p>If
 true, the default, th
 en the thread pool will operate. If false, then ParallelExecutor's 
implementation changes to invoke the Invokable immediately, not in a pooled 
thread. This is useful in environments, such as <a  class="external-link" 
href="http://code.google.com/appengine/"; rel="nofollow">Google App Engine</a>, 
that do not support the creation of threads and thread pools.</p><h3 
id="ParallelExecution-tapestry.thread-pool.core-pool-size">tapestry.thread-pool.core-pool-size</h3><p>Minimum
 size of the thread pool. Defaults to 3.</p><h3 
id="ParallelExecution-tapestry.thread-pool.max-pool-size">tapestry.thread-pool.max-pool-size</h3><p>Maximum
 number of threads (active or inactive) in the thread pool. Defaults to 
20.</p><h3 
id="ParallelExecution-tapestry.thread-pool.keep-alive">tapestry.thread-pool.keep-alive</h3><p>Time
 to keep waiting threads alive. Defaults to "1 m" (one minute).</p><h3 
id="ParallelExecution-tapestry.thread-pool.queue-size">tapestry.thread-pool.queue-size</h3><p>
+                <div id="ConfluenceContent"><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/ParallelExecutor.html";>ParallelExecutor</a>
 service allows a computation to occur in parallel.</p><p>It can be used in two 
ways. First, with an explicit <a  class="external-link" 
href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html";
 rel="nofollow">Future</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;">   Future&lt;String&gt; future = executor.invoke(new 
Invokable&lt;String&gt;() { ... });</pre>
+</div></div><p>The executor will submit the Invokable to a thread pool for 
execution in the background.</p><p>The ultimate value of the Invokable is 
available by invoking <code>get()</code> on the Future; this will block until 
the value is ready.</p><p>Other methods on Future can cancel the execution, or 
get the value only if it is ready within a timeout.</p><p>The thread pool is 
started automatically as needed, and will shutdown when the Registry itself is 
shutdown.</p><p>Another alternative will return an object proxy, not a 
Future:</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;">  RSSFeed feed = executor.invoke(RSSFeed.class, new 
Invokable&lt;RSSFeed&gt;() { ... });</pre>
+</div></div><p>This only works if the type is an interface. A proxy for the 
interface is created around the Future object; any invocation on the proxy will 
invoke get() on the Future (that is, will block until the value is 
computed).</p><h1 id="ParallelExecution-Configuration">Configuration</h1><p>The 
behavior of the ParallelExecutor can be tuned with global configuration 
symbols.</p><p>Java constants for the configuration symbols are defined in <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/IOCSymbols.html";>IOCSymbols</a>.</p><h3
 
id="ParallelExecution-tapestry.thread-pool-enabled">tapestry.thread-pool-enabled</h3><p>If
 true, the default, then the thread pool will operate. If false, then 
ParallelExecutor's implementation changes to invoke the Invokable immediately, 
not in a pooled thread. This is useful in environments, such as <a  
class="external-link" href="http://code.google.com/appengine/"; 
rel="nofollow">Google App Engine</a>,
  that do not support the creation of threads and thread pools.</p><h3 
id="ParallelExecution-tapestry.thread-pool.core-pool-size">tapestry.thread-pool.core-pool-size</h3><p>Minimum
 size of the thread pool. Defaults to 3.</p><h3 
id="ParallelExecution-tapestry.thread-pool.max-pool-size">tapestry.thread-pool.max-pool-size</h3><p>Maximum
 number of threads (active or inactive) in the thread pool. Defaults to 
20.</p><h3 
id="ParallelExecution-tapestry.thread-pool.keep-alive">tapestry.thread-pool.keep-alive</h3><p>Time
 to keep waiting threads alive. Defaults to "1 m" (one minute).</p><h3 
id="ParallelExecution-tapestry.thread-pool.queue-size">tapestry.thread-pool.queue-size</h3><p>
 
 </p><div class="confluence-information-macro 
confluence-information-macro-information"><p class="title">Added in 
5.3</p><span class="aui-icon aui-icon-small aui-iconfont-info 
confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body">
 </div></div>

Modified: websites/production/tapestry/content/parameter-type-coercion.html
==============================================================================
--- websites/production/tapestry/content/parameter-type-coercion.html (original)
+++ websites/production/tapestry/content/parameter-type-coercion.html Wed Sep 
20 12:29:16 2017
@@ -27,6 +27,14 @@
       </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>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -36,26 +44,13 @@
 
   <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">Parameter Type Coercion</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">Parameter Type Coercion</h1></div></div>
       <div class="clearer"></div>
       </div>
 
@@ -67,7 +62,44 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p><strong style="text-align: 
justify;">Type Coercion</strong><span style="color: rgb(0,0,0);">&#160;is the 
conversion of one type of object to a new object of a different type with 
similar content. Tapestry frequently must coerce objects from one type to 
another. A common example is the coercion of a string into an integer or a 
double.</span></p><p>See&#160;<a  href="type-coercion.html">Type Coercer 
Service</a> for the list of build-in coercions.</p><h2 
id="ParameterTypeCoercion-ParameterTypeCoercions">Parameter Type 
Coercions</h2><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 ("coercion","parameters") 
and space = currentSpace()</parame
 ter></rich-text-body><p>Tapestry automatically handles type coercions for <a  
href="component-parameters.html">component parameters</a>.</p><p>Type coercions 
occur when a value passed into a parameter (as bound in a template or in an 
annotation) does not match the type of the parameter.</p><p>For example, 
consider the Count component:</p><parameter 
ac:name="language">java</parameter><plain-text-body>public class Count
+                <div id="ConfluenceContent"><p><strong style="text-align: 
justify;">Type Coercion</strong><span style="color: rgb(0,0,0);">&#160;is the 
conversion of one type of object to a new object of a different type with 
similar content. Tapestry frequently must coerce objects from one type to 
another. A common example is the coercion of a string into an integer or a 
double.</span></p><p>See&#160;<a  href="type-coercion.html">Type Coercer 
Service</a> for the list of build-in coercions.</p><h2 
id="ParameterTypeCoercion-ParameterTypeCoercions">Parameter Type 
Coercions</h2><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="type-coercion.html">Type Coercion</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="parameter-type-coercion.html">Parameter Type Coercion</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="enum-parameter-recipe.html">Enum Parameter Recipe</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="supporting-informal-parameters.html">Supporting Informal 
Parameters</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="default-parameter.html">Default Parameter</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-parameters.html">Component Parameters</a> 
+  </div> </li></ul></div><p>Tapestry automatically handles type coercions for 
<a  href="component-parameters.html">component parameters</a>.</p><p>Type 
coercions occur when a value passed into a parameter (as bound in a template or 
in an annotation) does not match the type of the parameter.</p><p>For example, 
consider the Count component:</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 class Count
 {
     @Parameter
     private int start = 1;
@@ -79,8 +111,11 @@
     private int value;
     
     . . .
-</plain-text-body><p>Here, the type of all three parameters is 
<code>int</code>.</p><p>However, it is likely that the component will be used 
as so:</p><parameter ac:name="language">java</parameter><plain-text-body>  
Merry Christmas: &lt;t:count end="3"&gt; Ho! &lt;/t:count&gt;
-</plain-text-body><p>A bare whole number is interpreted by the prop binding 
prefix as a <code>long</code>. So this is the <em>long</em> value 
3.</p><p>Tapestry will automatically coerce the bound value, a 
<code>long</code>, to the parameter's type, <code>int</code>. This may be a 
lossy coercion (if the <code>long</code> represents a number larger than can be 
stored in an <code>int</code>).</p><h2 
id="ParameterTypeCoercion-TypeCoercerService">TypeCoercer Service</h2><p>Main 
Article: <a  href="type-coercion.html">Type Coercion</a></p><p>The TypeCoercer 
service is responsible for this type coercion. This service is part of the <a  
href="ioc.html">tapestry-ioc</a> module. The service is quite extensible, 
allowing for new types and coercions to be added easily. The TapestryModule 
contributes a few additional coercions into the TypeCoercer service.</p></div>
+</pre>
+</div></div><p>Here, the type of all three parameters is 
<code>int</code>.</p><p>However, it is likely that the component will be used 
as so:</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;">  Merry Christmas: &lt;t:count end="3"&gt; Ho! 
&lt;/t:count&gt;
+</pre>
+</div></div><p>A bare whole number is interpreted by the prop binding prefix 
as a <code>long</code>. So this is the <em>long</em> value 3.</p><p>Tapestry 
will automatically coerce the bound value, a <code>long</code>, to the 
parameter's type, <code>int</code>. This may be a lossy coercion (if the 
<code>long</code> represents a number larger than can be stored in an 
<code>int</code>).</p><h2 
id="ParameterTypeCoercion-TypeCoercerService">TypeCoercer Service</h2><p>Main 
Article: <a  href="type-coercion.html">Type Coercion</a></p><p>The TypeCoercer 
service is responsible for this type coercion. This service is part of the <a  
href="ioc.html">tapestry-ioc</a> module. The service is quite extensible, 
allowing for new types and coercions to be added easily. The TapestryModule 
contributes a few additional coercions into the TypeCoercer service.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/performance-and-clustering.html
==============================================================================
--- websites/production/tapestry/content/performance-and-clustering.html 
(original)
+++ websites/production/tapestry/content/performance-and-clustering.html Wed 
Sep 20 12:29:16 2017
@@ -36,26 +36,13 @@
 
   <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">Performance and Clustering</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">Performance and Clustering</h1></div></div>
       <div class="clearer"></div>
       </div>
 
@@ -67,7 +54,51 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>Tapestry has a great 
<strong>performance</strong> story to tell. It's designed to take advantage of 
the speed of the modern JVM: no reflection, built to support a high level of 
concurrency without contention, and clean, lightweight code paths. In addition, 
there is built-in integrated GZIP content compression, far-future expires 
headers on static resources, JavaScript aggregation and minification, and an 
intentionally lightweight use of the HTTPSession. The result is a blistering 
fast framework. See <a  class="external-link" 
href="http://tapestry.apache.org/2011/06/13/tapestrys-performance-tested.html";>Tapestry's
 Performance Tested</a> for some objective numbers.</p><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><paramete
 r ac:name="title">Related Articles</parameter><parameter ac:name="cql">label = 
"persistence" and space = currentSpace()</parameter></rich-text-body><h2 
id="PerformanceandClustering-PerformanceTips">Performance Tips</h2><p>But even 
with all of Tapestry's built-in speediness, to really get top performance 
you'll need to be sure you're not hamstringing Tapestry. As a start, use the 
following checklist:</p><ul><li>Ensure (be absolutely sure) that <a  
href="configuration.html">Production Mode</a> is turned on in 
production.</li><li>Minimize the use of the HTTPSession (see below), especially 
if you're using clustering.</li><li>Set <a  
href="configuration.html">tapestry.clustered-sessions</a> to "false" if you 
aren't using clustering.</li><li>Organize your JavaScript files into <a  
href="legacy-javascript.html">JavaScriptStacks</a>.</li><li>Ensure that your 
static resources (images, CSS, JavaScript) are being cached by the 
browser.<ul><li>Use "asset:" or "context:" <a  href="component-para
 meters.html">binding prefixes</a> for all links to static resources (images, 
CSS, JavaScript).</li><li>Make sure that your firewall, proxy server, load 
balancer, front-end web servers, and app servers all allow caching of static 
resources.</li><li>Ensure "cache-control" and "vary" HTTP headers are set 
correctly for your static resources.</li><li>Use a client-based tool (like 
Firebug) to examine the requests that your browser makes as you navigate 
through the site. You should <em>not</em> see repeated requests for static 
resources.</li></ul></li><li>Consider using a <a  class="external-link" 
href="http://en.wikipedia.org/wiki/Content_delivery_network"; 
rel="nofollow">Content Delivery Network</a> for static parts of your 
site.</li></ul><p>After all of the above issues are addressed, if you still 
have performance problems, they probably aren't related to Tapestry.</p><h2 
id="PerformanceandClustering-ClusteringversusStickySessions">Clustering versus 
Sticky Sessions</h2><p>For web applica
 tions, <strong>clustering</strong> is a load-balancing technique in which 
multiple application servers are set up to behave as one big server. Generally 
this requires replicating HttpSession data across the servers, to ensure that a 
user's web interactions will continue without interruption regardless of which 
server handles the next request. Session replication achieves very high 
reliability, but it incurs an extra performance cost (due to the serializing 
and deserializing of session data and the extra network traffic 
required).</p><p>In contrast, <strong>Sticky Sessions</strong> (also called 
<em>session persistence</em> or <em>sticky persistence</em>) is a load 
balancing technique in which each session is assigned to a particular server 
for the duration of the session. This approach doesn't require copying 
HTTPSession data between servers, so it's very scalable. But if a server goes 
down, all of its sessions are lost.</p><p>In general, the sticky sessions 
approach is the way to go
  when possible (that is, when performance is more important than session 
survival). It represents a much more efficient use of resources ... you are 
scaling <em>out</em> not <em>up</em>, which is always cheaper. It also means 
that you don't have to be as careful about what goes into the 
HTTPSession.</p><p><em>For details on setting up clustering and sticky 
sessions, see the documentation of whatever load balancer you are 
using.</em></p><h2 
id="PerformanceandClustering-Clustering">Clustering</h2><p>Tapestry is designed 
to be "a good citizen" of an application server that supports clustering. It is 
careful about what it writes into the HttpSession. The framework understands 
that the server that receives a request may not be the same one that rendered 
the page initially; this knowledge affects many code paths, and it guides the 
approach Tapestry takes to caching page and component properties.</p><p>Your 
part is to properly manage the objects put into the HttpSession (via 
@SessionAttrib
 ute, @SessionState or @Persist; see <a  href="session-storage.html">Session 
Storage</a>):</p><ul><li>Don't store anything in the session that you don't 
have to. Principally this means minimizing the use of @Persist (see <a  
href="page-navigation.html">Page Activation</a> and <a  
href="using-select-with-a-list.html">Using Select With a List</a>), storing 
only IDs in the session rather than whole entities.</li><li>Where possible, 
persist only objects that are immutable (i.e., String, or a primitive or 
wrapper type).</li><li>Only put <em>serializable</em> objects into the 
session.</li><li>Make use of the @ImmutableSessionPersistedObject annotation 
and OptimizedSessionPersistedObject interface (both described 
below).</li></ul><p>Again, Tapestry is a good citizen, but from the application 
server's point of view, it's just another servlet application. The heavy 
lifting here is application server specific.</p><p><parameter ac:name=""><a  
href="clustering-issues.html">Clustering Issues</a><
 /parameter></p></div>
+                <div id="ConfluenceContent"><p>Tapestry has a great 
<strong>performance</strong> story to tell. It's designed to take advantage of 
the speed of the modern JVM: no reflection, built to support a high level of 
concurrency without contention, and clean, lightweight code paths. In addition, 
there is built-in integrated GZIP content compression, far-future expires 
headers on static resources, JavaScript aggregation and minification, and an 
intentionally lightweight use of the HTTPSession. The result is a blistering 
fast framework. See <a  class="external-link" 
href="http://tapestry.apache.org/2011/06/13/tapestrys-performance-tested.html";>Tapestry's
 Performance Tested</a> for some objective numbers.</p><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="performance-and-clustering.html">Performance and Clustering</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="session-storage.html">Session Storage</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="persistent-page-data.html">Persistent Page Data</a> 
+  </div> </li></ul></div><h2 
id="PerformanceandClustering-PerformanceTips">Performance Tips</h2><p>But even 
with all of Tapestry's built-in speediness, to really get top performance 
you'll need to be sure you're not hamstringing Tapestry. As a start, use the 
following checklist:</p><ul><li>Ensure (be absolutely sure) that <a  
href="configuration.html">Production Mode</a> is turned on in 
production.</li><li>Minimize the use of the HTTPSession (see below), especially 
if you're using clustering.</li><li>Set <a  
href="configuration.html">tapestry.clustered-sessions</a> to "false" if you 
aren't using clustering.</li><li>Organize your JavaScript files into <a  
href="legacy-javascript.html">JavaScriptStacks</a>.</li><li>Ensure that your 
static resources (images, CSS, JavaScript) are being cached by the 
browser.<ul><li>Use "asset:" or "context:" <a  
href="component-parameters.html">binding prefixes</a> for all links to static 
resources (images, CSS, JavaScript).</li><li>Make sure that your 
 firewall, proxy server, load balancer, front-end web servers, and app servers 
all allow caching of static resources.</li><li>Ensure "cache-control" and 
"vary" HTTP headers are set correctly for your static resources.</li><li>Use a 
client-based tool (like Firebug) to examine the requests that your browser 
makes as you navigate through the site. You should <em>not</em> see repeated 
requests for static resources.</li></ul></li><li>Consider using a <a  
class="external-link" 
href="http://en.wikipedia.org/wiki/Content_delivery_network"; 
rel="nofollow">Content Delivery Network</a> for static parts of your 
site.</li></ul><p>After all of the above issues are addressed, if you still 
have performance problems, they probably aren't related to Tapestry.</p><h2 
id="PerformanceandClustering-ClusteringversusStickySessions">Clustering versus 
Sticky Sessions</h2><p>For web applications, <strong>clustering</strong> is a 
load-balancing technique in which multiple application servers are set up to 
behave
  as one big server. Generally this requires replicating HttpSession data 
across the servers, to ensure that a user's web interactions will continue 
without interruption regardless of which server handles the next request. 
Session replication achieves very high reliability, but it incurs an extra 
performance cost (due to the serializing and deserializing of session data and 
the extra network traffic required).</p><p>In contrast, <strong>Sticky 
Sessions</strong> (also called <em>session persistence</em> or <em>sticky 
persistence</em>) is a load balancing technique in which each session is 
assigned to a particular server for the duration of the session. This approach 
doesn't require copying HTTPSession data between servers, so it's very 
scalable. But if a server goes down, all of its sessions are lost.</p><p>In 
general, the sticky sessions approach is the way to go when possible (that is, 
when performance is more important than session survival). It represents a much 
more efficient use
  of resources ... you are scaling <em>out</em> not <em>up</em>, which is 
always cheaper. It also means that you don't have to be as careful about what 
goes into the HTTPSession.</p><p><em>For details on setting up clustering and 
sticky sessions, see the documentation of whatever load balancer you are 
using.</em></p><h2 
id="PerformanceandClustering-Clustering">Clustering</h2><p>Tapestry is designed 
to be "a good citizen" of an application server that supports clustering. It is 
careful about what it writes into the HttpSession. The framework understands 
that the server that receives a request may not be the same one that rendered 
the page initially; this knowledge affects many code paths, and it guides the 
approach Tapestry takes to caching page and component properties.</p><p>Your 
part is to properly manage the objects put into the HttpSession (via 
@SessionAttribute, @SessionState or @Persist; see <a  
href="session-storage.html">Session Storage</a>):</p><ul><li>Don't store 
anything i
 n the session that you don't have to. Principally this means minimizing the 
use of @Persist (see <a  href="page-navigation.html">Page Activation</a> and <a 
 href="using-select-with-a-list.html">Using Select With a List</a>), storing 
only IDs in the session rather than whole entities.</li><li>Where possible, 
persist only objects that are immutable (i.e., String, or a primitive or 
wrapper type).</li><li>Only put <em>serializable</em> objects into the 
session.</li><li>Make use of the @ImmutableSessionPersistedObject annotation 
and OptimizedSessionPersistedObject interface (both described 
below).</li></ul><p>Again, Tapestry is a good citizen, but from the application 
server's point of view, it's just another servlet application. The heavy 
lifting here is application server specific.</p><p></p><h2 
id="PerformanceandClustering-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="PerformanceandClustering-@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="PerformanceandClustering-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="PerformanceandClustering-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>
 
       <div class="clearer"></div>


Reply via email to