You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by bu...@apache.org on 2018/02/18 16:20:17 UTC

svn commit: r1025561 - in /websites/production/tapestry/content: cache/main.pageCache configuration.html content-type-and-markup.html https.html persistent-page-data.html response-compression.html security.html session-storage.html

Author: buildbot
Date: Sun Feb 18 16:20:17 2018
New Revision: 1025561

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    websites/production/tapestry/content/configuration.html
    websites/production/tapestry/content/content-type-and-markup.html
    websites/production/tapestry/content/https.html
    websites/production/tapestry/content/persistent-page-data.html
    websites/production/tapestry/content/response-compression.html
    websites/production/tapestry/content/security.html
    websites/production/tapestry/content/session-storage.html

Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/tapestry/content/configuration.html
==============================================================================
--- websites/production/tapestry/content/configuration.html (original)
+++ websites/production/tapestry/content/configuration.html Sun Feb 18 16:20:17 2018
@@ -147,11 +147,11 @@
 
 
 <h1 id="Configuration-ConfiguringTapestry">Configuring Tapestry</h1><p>This page discusses all the ways in which Tapestry can be configured. Tapestry applications are configured almost entirely using Java, with very little XML at all.</p><p><strong>Contents</strong></p><p><style type="text/css">/*<![CDATA[*/
