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;"><!DOCTYPE web-app
@@ -410,7 +410,7 @@ Added in 5.4
</p><div class="aui-message aui-message-info">
Added in 5.4
 
-</div><strong>SymbolConstants.RESTRICTIVE_ENVIRONMENT</strong> – A
flag (true or false) that, if true, changes some default Tapestry behavior to
make it work better in restrictive environments such as <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> –
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 <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> –
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 <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> – A
flag (true or false) that, if true, changes some default Tapestry behavior to
make it work better in restrictive environments such as <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> –
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 <strong><code>false</code></strong>. See <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> –
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 <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 <?xml?> 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><![CDATA[]>
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 <?xml?> 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><![CDATA[]>
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 (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 (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<String,String>
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<String,String>
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<Class,Object> 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> </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> </p><p>The value stored in the HttpSession is
a <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 <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> </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 <span>ensure
that all access to certain pages (or all pages) occurs only via the encrypted
HTTPS protocol</span><span>. See <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> </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 <span>ensure
that all access to certain pages (or all pages) occurs only via the encrypted
HTTPS protocol</span><span>. See <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 <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 <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 @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/WhitelistAccessOnly.html">WhitelistAccessOnly</a> will
only be displayed to users (clients) that are on the <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), but you can customize this by contributing to the
ClientWhitelist service 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) – 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> </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 <a
href="security.html">Security FAQ</a> for how to deal with this.</p><h2
id="Security-AssetSecurity">Asset Security</h2><p>Main Article: <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. 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="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 </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);"> (HMAC) into serialized Java object data that
it sends to the client (generally, this means the </span><code
style="text-align: justify;">t:formdata</code><span style="color:
rgb(0,0,0);"> 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 <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: </sp
an></p><div class="preformatted panel" style="border-width: 1px;"><div
class="preformattedContent panelContent">
+</div></div><p> </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 <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: <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. 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 </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);"> (HMAC) into serialized Java object data that
it sends to the client (generally, this means the </span><code
style="text-align: justify;">t:formdata</code><span style="color:
rgb(0,0,0);"> 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 <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: </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> is a 3rd party module that has
several features for preventing CSRF attacks. It protects
all <span>component event handlers (event links, forms, etc.) by adding
a </span><span>CSRF token to event links and adds a CSRF token as a hidden
field to all forms.
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> <span style="color:
rgb(0,0,0);">is an add-on to the </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);"> 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: </span><a class="external-link"
href="http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId">http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId</a></li></ul><p> </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<Class,
ApplicationStateContribution> configuration)
{
ApplicationStateCreator<MyState> creator = new
ApplicationStateCreator<ShoppingCart>()
@@ -182,8 +182,8 @@ div.rbtoc1518405712407 li {margin-left:
<div class="aui-message aui-message-info">
Added in 5.2
 
-</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<String,String>
configuration)
{
configuration.add(SymbolConstants.SESSION_LOCKING_ENABLED, true);