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 2022/04/21 07:11:58 UTC

svn commit: r1079258 - in /websites/production/tapestry/content: cache/main.pageCache session-storage.html

Author: buildbot
Date: Thu Apr 21 07:11:58 2022
New Revision: 1079258

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    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/session-storage.html
==============================================================================
--- websites/production/tapestry/content/session-storage.html (original)
+++ websites/production/tapestry/content/session-storage.html Thu Apr 21 07:11:58 2022
@@ -142,7 +142,7 @@
             
             <!-- /// Content Start -->
             <div id="content">
-                            <div id="ConfluenceContent"><p>Most web applications will need to have some data that is shared across multiple pages. Perhaps you are creating a multi-page wizard, or you have an object that tracks the user's identify once logged in, or maybe you need to manage a shopping cart.</p><div class="aui-label" style="float:right" title="Related Articles">
+                            <div id="ConfluenceContent"><p></p><p>Most web applications will need to have some data that is shared across multiple pages. Perhaps you are creating a multi-page wizard, or you have an object that tracks the user's identify once logged in, or maybe you need to manage a shopping cart.</p><div class="aui-label" style="float:right" title="Related Articles">
 
 
 
@@ -160,7 +160,7 @@
                 <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="session-storage.html">Session Storage</a>
+                        <a href="performance-and-clustering.html">Performance and Clustering</a>
                 
                         
                     </div>
@@ -169,7 +169,7 @@
                 <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="performance-and-clustering.html">Performance and Clustering</a>
+                        <a href="persistent-page-data.html">Persistent Page Data</a>
                 
                         
                     </div>
@@ -178,7 +178,7 @@
                 <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="persistent-page-data.html">Persistent Page Data</a>
+                        <a href="session-storage.html">Session Storage</a>
                 
                         
                     </div>
@@ -189,11 +189,11 @@
 <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="na
 vmenu" 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.rbtoc1614176414149 {padding: 0px;}
-div.rbtoc1614176414149 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1614176414149 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1650525112447 {padding: 0px;}
+div.rbtoc1650525112447 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1650525112447 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style><div class="toc-macro rbtoc1614176414149">
+/*]]>*/</style><div class="toc-macro rbtoc1650525112447">
 <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>
@@ -203,7 +203,7 @@ div.rbtoc1614176414149 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="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>MyPage.java (partial)</b></div><div class="codeContent panelContent pdl">
+</div></div></div>Example:<p></p><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><code class="language-java">public class MyPage
 {
   @SessionState
@@ -218,7 +218,7 @@ div.rbtoc1614176414149 li {margin-left:
 
   ... then, later in this class or any other:
 
-  @sessionState
+  @SessionState
   private String userCity;     // This overwrites value in userName, because it's also a String!
 </code></pre>
 </div></div><p>The simple rule is, NEVER use @SessionState for simple-type variables. It is ALWAYS worth taking the time to build a special class to hold your session state information. Doing so will force you to consolidate that information into a single, logical unit that can't be accidentally accessed by other classes. (Alternatively, see the Session Attribute section below.)</p><h3 id="SessionStorage-CheckforCreation">Check for Creation</h3><p>Scalable web applications do not create the server-side session needlessly. If you can avoid creating the session, especially on first access to your web application, you will be able to handle an order of magnitude more users. So, if you can avoid creating the SSO, you should do so.</p><p>But how to avoid creating it? Simply checking ("shoppingCart!= null") will force the creation of the SSO and the session to store it in.</p><p>Instead, create a second field with a matching name but with "Exists" appended:</p><div class="code panel pdl" 
 style="border-width: 1px;"><div class="codeContent panelContent pdl">
@@ -247,6 +247,7 @@ div.rbtoc1614176414149 li {margin-left:
 <div class="aui-message aui-message-info macro-since"><b class="param-since">Added in 5.2</b>
 
 
+    <div class="param-body"></div>
 
 </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><code class="language-java">public class MyPage {
@@ -280,7 +281,7 @@ public class MyPage {
     private User userName;
 }
 </code></pre>
-</div></div><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="https://tapestry.apache.org/current/a
 pidocs/org/apache/tapestry5/http/annotations/ImmutableSessionPersistedObject.html">ImmutableSessionPersistedObject</a> annotation.</p><h3 id="SessionStorage-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject Interface</h3><p>The <a class="external-link" href="https://tapestry.apache.org/current/apidocs/org/apache/tapestry5/http/OptimizedSessionPersistedObject.html">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="https://tapestry.apache.org/current/apidocs/org/apache/tapestry5/http/se
 rvices/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><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 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="confluen
 ce-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">
+</div></div><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="https://tapestry.apache.org/current/a
 pidocs/org/apache/tapestry5/http/annotations/ImmutableSessionPersistedObject.html">ImmutableSessionPersistedObject</a> annotation.</p><h3 id="SessionStorage-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject Interface</h3><p>The <a class="external-link" href="https://tapestry.apache.org/current/apidocs/org/apache/tapestry5/http/OptimizedSessionPersistedObject.html">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="https://tapestry.apache.org/current/apidocs/org/apache/tapestry5/http/se
 rvices/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><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 objectsare stored in the session and shared between threads.</p><p>The <a href="configuration.html"><code>tapestry.session-locking-enabled</code></a> <span class="confluenc
 e-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><code class="language-java">  public static void contributeApplicationDefaults(MappedConfiguration&lt;String,String&gt; configuration)
   {
     configuration.add(SymbolConstants.SESSION_LOCKING_ENABLED, true);