-div.rbtoc1518967168018 {padding: 0px;}
-div.rbtoc1518967168018 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1518967168018 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1518970800044 {padding: 0px;}
+div.rbtoc1518970800044 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1518970800044 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style></p><div class="toc-macro rbtoc1518967168018">
+/*]]>*/</style></p><div class="toc-macro rbtoc1518970800044">
 <ul class="toc-indentation"><li><a  href="#Configuration-XMLconfiguration(web.xml)">XML configuration (web.xml)</a></li><li><a  href="#Configuration-YourApplication'sModuleClass">Your Application's Module Class</a></li><li><a  href="#Configuration-ConfigurationSymbolNames">Configuration Symbol Names</a></li><li><a  href="#Configuration-SettingComponentParameterDefaults">Setting Component Parameter Defaults</a></li><li><a  href="#Configuration-ConfiguringIgnoredPaths">Configuring Ignored Paths</a></li><li><a  href="#Configuration-ConfiguringContentTypeMapping">Configuring Content Type Mapping</a></li><li><a  href="#Configuration-SettingExecutionModes">Setting Execution Modes</a></li></ul>
 </div><h2 id="Configuration-XMLconfiguration(web.xml)">XML configuration (web.xml)</h2><p>Tapestry runs on top of the standard Java Servlet API. To the servlet container, such as Tomcat, Tapestry appears as a <em>servlet filter</em>. This gives Tapestry great flexibility in matching URLs without requiring lots of XML configuration.</p><p>Although most configuration is done with Java, a small but necessary amount of configuration occurs inside the servlet deployment descriptor, WEB-INF/web.xml. Most of the configuration is boilerplate, nearly the same for all applications.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>web.xml (partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;!DOCTYPE web-app
@@ -410,7 +410,7 @@ Added in 5.4
 </p><div class="aui-message aui-message-info">
 Added in 5.4 
    &#160;
-</div><strong>SymbolConstants.RESTRICTIVE_ENVIRONMENT</strong>&#160;&#8211; A flag (true or false) that, if true, changes some default Tapestry behavior to make it work better in restrictive environments such as&#160;<a  href="google-app-engine.html">Google App Engine</a> (GAE). Specifically, if true, then OperationsTracker writes its exception report files into a single folder (specified by the tapestry.exception-reports-dir symbol, above) rather than creating dated sub-folders under that path, and ResourceTransformerFactory avoids creating a cache folder for resources.<h3 id="Configuration-tapestry.secure-enabled">tapestry.secure-enabled</h3><p><strong>SymbolConstants.SECURE_ENABLED</strong>&#160;&#8211; If true, then @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Secure.html">Secure</a> annotations are honored; if false, no security checks or redirects take place. This defaults to tapestry.production-mode, meaning that
  in development mode it will (by default) be disabled. See&#160;<a  href="https.html">HTTPS</a> for details.</p><h3 id="Configuration-tapestry.secure-page">tapestry.secure-page</h3><p><strong>MetaDataConstants.SECURE_PAGE</strong>&#160;&#8211; If true, then the page may only be accessed via HTTPS. The @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Secure.html">Secure</a> annotation will set this value to true. This symbol is the default for all pages; set it to "true" to force the entire application to be secure. See&#160;<a  href="https.html">HTTPS</a> for details.</p><h3 id="Configuration-tapestry.service-reloading-enabled">tapestry.service-reloading-enabled</h3>
+</div><strong>SymbolConstants.RESTRICTIVE_ENVIRONMENT</strong>&#160;&#8211; A flag (true or false) that, if true, changes some default Tapestry behavior to make it work better in restrictive environments such as&#160;<a  href="google-app-engine.html">Google App Engine</a> (GAE). Specifically, if true, then OperationsTracker writes its exception report files into a single folder (specified by the tapestry.exception-reports-dir symbol, above) rather than creating dated sub-folders under that path, and ResourceTransformerFactory avoids creating a cache folder for resources.<h3 id="Configuration-tapestry.secure-enabled">tapestry.secure-enabled</h3><p><strong>SymbolConstants.SECURE_ENABLED</strong>&#160;&#8211; If true, then @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Secure.html">Secure</a> annotations are honored; if false, no security checks or redirects take place. This defaults to tapestry.production-mode, meaning that
  in development mode it will (by default) be disabled. However, sites that are intended to be served <em>only</em> under HTTPS should set this to&#160;<strong><code>false</code></strong>. See&#160;<a  href="https.html">HTTPS</a> for details.</p><h3 id="Configuration-tapestry.secure-page">tapestry.secure-page</h3><p><strong>MetaDataConstants.SECURE_PAGE</strong>&#160;&#8211; If true, then the page may only be accessed via HTTPS. The @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Secure.html">Secure</a> annotation will set this value to true. This symbol is the default for all pages; set it to "true" to force the entire application to be secure. See&#160;<a  href="https.html">HTTPS</a> for details.</p><h3 id="Configuration-tapestry.service-reloading-enabled">tapestry.service-reloading-enabled</h3>
 
 
 

Modified: websites/production/tapestry/content/content-type-and-markup.html
==============================================================================
--- websites/production/tapestry/content/content-type-and-markup.html (original)
+++ websites/production/tapestry/content/content-type-and-markup.html Sun Feb 18 16:20:17 2018
@@ -67,7 +67,7 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>Tapestry reads <a  href="content-type-and-markup.html">well-formed XML template files</a> and renders its output as XML, with minor caveats:</p><ul><li>The &lt;?xml?&gt; XML declaration is omitted.</li><li>Most elements render with an open and close tag, even if empty.</li><li>Certain elements will be abbreviated to just the open tag, if empty:<ul><li>br</li><li>hr</li><li>img</li></ul></li><li>&lt;![CDATA[]&gt; sections are <strong>not</strong> used</li></ul><p>This is all to ensure that the markup stream, while (almost) well formed, is still properly understood by browsers expecting ordinary HTML. In fact, Tapestry may decide to render a purely XML document; it depends on the content type of the response.</p><p>When Tapestry renders a page, the output content type and charset is obtained from meta data on the page itself. Meta data is specified using the <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/ap
 ache/tapestry5/annotations/Meta.html">@Meta</a> annotation.</p><h3 id="ContentTypeandMarkup-ContentType">Content Type</h3><p>The response content type is obtained via meta-data key <code>tapestry.response-content-type</code>. This value defaults to "text/html", which triggers specialized XML rendering.</p><p>A page may declare its content type using the @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ContentType.html">ContentType</a> class annotation. Content types other than "text/html" will render as well-formed XML documents, including the XML declaration, and more standard behavior for empty elements.</p><h3 id="ContentTypeandMarkup-CharacterSet">Character Set</h3><p>The character set (aka character encoding) used when writing output and when parsing requests is normally "utf-8". UTF-8 is a version of Unicode where individual characters are encoded as one or more bytes. Most western language characters (that is, typica
 l ASCII characters) are encoded in a single byte. Accented characters or non-western characters (such as Japanese, Arabic, etc.) may be encoded as two or more bytes.</p><p>All pages use the same encoding, which can be set using the <code>tapestry.charset</code> <a  href="content-type-and-markup.html">configuration setting</a>.</p></div>
+                <div id="ConfluenceContent"><p>Tapestry reads <a  href="component-templates.html">well-formed XML template files</a> and renders its output as XML, with minor caveats:</p><ul><li>The &lt;?xml?&gt; XML declaration is omitted.</li><li>Most elements render with an open and close tag, even if empty.</li><li>Certain elements will be abbreviated to just the open tag, if empty:<ul><li>br</li><li>hr</li><li>img</li></ul></li><li>&lt;![CDATA[]&gt; sections are <strong>not</strong> used</li></ul><p>This is all to ensure that the markup stream, while (almost) well formed, is still properly understood by browsers expecting ordinary HTML. In fact, Tapestry may decide to render a purely XML document; it depends on the content type of the response.</p><p>When Tapestry renders a page, the output content type and charset is obtained from meta data on the page itself. Meta data is specified using the <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache
 /tapestry5/annotations/Meta.html">@Meta</a> annotation.</p><h3 id="ContentTypeandMarkup-ContentType">Content Type</h3><p>The response content type is obtained via meta-data key <code>tapestry.response-content-type</code>. This value defaults to "text/html", which triggers specialized XML rendering.</p><p>A page may declare its content type using the @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ContentType.html">ContentType</a> class annotation. Content types other than "text/html" will render as well-formed XML documents, including the XML declaration, and more standard behavior for empty elements.</p><h3 id="ContentTypeandMarkup-CharacterSet">Character Set</h3><p>The character set (aka character encoding) used when writing output and when parsing requests is normally "utf-8". UTF-8 is a version of Unicode where individual characters are encoded as one to four 8-bit bytes. Most western language characters (that is, typi
 cal ASCII characters) are encoded in a single byte. Accented characters or non-western characters (such as Japanese, Arabic, etc.) may be encoded as two or more bytes.</p><p>In Tapestry, all pages use the same encoding. The default is "UTF-8", but this can be changed using the <a  href="configuration.html">tapestry.charset configuration symbol</a>.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/https.html
==============================================================================
--- websites/production/tapestry/content/https.html (original)
+++ websites/production/tapestry/content/https.html Sun Feb 18 16:20:17 2018
@@ -75,7 +75,7 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><h1 id="HTTPS-SecuringyourapplicationwithHTTPS">Securing your application with HTTPS</h1><div class="aui-label" style="float:right" title="Related Articles">
+                <div id="ConfluenceContent"><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 page describes Tapestry's mechanism for automatically switching between HTTP and HTTPS URLs. With the <a  class="external-link" href="https://en.wikipedia.org/wiki/HTTPS" rel="nofollow">recent trend</a> to have all web sites use HTTPS, you will likely want to disable this behavior. To do so, set the <a  href="configuration.html">tapestry.secure-enabled</a> configuration symbol to <em>false</em> (counter-intuitively).</p></div></div><p>By default, Tapestry assumes your application will be primarily deployed as a standard web application, using HTTP&#160;(not HTTPS) as the primary protocol.</p><div class="aui-label" style="float:right; margin: 1em" title="Related Articles">
 
 
 
@@ -117,26 +117,26 @@
 </div>
 
 
-<p>Tapestry assumes your application will be primarily deployed as a standard web application, using HTTP&#160;(not HTTPS) as the transport mechanism.</p><p>However, many applications will need to have some of their pages secured: only accessible via HTTPS. This could be a login page, or a product ordering wizard, or administrative pages.</p><p>All that is necessary to mark a page as secure is to add the @Secure annotation to the page class:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<p>Many applications will need to have some of their pages secured: only accessible via HTTPS. This could be a login page, or a product ordering wizard, or administrative pages.</p><p>All that is necessary to mark a page as secure is to add the @Secure annotation to the page class:</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;">@Secure
 public class ProcessOrder
 {
   . . .
 }
 </pre>
-</div></div><p>When a page is marked as secure, Tapestry will ensure that access to that page uses HTTPS. All links to the page will use the "https" protocol.</p><p>If an attempt is made to access a secure page using a non-secure request (a normal HTTP request), Tapestry will send an HTTPS redirect to the client.</p><p>Links to non-secure pages from a secure page will do the reverse: a complete URL with an "http" protocol will be used. In other words, Tapestry manages the transition from insecure to secure and back again.</p><p>Links to other (secure) pages <em>and to assets</em> will be based on relative URLs and, therefore, secure.</p><p>The rationale behind using secure links to assets from secure pages is that it prevents the client web browser from reporting a mixed security level.</p><h2 id="HTTPS-SecuringMultiplePages">Securing Multiple Pages</h2><p>Rather than placing an @Secure annotation on individual pages, it is possible to enable security for folders of pages. All pages
  in or beneath the folder will be secured.</p><p>This is accomplished by making a contribution to the MetaDataLocator service configuration. For example, to secure all pages in the "admin" folder:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>When a page is marked as secure, Tapestry will ensure that access to that page uses HTTPS. All links to the page will use the "https" protocol.</p><p>If an attempt is made to access a secure page using a non-secure request (a normal HTTP request), Tapestry will send an HTTPS redirect to the client.</p><p>Links to non-secure pages from a secure page will do the reverse: a complete URL with an "http" protocol will be used. In other words, Tapestry manages the transition from insecure to secure and back again.</p><p>Links to other (secure) pages <em>and to assets</em> will be based on relative URLs and, therefore, secure.</p><p>The rationale behind using secure links to assets from secure pages is that it prevents the client web browser from reporting a mixed security level.</p><h2 id="HTTPS-SecuringMultiplePages">Securing Multiple Pages</h2><p>Rather than placing an @Secure annotation on individual pages, it is possible to enable https URL redirecting for entire folders
  of pages. All pages in or beneath the folder will be secured.</p><p>This is accomplished by making a contribution to the MetaDataLocator service configuration. For example, to secure all pages in the "admin" folder:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public void contributeMetaDataLocator(MappedConfiguration&lt;String,String&gt; configuration)
 {
     configuration.add("admin:" + MetaDataConstants.SECURE_PAGE, "true");
 }
 </pre>
-</div></div><p>Here "admin" is the folder name, and the colon is a separator between the folder name and the the meta data key. SECURE_PAGE is a public constant for value "tapestry.secure-page";</p><p>When Tapestry is determining if a page is secure or not, it starts by checking for the @Secure annotation, then it consults the MetaDataLocator service.</p><p>If you want to make your entire application secure:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>Here "admin" is the folder name, and the colon is a separator between the folder name and the the meta data key. SECURE_PAGE is a public constant for value "tapestry.secure-page";</p><p>When Tapestry is determining if a page is secure or not, it starts by checking for the @Secure annotation, then it consults the MetaDataLocator service.</p><p>If you want to make your entire application secure:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public void contributeMetaDataLocator(MappedConfiguration&lt;String,String&gt; configuration)
 {
     configuration.add(MetaDataConstants.SECURE_PAGE, "true");
 }
 </pre>
-</div></div><p>With no colon, the meta data applies to the entire application (including any component libraries used in the application).</p><h2 id="HTTPS-BaseURLSupport">Base URL Support</h2><p>When Tapestry switches back and forth between secure and unsecure mode, it must create a full URL (rather than a relative URL) that identifies the protocol, server host name and perhaps even a port number.</p><p>That can be a stumbling point, especially the server host name. In a cluster, behind a fire wall, the server host name available to Tapestry, via the <code>HttpServletRequest.getServerName()</code> method, is often <em>not</em> the server name the client web browser sees ... instead it is the name of the internal server behind the firewall. The firewall server has the correct name from the web browser's point of view.</p><p>Because of this, Tapestry includes a hook to allow you to override how these default URLs are created: the BaseURLSource service.</p><p>The default implementatio
 n is based on just the getServerName() method; it's often not the correct choice even for development.</p><p>Fortunately, it is very easy to override this implementation. Here's an example of an override that uses the default port numbers that the <a  class="external-link" href="http://www.eclipse.org/jetty/" rel="nofollow">Jetty servlet container</a> uses for normal HTTP (port 8080) and for secure HTTPS (port 8443):</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>With no colon, the meta data applies to the entire application (including any component libraries used in the application).</p><h2 id="HTTPS-BaseURLSupport">Base URL Support</h2><p>When Tapestry switches back and forth between secure and unsecure mode, it must create a full URL (rather than a relative URL) that identifies the protocol, server host name and perhaps even a port number.</p><p>That can be a stumbling point, especially the server host name. In a cluster, behind a fire wall, the server host name available to Tapestry, via the <code>HttpServletRequest.getServerName()</code> method, is often <em>not</em> the server name the client web browser sees ... instead it is the name of the internal server behind the firewall. The firewall server has the correct name from the web browser's point of view.</p><p>Because of this, Tapestry includes a hook to allow you to override how these default URLs are created: the BaseURLSource service.</p><p>The default implementatio
 n is based on just the getServerName() method; it's often not the correct choice even for development.</p><p>Fortunately, it is very easy to override this implementation. Here's an example of an override that uses the default port numbers that the <a  class="external-link" href="http://www.eclipse.org/jetty/" rel="nofollow">Jetty servlet container</a> uses for normal HTTP (port 8080) and for secure HTTPS (port 8443):</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">    public static void contributeServiceOverride(MappedConfiguration&lt;Class,Object&gt; configuration)
     {
         BaseURLSource source = new BaseURLSource()
@@ -154,7 +154,7 @@ public class ProcessOrder
         configuration.add(BaseURLSource.class, source);
     }
 </pre>
-</div></div><p>This override is hardcoded to generate URLs for localhost; as such you might use it for development but certainly not in production.</p><h2 id="HTTPS-DevelopmentMode">Development Mode</h2><p>When working in development mode, the Secure annotation is ignored. This is controlled by the tapestry.secure-enabled <a  href="https.html">configuration symbol</a>.</p><h2 id="HTTPS-ApplicationServerConfiguration">Application Server Configuration</h2><p>Setting up HTTPS support varies from application server to application server.</p><ul><li>Jetty:<ul><li><a  class="external-link" href="https://wiki.eclipse.org/Jetty/Howto/Configure_SSL" rel="nofollow">Versions 7, 8 or 9</a></li></ul></li><li>Tomcat:<ul><li><a  class="external-link" href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html">Version 6.0</a></li><li><a  class="external-link" href="http://tomcat.apache.org/tomcat-5.5-doc/ssl-howto.html">Version 5.5</a></li></ul></li></ul></div>
+</div></div><p>This override is hardcoded to generate URLs for localhost; as such you might use it for development but certainly not in production.</p><h2 id="HTTPS-DevelopmentMode">Development Mode</h2><p>When working in development mode, the Secure annotation is ignored. This is controlled by the <a  href="configuration.html">tapestry.secure-enabled</a> configuration symbol.</p><h2 id="HTTPS-ApplicationServerConfiguration">Application Server Configuration</h2><p>Setting up HTTPS support varies from application server to application server.</p><ul><li>Jetty:<ul><li><a  class="external-link" href="http://www.eclipse.org/jetty/documentation/current/configuring-ssl.html" rel="nofollow">Versions 7, 8 or 9</a></li></ul></li><li>Tomcat:<ul><li><a  class="external-link" href="https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html">Tomcat 7</a></li><li><a  class="external-link" href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html">Version 6.0</a></li><li><a  class="external-link" 
 href="http://tomcat.apache.org/tomcat-5.5-doc/ssl-howto.html">Version 5.5</a></li></ul></li></ul><p>&#160;</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/persistent-page-data.html
==============================================================================
--- websites/production/tapestry/content/persistent-page-data.html (original)
+++ websites/production/tapestry/content/persistent-page-data.html Sun Feb 18 16:20:17 2018
@@ -119,7 +119,7 @@
 </div>
 
 
-<p>However, you often want to store some data on a <em>single</em> page, and have access to it in later requests to that same page, without having to store it in a database between requests. (To store values across multiple pages, see <a  href="persistent-page-data.html">Persistent Page Data</a>.)</p><p>Making page data persist across requests to a single page is accomplished with the @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html">Persist</a> annotation. This annotation is applied to private instance fields of components:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<p>However, you often want to store some data on a <em>single</em> page, and have access to it in later requests to that same page, without having to store it in a database between requests. (To store values across multiple pages, see <a  href="session-storage.html">Session Storage</a>.)</p><p>Making page data persist across requests to a single page is accomplished with the @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html">Persist</a> annotation. This annotation is applied to private instance fields of components:</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;">  @Persist
   private int value;
 </pre>
@@ -144,7 +144,7 @@
 </div></div><p>&#160;</p><p>The value stored in the HttpSession is a&#160;<em>token</em> for the entity: its Java class name and primary key. When the field is restored in a later request, the entity is re-instantiated using that data.</p><p>What is&#160;<em>not</em> stored is any changes to the persistent entity that are not committed to the external datastore (the database).</p><p>Starting in Tapestry 5.4, it is possible to store a non-persistent entity (a transient entity). A transient entity is stored directly into the HttpSession, and should be Serializable if the application is clustered.</p><h3 id="PersistentPageData-JPAEntityStrategy">JPA Entity Strategy</h3><p>The tapestry-jpa module uses a similar strategy. However, at the current time it can only store a persisted entity (one that has been saved to the database and has a primary key).</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>"Exa
 mple: JPA Entity Strategy"</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Persist(JpaPersistenceConstants.ENTITY)
   private Account account;</pre>
-</div></div><p><span style="color: rgb(83,145,38);">Persistence Strategy Inheritance</span></p><p>By default the value for the Persist annotation is the empty string. When this is true, then the actual strategy to be used is determined by a search up the component hierarchy.</p><p>For each component, the meta-data property <code>tapestry.persistence-strategy</code> is checked. This can be specified using the <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Meta.html">Meta</a> annotation.</p><p>If the value is non-blank, then that strategy is used. This allows a component to control the persistence strategy used inside any sub-components (that don't explicitly use a different strategy).</p><p>In any case, if no component provides the meta data, then the ultimate default, "session", is used.</p><h2 id="PersistentPageData-DefaultValues">Default Values</h2><p>Fields marked with @Persist may not have default values (whether set i
 nline, or inside a constructor).</p><h2 id="PersistentPageData-ClearingPersistentFields">Clearing Persistent Fields</h2><p>If you reach a point where you know that all data for a page can be discarded, you can do exactly that.</p><p>The method <code>discardPersistentFieldChanges()</code> of ComponentResources will discard all persistent fields for the page, regardless of which strategy is used to store the property. This will not affect the page in memory, but takes effect for subsequent requests.</p><p></p><h2 id="PersistentPageData-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 se
 ssion 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 o
 bject hasn't changed.</p><p>Tapestry has solutions to this, too:</p><h3 id="PersistentPageData-@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="PersistentPageData-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="PersistentPageData-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 class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Example: Entity Session Strategy</b></div
 ><div class="codeContent panelContent pdl">
+</div></div><h3 id="PersistentPageData-PersistenceStrategyInheritance"><span style="color: rgb(83,145,38);">Persistence Strategy Inheritance</span></h3><p>By default the value for the Persist annotation is the empty string. When this is true, then the actual strategy to be used is determined by a search up the component hierarchy.</p><p>For each component, the meta-data property <code>tapestry.persistence-strategy</code> is checked. This can be specified using the @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Meta.html">Meta</a> annotation.</p><p>If the value is non-blank, then that strategy is used. This allows a component to control the persistence strategy used inside any sub-components (that don't explicitly use a different strategy).</p><p>In any case, if no component provides the meta data, then the ultimate default, "session", is used.</p><h2 id="PersistentPageData-DefaultValues">Default Values</h2><p>Fields marke
 d with @Persist may not have default values (whether set inline, or inside a constructor).</p><h2 id="PersistentPageData-ClearingPersistentFields">Clearing Persistent Fields</h2><p>If you reach a point where you know that all data for a page can be discarded, you can do exactly that.</p><p>The method <code>discardPersistentFieldChanges()</code> of ComponentResources will discard all persistent fields for the page, regardless of which strategy is used to store the property. This will not affect the page in memory, but takes effect for subsequent requests.</p><p></p><h2 id="PersistentPageData-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 s
 ingle 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 re
 plicated needlessly if the internal state of the mutable object hasn't changed.</p><p>Tapestry has solutions to this, too:</p><h3 id="PersistentPageData-@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="PersistentPageData-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject Interface</h3><p>The <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/OptimizedSessionPersistedObject">OptimizedSessionPersistedObject</a> interface allo
 ws 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="PersistentPageData-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 class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom
 -width: 1px;"><b>Example: Entity Session Strategy</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Persist(HibernatePersistenceConstants.ENTITY)
   private User user;</pre>
 </div></div><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>"Example:JAP Session Strategy"</b></div><div class="codeContent panelContent pdl">

Modified: websites/production/tapestry/content/response-compression.html
==============================================================================
--- websites/production/tapestry/content/response-compression.html (original)
+++ websites/production/tapestry/content/response-compression.html Sun Feb 18 16:20:17 2018
@@ -109,7 +109,7 @@
 </div>
 
 
-<p>This directly applies to both rendered pages and streamed assets from the classpath.</p><p>Context assets will also be compressed ... but this requires referencing such assets using the "context:" binding prefix, so that generated URL is handled by Tapestry and not the servlet container.</p><h1 id="ResponseCompression-CompressionConfiguration">Compression Configuration</h1><p>Main Article: <a  href="response-compression.html">Response Compression</a></p><p>Small streams generally do not benefit from being compressed; there is overhead when using compression, not just the CPU time to compress the bytes, but a lot of overhead. For small responses, Tapestry does not attempt to compress the output stream.</p><p>The configuration symbol <code>tapestry.min-gzip-size</code> allows the cutoff to be set; it defaults to 100 bytes.</p><p>In addition, some file types are already compressed and should not be recompressed (they actually get larger, not smaller!). The service <a  class="externa
 l-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ResponseCompressionAnalyzer.html">ResponseCompressionAnalyzer</a>'s configuration is an unordered collection of content type strings that should <em>not</em> be compressed. The default content types are "image/jpeg".</p><h1 id="ResponseCompression-StreamResponse">StreamResponse</h1><p>When returning a <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/StreamResponse.html">StreamResponse</a> from a <a  href="response-compression.html">component event method</a>, the stream is totally under your control; it will not be compressed. You should use the ResponseCompressionAnalyzer service to determine if the client supports compression, and add a java.util.zip.GZIPOutputStream to your stream stack if compression is desired.</p></div>
+<p>This directly applies to both rendered pages and streamed assets from the CLASSPATH.</p><p>Context assets will also be compressed ... but this requires referencing such assets using the "context:" binding prefix, so that generated URL is handled by Tapestry and not the servlet container.</p><h1 id="ResponseCompression-CompressionConfiguration">Compression Configuration</h1><p>Small streams generally do not benefit from being compressed; there is overhead when using compression, not just the CPU time to compress the bytes, but a lot of overhead. For small responses, Tapestry does not attempt to compress the output stream.</p><p>The configuration symbol <a  href="configuration.html"><code>tapestry.min-gzip-size</code></a> allows the cutoff to be set; it defaults to 100 bytes.</p><p>In addition, some file types are already compressed and should not be re-compressed (they actually get larger, not smaller!). The service <a  class="external-link" href="http://tapestry.apache.org/curren
 t/apidocs/org/apache/tapestry5/services/ResponseCompressionAnalyzer.html">ResponseCompressionAnalyzer</a>'s configuration is an unordered collection of content type strings that should <em>not</em> be compressed. The default list of content types that are NOT compressed are:</p><ul><li>image/* (image/jpeg, image/png, image/gif, etc) <em>except</em> image/svg+xml, which is compressed</li><li>application/x-shockwave-flash</li><li>application/font-woff</li><li>application/x-font-ttf</li><li>application/vnd.ms-fontobj</li></ul><h1 id="ResponseCompression-StreamResponse">StreamResponse</h1><p>When returning a <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/StreamResponse.html">StreamResponse</a> from a <a  href="component-events.html">component event method</a>, the stream is totally under your control; it will not be compressed. You should use the ResponseCompressionAnalyzer service to determine if the client supports compression, and add 
 a java.util.zip.GZIPOutputStream to your stream stack if compression is desired.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/security.html
==============================================================================
--- websites/production/tapestry/content/security.html (original)
+++ websites/production/tapestry/content/security.html Sun Feb 18 16:20:17 2018
@@ -128,7 +128,7 @@
 </div>
 
 
-<p>&#160;</p><h2 id="Security-HTTPS-onlyPages">HTTPS-only Pages</h2><p>Main Article: <a  href="security.html">Security</a></p><p>Tapestry provides several annotations and configuration settings that you can use to&#160;<span>ensure that all access to certain pages (or all pages) occurs only via the encrypted HTTPS protocol</span><span>. See&#160;<a  href="security.html">Security</a> for details.</span></p><h2 id="Security-ControllingPageAccess"><span>Controlling Page Access</span></h2><p></p><div class="navmenu" style="float:right; background:#eee; margin:3px; padding:0 1em">
+<p>&#160;</p><h2 id="Security-HTTPS-onlyPages">HTTPS-only Pages</h2><p>Main Article: <a  href="https.html">HTTPS</a></p><p>Tapestry provides several annotations and configuration settings that you can use to&#160;<span>ensure that all access to certain pages (or all pages) occurs only via the encrypted HTTPS protocol</span><span>. See&#160;<a  href="https.html">HTTPS</a> for details.</span></p><h2 id="Security-ControllingPageAccess"><span>Controlling Page Access</span></h2><p></p><div class="navmenu" style="float:right; background:#eee; margin:3px; padding:0 1em">
 <p>    <strong>JumpStart Demo:</strong><br clear="none">
     <a  class="external-link" href="http://jumpstart.doublenegative.com.au/jumpstart/examples/infrastructure/protectingpages" rel="nofollow">Protecting Pages</a></p></div><span>For simple access control needs, you can contribute a&#160;<span><a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ComponentRequestFilter.html">ComponentRequestFilter</a> with your custom logic that decides which pages should be accessed by which users. The <a  class="external-link" href="https://tapestry-app.apache.org/hotels/">Tapestry Hotel Booking </a>app demonstrates this approach with an <code>@AnonymousAccess</code> annotation along with a ComponentRequestFilter named&#160;<code>AuthenticationFilter.java</code>. The filter enforces security by intercepting all requests to pages that don't have that annotation, and it redirects those requests to the login page. <a  class="external-link" href="http://jumpstart.doublenegative.com.au/jumpstart/examples
 /infrastructure/protectingpages" rel="nofollow">JumpStart</a> has a similar demo.<br clear="none"></span></span><p><span>For more advanced needs see the Security Framework Integration section below.</span></p><h2 id="Security-White-listedPages">White-listed Pages</h2><p>Pages whose component classes are annotated with&#160;@<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/WhitelistAccessOnly.html">WhitelistAccessOnly</a>&#160;will only be displayed to users (clients) that are on the&#160;<em>whitelist</em>. By default the whitelist consists only of clients whose fully-qualified domain name is "localhost" (or the IP address equivalent, 127.0.0.1 or 0:0:0:0:0:0:0:1),&#160;but you can customize this by contributing to the ClientWhitelist service&#160;in your application's module class (usually AppModule.java):</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-
 width: 1px;"><b>AppModule.java (partial) &#8211; simple inline example</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">    @Contribute(ClientWhitelist.class)
@@ -143,7 +143,7 @@
             }
         }, "before:*");
     }</pre>
-</div></div><p>&#160;</p><p>Sometimes, in production, a firewall or proxy may make it look like the client web browser originates from localhost, with the consequence that whitelisted pages may be visible to all users. See the&#160;<a  href="security.html">Security FAQ</a> for how to deal with this.</p><h2 id="Security-AssetSecurity">Asset Security</h2><p>Main Article:&#160;<a  href="security.html">Security</a></p><p>Tapestry serves assets (static content such as CSS files, images, and JavaScript, many of which are on the classpath alongside your compiled class files) to the client.&#160;Because of this, great care has gone into ensuring that certain file types cannot be served to the client. By default, file ending with ".class', ".tml" and ".properties" can be served to the client only if the request includes the file's MD5 checksum. As you would expect, that blacklist can be extended. See&#160;<a  href="security.html">Asset Security</a> for more information.</p><h2 id="Security-P
 rotectingSerializedObjectDataontheClient">Protecting Serialized Object Data on the Client</h2><p><span style="color: rgb(0,0,0);">As of version 5.3.6, Tapestry integrates a&#160;</span><a  class="external-link" href="http://en.wikipedia.org/wiki/HMAC" rel="nofollow" style="text-decoration: underline;text-align: justify;">hash-based message authentication code</a><span style="color: rgb(0,0,0);">&#160;(HMAC) into serialized Java object data that it sends to the client (generally, this means the&#160;</span><code style="text-align: justify;">t:formdata</code><span style="color: rgb(0,0,0);">&#160;hidden field used by the Form component). This ensures that the hidden binary object data is guaranteed to be unaltered when it returns to the server upon form (or AJAX) submission. The HMAC pass phrase is set using the&#160;<a  href="security.html">tapestry.hmac-passphrase</a> configuration symbol. If you don't set that value, you'll see a warning message in the browser, like this:&#160;</sp
 an></p><div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
+</div></div><p>&#160;</p><p>Sometimes, in production, a firewall or proxy may make it look like the client web browser originates from localhost, with the consequence that whitelisted pages may be visible to all users. See the&#160;<a  href="security-faq.html">Security FAQ</a> for how to deal with this.</p><h2 id="Security-AssetSecurity">Asset Security</h2><p>Main Article:&#160;<a  href="security.html">Security</a></p><p class="confluence-link">Tapestry serves assets (static content such as CSS files, images, and JavaScript, many of which are on the classpath alongside your compiled class files) to the client.&#160;Because of this, great care has gone into ensuring that certain file types cannot be served to the client. By default, file ending with ".class', ".tml" and ".properties" can be served to the client only if the request includes the file's MD5 checksum. As you would expect, that blacklist can be extended. See <a  href="assets.html">Assets</a> for more information.</p><h2 i
 d="Security-ProtectingSerializedObjectDataontheClient">Protecting Serialized Object Data on the Client</h2><p><span style="color: rgb(0,0,0);">As of version 5.3.6, Tapestry integrates a&#160;</span><a  class="external-link" href="http://en.wikipedia.org/wiki/HMAC" rel="nofollow" style="text-decoration: underline;text-align: justify;">hash-based message authentication code</a><span style="color: rgb(0,0,0);">&#160;(HMAC) into serialized Java object data that it sends to the client (generally, this means the&#160;</span><code style="text-align: justify;">t:formdata</code><span style="color: rgb(0,0,0);">&#160;hidden field used by the Form component). This ensures that the hidden binary object data is guaranteed to be unaltered when it returns to the server upon form (or AJAX) submission. The HMAC pass phrase is set using the&#160;<a  href="configuration.html">tapestry.hmac-passphrase</a> configuration symbol. If you don't set that value, you'll see a warning message in the browser, li
 ke this:&#160;</span></p><div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
 <pre>The symbol 'tapestry.hmac-passphrase' has not been configured. This is used to configure hash-based message authentication of Tapestry data stored in forms, or in the URL. You application is less secure, and more vulnerable to denial-of-service attacks, when this symbol is not configured.</pre>
 </div></div><p><span style="color: rgb(0,0,0);">The solution is to set the tapestry.hmac-passphrase to some value (any fixed, private string, such as 30 to 40 random-looking characters, will do) in your application's module class (usually AppModule.java).</span></p><h2 id="Security-CrossSiteRequestForgery(CSRF)"><span style="color: rgb(83,145,38);">Cross Site Request Forgery (CSRF)</span></h2><p>Cross Site Request Forgery is a type of security vulnerability in which legitimate, authorized users may be made to unwittingly submit malicious requests to your web application.</p><p><a  class="external-link" href="https://github.com/porscheinformatik/tapestry-csrf-protection" rel="nofollow">Tapestry-csrf-protection</a>&#160;is a 3rd party module that has several features for preventing CSRF attacks. It protects all&#160;<span>component event handlers (event links, forms, etc.) by adding a&#160;</span><span>CSRF token to event links and adds a CSRF token as a hidden field to all forms.&#16
 0;</span><span>Tokens are generated on a per-session basis.</span></p><h2 id="Security-SecurityFrameworkIntegration"><span>Security Framework Integration</span></h2><p>Tapestry does not lock you into a specific authentication/authorization implementation. There are integration modules available for the more popular open source Java security frameworks. A popular choice among Tapestry users is <a  class="external-link" href="http://www.tynamo.org/tapestry-security+guide/" rel="nofollow">tapestry-security (based on Apache Shiro) from Tynamo.org</a>. It is always kept up-to-date with the latest Tapestry versions and offers several supporting security modules (e.g. <a  class="external-link" href="http://www.tynamo.org/tapestry-security-jpa+guide/" rel="nofollow">tapestry-security-jpa</a>, <a  class="external-link" href="http://www.tynamo.org/tynamo-federatedaccounts+guide/" rel="nofollow">tynamo-federatedaccounts</a>). There's also an <a  class="external-link" href="http://www.localhost
 .nu/java/tapestry-spring-security" rel="nofollow">integration module available for Spring Security</a> but lately, it hasn't kept up with the latest versions of Tapestry 5.</p><p>Additional information:</p><ul><li><a  class="external-link" href="http://www.tynamo.org/tynamo-federatedaccounts+guide/" rel="nofollow">Tynamo-federatedaccounts</a>&#160;<span style="color: rgb(0,0,0);">is an add-on to the&#160;</span><a  class="external-link" href="http://www.tynamo.org/tapestry-security+guide/" rel="nofollow">tapestry-security</a><span style="color: rgb(0,0,0);">&#160;module, providing federated (third-party) authentication with Facebook, Twitter or Google.</span></li></ul><ul><li><span>To include OpenID with Spring Security in your application, see the following Wiki entry:&#160;</span><a  class="external-link" href="http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId">http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId</a></li></ul><p>&#160;</p></div
 >
       </div>

Modified: websites/production/tapestry/content/session-storage.html
==============================================================================
--- websites/production/tapestry/content/session-storage.html (original)
+++ websites/production/tapestry/content/session-storage.html Sun Feb 18 16:20:17 2018
@@ -119,14 +119,14 @@
 </div>
 
 
-<p>Ordinary <a  href="session-storage.html">page-persistent fields</a> won't work for this, since persistent fields are available only to a specific page, not shared across multiple pages.</p><p>Tapestry provides two mechanisms for storing such data: Session State Objects and Session Attributes. When deciding between the two, it's best to use Session State Objects for complex objects, and Session Attributes for simple types.</p><h2 id="SessionStorage-SessionStateObjects">Session State Objects</h2><p>With a Session State Object (SSO), the value is automatically stored outside the page; with the default storage strategy, it is stored in the session. Such a value is global to all pages <em>for the same user</em>, but is stored separately for different users.</p><p>A field holding an SSO is marked with the @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/SessionState.html">SessionState</a> annotation.</p><div class="navmenu" st
 yle="float:right; background:white; margin:3px; padding:3px">
+<p>Ordinary <a  href="persistent-page-data.html">page-persistent fields</a></p><p>won't work for this, since persistent fields are available only to a specific page, not shared across multiple pages.</p><p>Tapestry provides two mechanisms for storing such data: Session State Objects and Session Attributes. When deciding between the two, it's best to use Session State Objects for complex objects, and Session Attributes for simple types.</p><h2 id="SessionStorage-SessionStateObjects">Session State Objects</h2><p>With a Session State Object (SSO), the value is automatically stored outside the page; with the default storage strategy, it is stored in the session. Such a value is global to all pages <em>for the same user</em>, but is stored separately for different users.</p><p>A field holding an SSO is marked with the @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/SessionState.html">SessionState</a> annotation.</p><div class="
 navmenu" style="float:right; background:white; margin:3px; padding:3px">
 <div class="panel" style="border-width: 1px;"><div class="panelHeader" style="border-bottom-width: 1px;"><b>Contents</b></div><div class="panelContent">
 <style type="text/css">/*<![CDATA[*/
-div.rbtoc1518405712407 {padding: 0px;}
-div.rbtoc1518405712407 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1518405712407 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1518970798990 {padding: 0px;}
+div.rbtoc1518970798990 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1518970798990 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style><div class="toc-macro rbtoc1518405712407">
+/*]]>*/</style><div class="toc-macro rbtoc1518970798990">
 <ul class="toc-indentation"><li>Related Articles</li></ul>
 <ul><li><a  href="#SessionStorage-SessionStateObjects">Session State Objects</a>
 <ul class="toc-indentation"><li><a  href="#SessionStorage-Pitfalls">Pitfalls</a></li><li><a  href="#SessionStorage-CheckforCreation">Check for Creation</a></li><li><a  href="#SessionStorage-PersistenceStrategies">Persistence Strategies</a></li><li><a  href="#SessionStorage-ConfiguringSSOs">Configuring SSOs</a></li></ul>
@@ -136,7 +136,7 @@ div.rbtoc1518405712407 li {margin-left:
 <ul class="toc-indentation"><li><a  href="#SessionStorage-@ImmutableSessionPersistedObjectAnnotation">@ImmutableSessionPersistedObject Annotation</a></li><li><a  href="#SessionStorage-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject Interface</a></li><li><a  href="#SessionStorage-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer Service</a></li></ul>
 </li><li><a  href="#SessionStorage-SessionLocking">Session Locking</a></li></ul>
 </div>
-</div></div></div>Example:<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div></div>Example:<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>MyPage.java (partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class MyPage
 {
   @SessionState
@@ -161,7 +161,7 @@ div.rbtoc1518405712407 li {margin-left:
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @SessionState(create=false)
   private ShoppingCart shoppingCart;
 </pre>
-</div></div><p>In this case, the shoppingCart field will be null if the ShoppingCart SSO does not exist, but will be non-null if it has been created (either by assigning a value to the field, or by a different SSO field where create is true).</p><h3 id="SessionStorage-PersistenceStrategies">Persistence Strategies</h3><p>Main Article: <a  href="session-storage.html">Persistent Page Data</a></p><p>Each SSO is managed according to a persistence strategy. The default persistence strategy, "session", stores the SSOs inside the session. The session is created as needed.</p><h3 id="SessionStorage-ConfiguringSSOs">Configuring SSOs</h3><p>Generally, you will need to configure your Session State Object if you want to change the persistence strategy to other than the default. (Right now there's only one built in strategy, but more will be coming in the future.)</p><p>Alternately, you can configure a Session State Object in order to control how it is instantiated. You may need to inject some va
 lues into the SSO when it is first created, or otherwise initialize it. In this case, you may provide an <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ApplicationStateCreator.html">ApplicationStateCreator</a> object, which will be called upon to create the SSO as necessary. This is also the technique to use when you want your SSO to be represented by an <em>interface</em> rather than a <em>class</em>: you need to provide a creator that knows about the class that implements the interface.</p><p>A Session State Object is configured using contributions to the ApplicationStateManager service. From your application's module:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>In this case, the shoppingCart field will be null if the ShoppingCart SSO does not exist, but will be non-null if it has been created (either by assigning a value to the field, or by a different SSO field where create is true).</p><h3 id="SessionStorage-PersistenceStrategies">Persistence Strategies</h3><p>Main Article: <a  href="persistent-page-data.html">PersistentPage</a></p><p>Each SSO is managed according to a persistence strategy. The default persistence strategy, "session", stores the SSOs inside the session. The session is created as needed.</p><h3 id="SessionStorage-ConfiguringSSOs">Configuring SSOs</h3><p>Generally, you will need to configure your Session State Object if you want to change the persistence strategy to other than the default. (Right now there's only one built in strategy, but more will be coming in the future.)</p><p>Alternately, you can configure a Session State Object in order to control how it is instantiated. You may need to inject some val
 ues into the SSO when it is first created, or otherwise initialize it. In this case, you may provide an <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ApplicationStateCreator.html">ApplicationStateCreator</a> object, which will be called upon to create the SSO as necessary. This is also the technique to use when you want your SSO to be represented by an <em>interface</em> rather than a <em>class</em>: you need to provide a creator that knows about the class that implements the interface.</p><p>A Session State Object is configured using contributions to the ApplicationStateManager service. From your application's module:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  public void contributeApplicationStateManager(MappedConfiguration&lt;Class, ApplicationStateContribution&gt; configuration)
   {
     ApplicationStateCreator&lt;MyState&gt; creator = new ApplicationStateCreator&lt;ShoppingCart&gt;()
@@ -182,8 +182,8 @@ div.rbtoc1518405712407 li {margin-left:
 <div class="aui-message aui-message-info">
 Added in 5.2 
    &#160;
-</div><p>As an alternative to SSOs, Tapestry provides a <strong>Session Attribute</strong> mechanism, which lets you store data in the session by name (rather than type). It is particularly useful when integrating Tapestry with legacy applications that directly manipulate the HttpSession.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>The Old Way</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class Page {
+</div><p>As an alternative to SSOs, Tapestry provides a <strong>Session Attribute</strong> mechanism, which lets you store data in the session by name (rather than type). It is particularly useful when integrating Tapestry with legacy applications that directly manipulate the HttpSession.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>MyPage.java - The Old Way</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class MyPage {
     @Inject
     private Request request;
     
@@ -192,29 +192,29 @@ Added in 5.2
     }
 }
 </pre>
-</div></div><p>Starting with Tapestry 5.2, this can be accomplished just by annotating a page or component property with @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/SessionAttribute.html">SessionAttribute</a>. This annotation is used to map a property of a page or component to value stored in session. Unlike Session State Objects, the name (not the type) of the annotated property is used as the name of the session attribute to look for.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>The New Way</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class Page {
+</div></div><p>Starting with Tapestry 5.2, this can be accomplished just by annotating a page or component property with @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/SessionAttribute.html">SessionAttribute</a>. This annotation is used to map a property of a page or component to value stored in session. Unlike Session State Objects, the name (not the type) of the annotated property is used as the name of the session attribute to look for.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>MyPage.java - The New Way</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class MyPage {
     @SessionAttribute
     private User loggedInUserName;
 }
 </pre>
-</div></div><p>You can also provide a name using the annotation's <code>value</code> parameter:</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 Page {
+</div></div><p>You can also provide a name using the annotation's <code>value</code> parameter:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>MyPage.java</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class MyPage {
     @SessionAttribute("loggedInUserName")
     private User userName;
 }
 </pre>
-</div></div><h3 id="SessionStorage-Pitfalls.1">Pitfalls</h3><p>As with SSOs, when using Session Attributes you are creating a session-wide data storage area that has the serious possibility of data collisions, not just within your application but with other modules/libraries. To avoid problems, you should qualify the session attribute name with a package-like naming convention. For example, use something like "com.mycompany.myapp.username" instead of just "username".</p><p>It's best to define the session attribute name as constant, and use that in the annotation's value parameter, rather then defaulting to the instance variable name. This will help prevent subtle runtime errors due to misspellings. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>The Safer Way</b></div><div class="codeContent panelContent pdl">
+</div></div><h3 id="SessionStorage-Pitfalls.1">Pitfalls</h3><p>As with SSOs, when using Session Attributes you are creating a session-wide data storage area that has the serious possibility of data collisions, not just within your application but with other modules/libraries. To avoid problems, you should qualify the session attribute name with a package-like naming convention. For example, use something like "com.mycompany.myapp.username" instead of just "username".</p><p>It's best to define the session attribute name as constant, and use that in the annotation's value parameter, rather then defaulting to the instance variable name. This will help prevent subtle runtime errors due to misspellings. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>MyPage.java - The Safer Way</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public static final String USER_NAME_SESSION_ATTRIBUTE = "com.example.shoppingapp.username";
 
 ...
 
-public class Page {
+public class MyPage {
     @SessionAttribute(USER_NAME_SESSION_ATTRIBUTE)
     private User userName;
 }
 </pre>
-</div></div><p></p><h2 id="SessionStorage-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="SessionStorage-@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/cu
 rrent/apidocs/org/apache/tapestry5/annotations/ImmutableSessionPersistedObject.html">ImmutableSessionPersistedObject</a> annotation.</p><h3 id="SessionStorage-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="SessionStorage-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer Service</h3><p>The <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Sessi
 onPersistedObjectAnalyzer.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><h2 id="SessionStorage-SessionLocking">Session Locking</h2><p>Starting with version 5.4, by default Tapestry will apply locking semantics around access to the HttpSession. Reading attribute names occurs with a shared read lock, and getting or setting an attribute upgrades the lock to an exclusive write lock. This can tend to serialize threads when a number of simultaneous (Ajax) requests from the client arrive. However, many implementations of HttpSession are not thread safe, and often mutable objects<br clear="none"> are stored in the session and shared between threads.</p><p>The <code>tapestry.session-locking-enabled</code> <a  href="session-storage.html">symbol</a> can co
 ntrol this behavior. Setting this to true (the default) will yield a more robust application; setting it to false may speed up processing for more Ajax intensive applications (but care should then be given to ensuring that objects shared inside the session are themeselves immutable or thread-safe).</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent pdl">
+</div></div><p></p><h2 id="SessionStorage-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="SessionStorage-@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/cu
 rrent/apidocs/org/apache/tapestry5/annotations/ImmutableSessionPersistedObject.html">ImmutableSessionPersistedObject</a> annotation.</p><h3 id="SessionStorage-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="SessionStorage-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer Service</h3><p>The <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Sessi
 onPersistedObjectAnalyzer.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><h2 id="SessionStorage-SessionLocking">Session Locking</h2><p>Starting with version 5.4, by default Tapestry will apply locking semantics around access to the HttpSession. Reading attribute names occurs with a shared read lock, and getting or setting an attribute upgrades the lock to an exclusive write lock. This can tend to serialize threads when a number of simultaneous (Ajax) requests from the client arrive. However, many implementations of HttpSession are not thread safe, and often mutable objects<br clear="none"> are stored in the session and shared between threads.</p><p>The <a  href="configuration.html"><code>tapestry.session-locking-enabled</code></a> <span class="co
 nfluence-link">configuration symbol</span> can control this behavior. Setting this to true (the default) will yield a more robust application; setting it to false may speed up processing for more Ajax intensive applications (but care should then be given to ensuring that objects shared inside the session are themeselves immutable or thread-safe).</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  public static void contributeApplicationDefaults(MappedConfiguration&lt;String,String&gt; configuration)
   {
     configuration.add(SymbolConstants.SESSION_LOCKING_ENABLED, true);