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 Sat Feb  3 
16:21:22 2018
@@ -27,6 +27,16 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' 
rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' 
type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushJava.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushPlain.js' 
type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,23 +77,80 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><rich-text-body><p>The use of the 
term "persistence" here refers to <em>page-level</em> persistence, NOT database 
persistence.</p></rich-text-body><p>Most instance variables in Tapestry are 
automatically cleared at the end of each request. This is important, as it 
pertains to how Tapestry pages are shared, over time, by many 
users.</p><parameter ac:name="style">float:right</parameter><parameter 
ac:name="title">Related Articles</parameter><parameter 
ac:name="class">aui-label</parameter><rich-text-body><parameter 
ac:name="showLabels">false</parameter><parameter 
ac:name="showSpace">false</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter ac:name="cql">label = "persistence" and space = 
currentSpace()</parameter></rich-text-body><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. (T
 o 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><parameter ac:name="">java</parameter><plain-text-body>  @Persist
+                <div id="ConfluenceContent"><div 
class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>The use of the term "persistence" 
here refers to <em>page-level</em> persistence, NOT database 
persistence.</p></div></div><p>Most instance variables in Tapestry are 
automatically cleared at the end of each request. This is important, as it 
pertains to how Tapestry pages are shared, over time, by many users.</p><div 
class="aui-label" style="float:right" title="Related Articles">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="performance-and-clustering.html">Performance 
and Clustering</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="session-storage.html">Session Storage</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="persistent-page-data.html">Persistent Page 
Data</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div>
+
+
+<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">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Persist
   private int value;
-</plain-text-body><p>Such annotated fields will retain their state between 
requests. Generally, speaking, this means that the value is stored into the 
session (but other approaches are possible).</p><p>Whenever you make a change 
to a persistent field, its value is saved. On later requests to the same page, 
the value for the field is restored.</p><h2 
id="PersistentPageData-PersistenceStrategies">Persistence Strategies</h2><p>The 
value for each field is the <em>strategy</em> used to store the field between 
requests.</p><h3 id="PersistentPageData-SessionStrategy">Session 
Strategy</h3><p><plain-text-body>{float:right|background=#eee|padding=0 1em}
-    *JumpStart Demo:*
-    [Storing Data in a 
Page|http://jumpstart.doublenegative.com.au/jumpstart/examples/state/storingdatainapage]
-    [Passing Data Between 
Pages|http://jumpstart.doublenegative.com.au/jumpstart/examples/state/passingdatabetweenpages]
-{float}</plain-text-body>The session strategy stores field changes into the 
session; the session is created as necessary. Session strategy is the default 
strategy used unless otherwise overridden.</p><p>A suitably long session 
attribute name is used; it incorporates the name of the page, the nested 
component id, and the name of the field.</p><parameter ac:name="title">Example: 
Session Strategy</parameter><plain-text-body>  @Persist
+</pre>
+</div></div><p>Such annotated fields will retain their state between requests. 
Generally, speaking, this means that the value is stored into the session (but 
other approaches are possible).</p><p>Whenever you make a change to a 
persistent field, its value is saved. On later requests to the same page, the 
value for the field is restored.</p><h2 
id="PersistentPageData-PersistenceStrategies">Persistence Strategies</h2><p>The 
value for each field is the <em>strategy</em> used to store the field between 
requests.</p><h3 id="PersistentPageData-SessionStrategy">Session 
Strategy</h3><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/state/storingdatainapage";
 rel="nofollow">Storing Data in a Page</a><br clear="none">
+    <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/state/passingdatabetweenpages";
 rel="nofollow">Passing Data Between Pages</a></p></div>The session strategy 
stores field changes into the session; the session is created as necessary. 
Session strategy is the default strategy used unless otherwise overridden.<p>A 
suitably long session attribute name is used; it incorporates the name of the 
page, the nested component id, and the name of the field.</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>Example: Session Strategy</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Persist
   private int value;
-</plain-text-body><h3 id="PersistentPageData-FlashStrategy">Flash 
Strategy</h3><p>The flash strategy stores information in the session as well, 
just for not very long. Values are stored into the session, but then deleted 
from the session as they are first used to restore a page's state.</p><p>The 
flash is typically used to store temporary messages that should only be 
displayed to the user once.</p><parameter ac:name="title">Example: Flash 
Strategy</parameter><plain-text-body>  @Persist(PersistenceConstants.FLASH)
+</pre>
+</div></div><h3 id="PersistentPageData-FlashStrategy">Flash 
Strategy</h3><p>The flash strategy stores information in the session as well, 
just for not very long. Values are stored into the session, but then deleted 
from the session as they are first used to restore a page's state.</p><p>The 
flash is typically used to store temporary messages that should only be 
displayed to the user once.</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>Example: Flash Strategy</b></div><div class="codeContent panelContent 
pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Persist(PersistenceConstants.FLASH)
   private int value;
-</plain-text-body><h3 id="PersistentPageData-ClientStrategy">Client 
Strategy</h3><p>The field is persisted onto the client; you will see an 
additional query parameter in each URL (or an extra hidden field in each 
form).</p><p>Client persistence is somewhat expensive. It can bloat the size of 
the rendered pages by adding hundreds of characters to each link. There is 
extra processing on each request to de-serialize the values encoded into the 
query parameter.</p><p>Client persistence does not scale very well; as more 
information is stored into the query parameter, its length can become 
problematic. In many cases, web browsers, firewalls or other servers may 
silently truncate the URL which will break the application.</p><p>Use client 
persistence with care, and store a minimal amount of data. Try to store the 
identity (that is, primary key) of an object, rather than the object 
itself.</p><parameter ac:name="title">Example: Client 
Strategy</parameter><plain-text-body>  @Persist(Persisten
 ceConstants.CLIENT)
+</pre>
+</div></div><h3 id="PersistentPageData-ClientStrategy">Client 
Strategy</h3><p>The field is persisted onto the client; you will see an 
additional query parameter in each URL (or an extra hidden field in each 
form).</p><p>Client persistence is somewhat expensive. It can bloat the size of 
the rendered pages by adding hundreds of characters to each link. There is 
extra processing on each request to de-serialize the values encoded into the 
query parameter.</p><p>Client persistence does not scale very well; as more 
information is stored into the query parameter, its length can become 
problematic. In many cases, web browsers, firewalls or other servers may 
silently truncate the URL which will break the application.</p><p>Use client 
persistence with care, and store a minimal amount of data. Try to store the 
identity (that is, primary key) of an object, rather than the object 
itself.</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="bord
 er-bottom-width: 1px;"><b>Example: Client Strategy</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Persist(PersistenceConstants.CLIENT)
   private int value;
-</plain-text-body><h3 
id="PersistentPageData-HibernateEntityStrategy">Hibernate Entity 
Strategy</h3><p><span style="line-height: 1.4285715;">Entity persistence is 
provided by the tapestry-hibernate module (which extends Tapestry with new 
features).</span></p><p>In Entity persistence, the field should store a 
Hibernate entity instance.</p><parameter ac:name="title">"Hibernate Entity 
Strategy"</parameter><plain-text-body>  
@Persist(HibernatePersistenceConstants.ENTITY)
-  private User user;</plain-text-body><p>&#160;</p><p>The value stored in the 
HttpSession is a&#160;<em>token</em> for the entity: its Java class name and 
primary key. When the field is restored in a later request, the entity is 
re-instantiated using that data.</p><p>What is&#160;<em>not</em> stored is any 
changes to the persistent entity that are not committed to the external 
datastore (the database).</p><p>Starting in Tapestry 5.4, it is possible to 
store a non-persistent entity (a transient entity). A transient entity is 
stored directly into the HttpSession, and should be Serializable if the 
application is clustered.</p><h3 id="PersistentPageData-JPAEntityStrategy">JPA 
Entity Strategy</h3><p>The tapestry-jpa module uses a similar strategy. 
However, at the current time it can only store a persisted entity (one that has 
been saved to the database and has a primary key).</p><parameter 
ac:name="title">"Example: JPA Entity Strategy"</parameter><plain-text-body>  
@Persist(JpaPersistenc
 eConstants.ENTITY)
-  private Account account;</plain-text-body><p><span style="color: 
rgb(83,145,38);font-size: 20.0px;line-height: 1.5;">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>Fie
 lds marked 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><parameter ac:name=""><a  
href="clustering-issues.html">Clustering Issues</a></parameter></p><parameter 
ac:name="title">Example: Entity Session Strategy</parameter><plain-text-body>  
@Persist(HibernatePersistenceConstants.ENTITY)
-  private User user;</plain-text-body><parameter ac:name="title">"Example:JAP 
Session Strategy"</parameter><plain-text-body>  
@Persist(JpaPersistenceConstants.ENTITY)
-  private Account account;</plain-text-body></div>
+</pre>
+</div></div><h3 id="PersistentPageData-HibernateEntityStrategy">Hibernate 
Entity Strategy</h3><p><span>Entity persistence is provided by the 
tapestry-hibernate module (which extends Tapestry with new 
features).</span></p><p>In Entity persistence, the field should store a 
Hibernate entity instance.</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>"Hibernate Entity 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><p>&#160;</p><p>The value stored in the HttpSession is 
a&#160;<em>token</em> for the entity: its Java class name and primary key. When 
the field is restored in a later request, the entity is re-instantiated using 
that data.</p><p>What is&#160;<em>not</em> stored is any changes to the 
persistent entity that are not committed to the external datastore (the 
database).</p><p>Starting in Tapestry 5.4, it is possible to store a 
non-persistent entity (a transient entity). A transient entity is stored 
directly into the HttpSession, and should be Serializable if the application is 
clustered.</p><h3 id="PersistentPageData-JPAEntityStrategy">JPA Entity 
Strategy</h3><p>The tapestry-jpa module uses a similar strategy. However, at 
the current time it can only store a persisted entity (one that has been saved 
to the database and has a primary key).</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>"Exa
 mple: JPA Entity Strategy"</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Persist(JpaPersistenceConstants.ENTITY)
+  private Account account;</pre>
+</div></div><p><span style="color: rgb(83,145,38);">Persistence Strategy 
Inheritance</span></p><p>By default the value for the Persist annotation is the 
empty string. When this is true, then the actual strategy to be used is 
determined by a search up the component hierarchy.</p><p>For each component, 
the meta-data property <code>tapestry.persistence-strategy</code> is checked. 
This can be specified using the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Meta.html";>Meta</a>
 annotation.</p><p>If the value is non-blank, then that strategy is used. This 
allows a component to control the persistence strategy used inside any 
sub-components (that don't explicitly use a different strategy).</p><p>In any 
case, if no component provides the meta data, then the ultimate default, 
"session", is used.</p><h2 id="PersistentPageData-DefaultValues">Default 
Values</h2><p>Fields marked with @Persist may not have default values (whether 
set i
 nline, or inside a constructor).</p><h2 
id="PersistentPageData-ClearingPersistentFields">Clearing Persistent 
Fields</h2><p>If you reach a point where you know that all data for a page can 
be discarded, you can do exactly that.</p><p>The method 
<code>discardPersistentFieldChanges()</code> of ComponentResources will discard 
all persistent fields for the page, regardless of which strategy is used to 
store the property. This will not affect the page in memory, but takes effect 
for subsequent requests.</p><p></p><h2 
id="PersistentPageData-ClusteringIssues">Clustering Issues</h2><p>The Servlet 
API was designed with the intention that there would be only a modest amount of 
server-side state, and that the stored values would be individual numbers and 
strings, and thus, immutable.</p><p>However, many web applications do not use 
the HttpSession this way, instead storing large, mutable objects in the 
session. This is not a problem for single servers, but in a cluster, anything 
stored in the se
 ssion must be serialized to a bytestream and distributed to other servers 
within the cluster, and restored there.</p><p>Most application servers perform 
that serialization and distribution whenever HttpSession.setAttribute() is 
called. This creates a data consistency problem for mutable objects, because if 
you read a mutable session object, change its state, but <em>don't</em> invoke 
setAttribute(), the changes will be isolated to just a single server in the 
cluster.</p><p>Tapestry attempts to solve this: any session-persisted object 
that is read during a request will be re-stored back into the HttpSession at 
the end of the request. This ensures that changed internal state of those 
mutable objects is properly replicated around the cluster.</p><p>But while this 
solution solves the data consistency problem, it does so at the expense of 
performance, since all of those calls to setAttribute() result in extra session 
data being replicated needlessly if the internal state of the mutable o
 bject hasn't changed.</p><p>Tapestry has solutions to this, too:</p><h3 
id="PersistentPageData-@ImmutableSessionPersistedObjectAnnotation">@ImmutableSessionPersistedObject
 Annotation</h3><p>Tapestry knows that Java's String, Number and Boolean 
classes are immutable. Immutable objects do not require a re-store into the 
session.</p><p>You can mark your own session objects as immutable (and thus not 
requiring session replication) using the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ImmutableSessionPersistedObject.html";>ImmutableSessionPersistedObject</a>
 annotation.</p><h3 
id="PersistentPageData-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject
 Interface</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/OptimizedSessionPersistedObject";>OptimizedSessionPersistedObject</a>
 interface allows an object to control this behavior. An object with this
  interface can track when its mutable state changes. Typically, you should 
extend from the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.html";>BaseOptimizedSessionPersistedObject</a>
 base class.</p><h3 
id="PersistentPageData-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer
 Service</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.html";>SessionPersistedObjectAnalyzer</a>
 service is ultimately responsible for determining whether a session persisted 
object is dirty or not (dirty meaning in need of a restore into the session). 
This is an extensible service where new strategies, for new classes, can be 
introduced.</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>Example: Entity Session Strategy</b></div
 ><div class="codeContent panelContent pdl">
+<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">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Persist(JpaPersistenceConstants.ENTITY)
+  private Account account;</pre>
+</div></div></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/property-expressions.html
==============================================================================
--- websites/production/tapestry/content/property-expressions.html (original)
+++ websites/production/tapestry/content/property-expressions.html Sat Feb  3 
16:21:22 2018
@@ -67,7 +67,7 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>Tapestry uses <strong>property 
expressions</strong> to move data between components. Property expressions are 
the basis of the <a  href="component-parameters.html">component parameters</a> 
and <a  href="component-templates.html">template expansions</a>.</p><div 
class="aui-label" style="float:right" title="Related Articles">
+                <div id="ConfluenceContent"><p>Tapestry uses <strong>property 
expressions</strong> to move data between components. Property expressions are 
the basis of the <a  href="property-expressions.html">component parameters</a> 
and <a  href="property-expressions.html">template expansions</a>.</p><div 
class="aui-label" style="float:right" title="Related Articles">
 
 
 
@@ -100,7 +100,7 @@
 </div>
 
 
-<p>A property expression is a string that explains to Tapestry how to navigate 
from a root object (the containing component) through some number of 
properties, to a final property that can be read or updated. In fact, that's a 
simplification, as the properties may actually be public fields, or even method 
invocations.</p><p>As elsewhere in Tapestry, the names of fields, properties, 
and methods are recognized in a case-insensitive manner.</p><p>The most basic 
form of a property expression is a simple property name, such as 
"userName".</p><p>A series of property names may be specified, separated by 
periods: "user.name", which is equivalent to either 
<code>getUser().getName()</code> or <code>getUser().setName()</code>, depending 
on context (whether the expression is being read or updated).</p><p>The "." is 
called the "dereference operator". A second operator is "?." or the "safe 
dereference operator". This works the same as "." except that it allows any of 
the properties to be null. Wh
 en reading, a null short-circuits the expression (which returns null). When 
writing to a property, an intermediate null value will cause the value to be 
discarded without error.</p><p>In other words, "user?.name" works, even when 
the <code>user</code> property may be null.</p><p>Property expressions can also 
reference public methods. Methods may take parameters (or not), but must not 
return void. When the final term in a property expression is a method, then the 
property expression is read-only.</p><p>Being able to invoke methods was 
originally added so that it was possible to access methods such as 
<code>java.util.Map.size()</code> (which is not named like a property getter 
method). In Tapestry 5.1, property expressions were extended so that parameters 
could be passed into methods.</p><p>Parameters to methods are, themselves, 
property expressions. This means that you can write a property expression that 
reads a property and passes it as a parameter to a method, and then access a pr
 operty of the object returned from the method.</p><h2 
id="PropertyExpressions-Compilation">Compilation</h2><p>Property expressions 
are compiled to Java classes at runtime; there is no runtime reflection (unlike 
the OGNL expression language used in prior releases of Tapestry).</p><h2 
id="PropertyExpressions-Grammar">Grammar</h2><p>Expressed in simplified <a  
class="external-link" 
href="http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form"; 
rel="nofollow">Backus&#8211;Naur Form</a>, the grammar of property expressions 
is as follows:</p><div class="preformatted panel" style="border-width: 
1px;"><div class="preformattedContent panelContent">
+<p>A property expression is a string that explains to Tapestry how to navigate 
from a root object (the containing component) through some number of 
properties, to a final property that can be read or updated. In fact, that's a 
simplification, as the properties may actually be public fields, or even method 
invocations.</p><p>As elsewhere in Tapestry, the names of fields, properties, 
and methods are recognized in a case-insensitive manner.</p><p>The most basic 
form of a property expression is a simple property name, such as 
"userName".</p><p>A series of property names may be specified, separated by 
periods: "user.name", which is equivalent to either 
<code>getUser().getName()</code> or <code>getUser().setName()</code>, depending 
on context (whether the expression is being read or updated).</p><p>The "<span 
style="color: rgb(255,0,0);"><strong>.</strong></span>" is called the 
"dereference operator". In addition, there is a a "safe dereference operator", 
"<span style="color: rgb(255,0,0)
 ;">?.</span>", which&#160; works the same as "<span style="color: 
rgb(255,0,0);">.</span>" except that it allows any of the properties to be 
null. When reading, a null short-circuits the expression (which returns null). 
When writing to a property, an intermediate null value will cause the value to 
be discarded without error.</p><p>In other words, "user<span style="color: 
rgb(255,0,0);">?.</span>name" works, even when the <code>user</code> property 
may be null.</p><p>Property expressions can also reference public methods. 
Methods may take parameters (or not), but must not return void. When the final 
term in a property expression is a method, then the property expression is 
read-only.</p><p>Being able to invoke methods was originally added so that it 
was possible to access methods such as <code>java.util.Map.size()</code> (which 
is not named like a property getter method). In Tapestry 5.1, property 
expressions were extended so that parameters could be passed into 
methods.</p><p>Parame
 ters to methods are, themselves, property expressions. This means that you can 
write a property expression that reads a property and passes it as a parameter 
to a method, and then access a property of the object returned from the 
method.</p><h2 id="PropertyExpressions-Compilation">Compilation</h2><p>Property 
expressions are compiled to Java classes at runtime; there is no runtime 
reflection (unlike the OGNL expression language used in prior releases of 
Tapestry).</p><h2 id="PropertyExpressions-Grammar">Grammar</h2><p>Expressed in 
simplified <a  class="external-link" 
href="http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form"; 
rel="nofollow">Backus&#8211;Naur Form</a>, the grammar of property expressions 
is as follows:</p><div class="preformatted panel" style="border-width: 
1px;"><div class="preformattedContent panelContent">
 <pre>expression : keyword | rangeOp | constant | propertyChain | list | notOp 
| map;
 
 keyword : 'null' | 'this';
@@ -139,7 +139,7 @@ mapKey : keyword | constant | propertyCh
 </div></div>
 <div class="error"><span class="error">Unknown macro: {div}</span> 
 <p>Support for map literals was added in Tapestry 5.3.</p>
-</div>Notes:<ul><li>Whitespace is ignored.</li><li>Integers and decimals may 
have a leading sign ('+' or '-').</li><li>Constants are in base 10 (octal and 
hex notation is not yet supported). Decimals may contain a decimal point 
(exponent notation not yet supported).</li><li>Literal strings are enclosed in 
single quotes.</li><li>The <code>rangeOp</code> creates a range object that 
will iterate between the two values. The upper and lower bounds may be literal 
integers, or property expressions.</li><li>An identifier by itself is a 
property name. An identifier with parenthesis is a method 
invocation.</li><li>Property names, method names, and keywords are 
case-insensitive.</li><li>'this' is the root object (i.e., the containing 
component).</li><li>The <code>not</code> operator coerces the expression to a 
<code>boolean</code> (so it can be used on strings, numbers, 
etc.).</li><li>Method matching is based on method name and number of 
parameters, but not parameter types. The <a  href="type-
 coercion.html">TypeCoercer</a> service is used to convert parameters to the 
correct type to be passed into the method.</li></ul><h2 
id="PropertyExpressions-Examples">Examples</h2><div class="table-wrap"><table 
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>&#160;</p></th><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Example</p></th><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Notes</p></th></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>this</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>&#160;</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>null</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>&#160;</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Property Name</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><
 p>userName</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Calls 
getUserName() or setUserName, depending on context</p></td></tr><tr><th 
colspan="1" rowspan="1" class="confluenceTh"><p>Property Chain</p></th><td 
colspan="1" rowspan="1" class="confluenceTd"><p>user.address.city</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>Calls 
getUser().getAddress().getCity() or getUser().getAddress().setCity(), depending 
on context</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Property Chain</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>user?.name</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Calls getUser() and, if the result is not null, calls 
getName() on the result</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Method Invocation</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>groupList.size()</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>calls getGroupList().size()</p></
 td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Method 
Invocation</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>members.findById(user.id)?.name</p></td><td colspan="1" 
rowspan="1" class="confluenceTd"><p>Calls 
getMembers().findById(getUser().getId())?.getName() (unless findById returns 
null)</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Range</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>1..10</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Iterates between integers 1 and 10</p></td></tr><tr><th 
colspan="1" rowspan="1" class="confluenceTh"><p>Range</p></th><td colspan="1" 
rowspan="1" class="confluenceTd"><p>1..groupList.size()</p></td><td colspan="1" 
rowspan="1" class="confluenceTd"><p>Iterates between 1 and the result of 
getGroupList().size()</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Literal String</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>'Beer is proof that 
 God loves us and wants us to be happy.'</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Use single quotes</p></td></tr><tr><th colspan="1" 
rowspan="1" class="confluenceTh"><p>List</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>[user.name, user.email, user.phone]</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>&#160;</p></td></tr><tr><th 
colspan="1" rowspan="1" class="confluenceTh"><p>Not Operator</p></th><td 
colspan="1" rowspan="1" class="confluenceTd"><p>! user.deleted</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>the boolean negation of 
getUser().getDeleted()</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Not, Coerced</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>! user.middleName</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>true only if getUser.getMiddleName() returns null or an 
empty string</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Map</p></th><td cols
 pan="1" rowspan="1" class="confluenceTd"><p>{ 'framework' : 'Tapestry', 
'version' : version }</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Keys are string literals (in single quotes), but could 
be properties as well</p></td></tr></tbody></table></div></div>
+</div>Notes:<ul><li>Whitespace is ignored.</li><li>Integers and decimals may 
have a leading sign ('+' or '-').</li><li>Constants are in base 10 (octal and 
hex notation is not yet supported). Decimals may contain a decimal point 
(exponent notation not yet supported).</li><li>Literal strings are enclosed in 
single quotes.</li><li>The <code>rangeOp</code> creates a range object that 
will iterate between the two values. The upper and lower bounds may be literal 
integers, or property expressions.</li><li>An identifier by itself is a 
property name. An identifier with parenthesis is a method 
invocation.</li><li>Property names, method names, and keywords are 
case-insensitive.</li><li>'this' is the root object (i.e., the containing 
component).</li><li>The <code>not</code> operator coerces the expression to a 
<code>boolean</code> (so it can be used on strings, numbers, 
etc.).</li><li>Method matching is based on method name and number of 
parameters, but not parameter types. The <a  href="prope
 rty-expressions.html">TypeCoercer</a> service is used to convert parameters to 
the correct type to be passed into the method.</li></ul><h2 
id="PropertyExpressions-Examples">Examples</h2><div class="table-wrap"><table 
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>&#160;</p></th><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Example</p></th><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Notes</p></th></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>this</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>&#160;</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>null</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>&#160;</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Property Name</p></th><td colspan="1" rowspan="1" 
class="confluen
 ceTd"><p>userName</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Calls getUserName() or setUserName, depending on 
context</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Property Chain</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>user.address.city</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Calls getUser().getAddress().getCity() or 
getUser().getAddress().setCity(), depending on context</p></td></tr><tr><th 
colspan="1" rowspan="1" class="confluenceTh"><p>Property Chain</p></th><td 
colspan="1" rowspan="1" class="confluenceTd"><p>user?.name</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>Calls getUser() and, if the 
result is not null, calls getName() on the result</p></td></tr><tr><th 
colspan="1" rowspan="1" class="confluenceTh"><p>Method Invocation</p></th><td 
colspan="1" rowspan="1" class="confluenceTd"><p>groupList.size()</p></td><td 
colspan="1" rowspan="1" class="confluenceTd"><p>calls getGroupList().size(
 )</p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Method 
Invocation</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>members.findById(<a  class="external-link" 
href="http://user.id"; rel="nofollow">user.id</a>)?.name</p></td><td colspan="1" 
rowspan="1" class="confluenceTd"><p>Calls 
getMembers().findById(getUser().getId())?.getName() (unless findById returns 
null)</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Range</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>1..10</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Iterates between integers 1 and 10</p></td></tr><tr><th 
colspan="1" rowspan="1" class="confluenceTh"><p>Range</p></th><td colspan="1" 
rowspan="1" class="confluenceTd"><p>1..groupList.size()</p></td><td colspan="1" 
rowspan="1" class="confluenceTd"><p>Iterates between 1 and the result of 
getGroupList().size()</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Literal String</p></t
 h><td colspan="1" rowspan="1" class="confluenceTd"><p>'Beer is proof that God 
loves us and wants us to be happy.'</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Use single quotes</p></td></tr><tr><th colspan="1" 
rowspan="1" class="confluenceTh"><p>List</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>[<a  class="external-link" href="http://user.name"; 
rel="nofollow">user.name</a>, user.email, user.phone]</p></td><td colspan="1" 
rowspan="1" class="confluenceTd"><p>&#160;</p></td></tr><tr><th colspan="1" 
rowspan="1" class="confluenceTh"><p>Not Operator</p></th><td colspan="1" 
rowspan="1" class="confluenceTd"><p>! user.deleted</p></td><td colspan="1" 
rowspan="1" class="confluenceTd"><p>the boolean negation of 
getUser().getDeleted()</p></td></tr><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>Not, Coerced</p></th><td colspan="1" rowspan="1" 
class="confluenceTd"><p>! user.middleName</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>true only if ge
 tUser.getMiddleName() returns null or an empty string</p></td></tr><tr><th 
colspan="1" rowspan="1" class="confluenceTh"><p>Map</p></th><td colspan="1" 
rowspan="1" class="confluenceTd"><p>{ 'framework' : 'Tapestry', 'version' : 
version }</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Keys are 
string literals (in single quotes), but could be properties as 
well</p></td></tr></tbody></table></div></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/request-processing.html
==============================================================================
--- websites/production/tapestry/content/request-processing.html (original)
+++ websites/production/tapestry/content/request-processing.html Sat Feb  3 
16:21:22 2018
@@ -36,13 +36,26 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div></div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div>
+
+</div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form 
enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";> 
- <input type="text" name="q"> 
- <input type="submit" value="Search"> 
-</form></div><div class="emblem" style="float:left"><p><a  
href="index.html"><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div><div
 class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Request Processing</h1></div></div>
+            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";>
+  <input type="text" name="q">
+  <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a  href="index.html"><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Request Processing</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -54,43 +67,76 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><div class="aui-label" 
style="float:right" title="Related Articles"><h3>Related Articles</h3><ul 
class="content-by-label"><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="page-navigation.html">Page Navigation</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="page-life-cycle.html">Page Life Cycle</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="component-rendering.html">Component Rendering</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="component-events.html">Component Events</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="component-events-faq.html">Component Events FAQ</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="request-processing.html">Request Processing</a> 
-  </div> </li></ul></div><p><strong>Request Processing</strong> involves a 
sequence of steps that Tapestry performs when every HTTP request comes in. You 
<em>don't need</em> to know these steps to use Tapestry productively, but 
understanding the request processing pipeline is helpful if you want to 
understand Tapestry deeply.</p><p>Much of the early stages of processing are in 
the form of extensible <a  
href="pipelinebuilder-service.html">pipelines</a>.</p><h2 
id="RequestProcessing-TapestryFilter">Tapestry Filter</h2><p>All incoming 
requests originate with the TapestryFilter, which is a servlet filter 
configured inside your application's <a  
href="configuration.html">web.xml</a>.</p><p>The TapestryFilter is responsible 
for a number of startup and initialization functions.</p><p>When it receives a 
request, the TapestryFilter obtains the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpServletRequestHandler.html";>HttpServletR
 equestHandler</a> service, and invokes its service() method.</p><h2 
id="RequestProcessing-HttpServletRequestHandlerPipeline">HttpServletRequestHandler
 Pipeline</h2><p>This pipeline performs initial processing of the request. It 
can be extended by contributing a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpServletRequestFilter.html";>HttpServletRequestFilter</a>
 into the HttpServletRequestHandler service's configuration.</p><p>Tapestry 
does not contribute any filters into this pipeline of its own.</p><p>The 
terminator for the pipeline does two things:</p><ul><li>It stores the request 
and response into the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestGlobals.html";>RequestGlobals</a>
 service. This is a per-thread scoped service that stores 
per-thread/per-request information.</li><li>It wraps the request and response 
as a <a  class="external-link" href="http:
 
//tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Request.html">Request</a>
 and <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Response.html";>Response</a>,
 and passes them into the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestHandler.html";>RequestHandler</a>
 pipeline.</li></ul><h2 
id="RequestProcessing-RequestHandlerPipeline">RequestHandler 
Pipeline</h2><p>This pipeline is where most extensions related to requests take 
place. Request represents an abstraction on top of HttpServletRequest. 
(Primarily, this exists to bridge from the Servlet API objects to the 
corresponding Tapestry objects. This is to allow for a possible portlet 
integration for Tapestry.) Where other code and services within Tapestry 
require access to information in the request, such as query parameters, that 
information is obtained from the Request (or Response) objects.</p><
 p>The RequestHandler pipeline includes a number of built-in 
filters:</p><ul><li>CheckForUpdates is responsible for <a  
href="class-reloading.html">class and template 
reloading</a>.</li><li>Localization identifies the <a  
href="localization.html">locale for the user</a>.</li><li>StaticFiles checks 
for URLs that are for static files (files that exist inside the web context) 
and aborts the request, so that the servlet container can handle the request 
normally.</li><li>ErrorFilter catches uncaught exceptions from the lower levels 
of Tapestry and presents the exception report page. This involves the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestExceptionHandler.html";>RequestExceptionHandler</a>
 service, which is responsible for initializing and rendering the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/pages/ExceptionReport.html";>core/ExceptionReport</a>
 page.</li>
 </ul><p>The terminator for this pipeline stores the Request and the Response 
into RequestGlobals, then requests that the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Dispatcher.html";>MasterDispatcher</a>
 service figure out how to handle the request (if it is, indeed, a Tapestry 
request).</p><h2 id="RequestProcessing-MasterDispatcherService">Master 
Dispatcher Service</h2><p>The MasterDispatcher service is a chain-of-command, 
aggregating together (in a specific order), several Dispatcher objects. Each 
Dispatcher is built to recognize and process a particular kind of URL.</p><h3 
id="RequestProcessing-RootPathDispatcher">RootPath Dispatcher</h3><p>The 
RootPath Dispatcher recognizes a request for the application root (i.e., "/") 
and handles this the same as a render request for the "Start" page. Support for 
the Start page is kept for legacy purposes. Index pages are the correct 
approach.</p><h3 id="RequestProcessing-AssetDispatc
 her">Asset Dispatcher</h3><p>Requests that begin with "/assets/" are 
references to <a  href="assets.html">asset resources</a> that are stored on the 
classpath, inside the Tapestry JARs (or perhaps inside the JAR for a component 
library). The contents of the file will be delivered to the client browser as a 
byte stream. This dispatcher also handles requests that are simply polling for 
a change to the file.</p><h3 
id="RequestProcessing-PageRenderDispatcher">PageRender Dispatcher</h3><p>Page 
render requests are requests to render a particular page. Such requests may 
include additional elements on the path, which will be treated as activation 
context (see ComponentEvent Dispatcher below). Generally speaking, the 
activation context is the primary key of some related entity object. This 
allows the page to reconstruct the state it will need to successfully render 
itself.</p><p>The event handler method for the activate event may return a 
value; this is treated the same as the return value f
 rom a component action request; typically this will result in a redirect to 
another page. In this way, the activate event can perform simple validation at 
the page level ("can the user see this page?").</p><p>Page render URLs consist 
of the logical name of the page plus additional path elements for the 
activation context. The dispatcher here strips terms off of the path until it 
finds a known page name. Thus, "/mypage/27" would look first for a page whose 
name was "mypage/27", then look for a page name "mypage". Assuming the second 
search was successful, the page would be activated with the context "27". If no 
logical page name can be identified, control passes to the next 
dispatcher.</p><h3 
id="RequestProcessing-ComponentEventDispatcher">ComponentEvent 
Dispatcher</h3><p>The ComponentEvent dispatcher is used to trigger events in 
components.</p><p>The URL identifies the name of the page, then a series of 
component ids (the path from the page down to the specific component), then the 
 name of the event to be triggered on the component. The remaining path 
elements are used as the context for the <em>event</em> (not for the page 
activation, which does not currently apply). For example, "/griddemo.FOO.BAR/3" 
would locate page "griddemo", then component "FOO.BAR", and trigger an event 
named "action" (the default event type, which is omitted from the URL), with 
the context "3".</p><p>If the page in question has an activation context, it is 
supplied as an additional query parameter on the link.</p><p>In cases where the 
event type is not the default, "action", it will appear between the nested 
component id and the event context, preceded by a colon. Example: 
"/example/foo.bar:magic/99" would trigger an event of type "magic". This is not 
common in the vanilla Tapestry framework, but will likely be more common as 
Ajax features (which would not use the normal request logic) are 
implemented.</p><p>The response from a component action request is typically, 
but not universall
 y, used to send a redirect to the client; the redirect URL is a page render 
URL to display the response to the event. This is detailed under <a  
href="page-navigation.html">Page Navigation</a>.</p><h2 
id="RequestProcessing-RequestGlobalsService">RequestGlobals Service</h2><p>The 
RequestGlobals service has a life cycle of per-thread; this means that a 
separate instance exists for every thread, and therefore, for every request. 
The terminators of the two handler pipelines store the request/response pairs 
into the RequestGlobals service.</p><h2 
id="RequestProcessing-RequestService">Request Service</h2><p>The Request 
service is a <a  href="shadowbuilder-service.html">shadow</a> of the 
RequestGlobals services' request property. That is, any methods invoked on this 
service are delegated to the request object stored inside the 
RequestGlobals.</p><h2 id="RequestProcessing-Overview">Overview</h2><p>The 
following diagram provides an overview of how the different pipelines, filters 
and dispatc
 hers interact when processing an incoming request.</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-content-image-border" 
src="request-processing.data/tapestry_request_processing_800.png"></span></p></div>
+                <div id="ConfluenceContent"><div class="aui-label" 
style="float:right" title="Related Articles">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="page-navigation.html">Page Navigation</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="page-life-cycle.html">Page Life Cycle</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-rendering.html">Component 
Rendering</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-events.html">Component Events</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="component-events-faq.html">Component Events 
FAQ</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="request-processing.html">Request 
Processing</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div>
+
+
+<p><strong>Request Processing</strong> involves a sequence of steps that 
Tapestry performs when every HTTP request comes in. You <em>don't need</em> to 
know these steps to use Tapestry productively, but understanding the request 
processing pipeline is helpful if you want to understand Tapestry 
deeply.</p><p>Much of the early stages of processing are in the form of 
extensible <a  href="request-processing.html">pipelines</a>.</p><h2 
id="RequestProcessing-TapestryFilter">Tapestry Filter</h2><p>All incoming 
requests originate with the TapestryFilter, which is a servlet filter 
configured inside your application's <a  
href="request-processing.html">web.xml</a>.</p><p>The TapestryFilter is 
responsible for a number of startup and initialization functions.</p><p>When it 
receives a request, the TapestryFilter obtains the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpServletRequestHandler.html";>HttpServletRequestHandler</a>
 service
 , and invokes its service() method.</p><h2 
id="RequestProcessing-HttpServletRequestHandlerPipeline">HttpServletRequestHandler
 Pipeline</h2><p>This pipeline performs initial processing of the request. It 
can be extended by contributing a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/HttpServletRequestFilter.html";>HttpServletRequestFilter</a>
 into the HttpServletRequestHandler service's configuration.</p><p>Tapestry 
does not contribute any filters into this pipeline of its own.</p><p>The 
terminator for the pipeline does two things:</p><ul><li>It stores the request 
and response into the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestGlobals.html";>RequestGlobals</a>
 service. This is a per-thread scoped service that stores 
per-thread/per-request information.</li><li>It wraps the request and response 
as a <a  class="external-link" href="http://tapestry.apache.org/cur
 rent/apidocs/org/apache/tapestry5/services/Request.html">Request</a> and <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Response.html";>Response</a>,
 and passes them into the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestHandler.html";>RequestHandler</a>
 pipeline.</li></ul><h2 
id="RequestProcessing-RequestHandlerPipeline">RequestHandler 
Pipeline</h2><p>This pipeline is where most extensions related to requests take 
place. Request represents an abstraction on top of HttpServletRequest. 
(Primarily, this exists to bridge from the Servlet API objects to the 
corresponding Tapestry objects. This is to allow for a possible portlet 
integration for Tapestry.) Where other code and services within Tapestry 
require access to information in the request, such as query parameters, that 
information is obtained from the Request (or Response) objects.</p><p>The 
RequestHandler pipe
 line includes a number of built-in filters:</p><ul><li>CheckForUpdates is 
responsible for <a  href="request-processing.html">class and template 
reloading</a>.</li><li>Localization identifies the <a  
href="request-processing.html">locale for the user</a>.</li><li>StaticFiles 
checks for URLs that are for static files (files that exist inside the web 
context) and aborts the request, so that the servlet container can handle the 
request normally.</li><li>ErrorFilter catches uncaught exceptions from the 
lower levels of Tapestry and presents the exception report page. This involves 
the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestExceptionHandler.html";>RequestExceptionHandler</a>
 service, which is responsible for initializing and rendering the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/pages/ExceptionReport.html";>core/ExceptionReport</a>
 page.</li></ul><p>The term
 inator for this pipeline stores the Request and the Response into 
RequestGlobals, then requests that the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Dispatcher.html";>MasterDispatcher</a>
 service figure out how to handle the request (if it is, indeed, a Tapestry 
request).</p><h2 id="RequestProcessing-MasterDispatcherService">Master 
Dispatcher Service</h2><p>The MasterDispatcher service is a chain-of-command, 
aggregating together (in a specific order), several Dispatcher objects. Each 
Dispatcher is built to recognize and process a particular kind of URL.</p><h3 
id="RequestProcessing-RootPathDispatcher">RootPath Dispatcher</h3><p>The 
RootPath Dispatcher recognizes a request for the application root (i.e., "/") 
and handles this the same as a render request for the "Start" page. Support for 
the Start page is kept for legacy purposes. Index pages are the correct 
approach.</p><h3 id="RequestProcessing-AssetDispatcher">Asset Dispa
 tcher</h3><p>Requests that begin with "/assets/" are references to <a  
href="request-processing.html">asset resources</a> that are stored on the 
classpath, inside the Tapestry JARs (or perhaps inside the JAR for a component 
library). The contents of the file will be delivered to the client browser as a 
byte stream. This dispatcher also handles requests that are simply polling for 
a change to the file.</p><h3 
id="RequestProcessing-PageRenderDispatcher">PageRender Dispatcher</h3><p>Page 
render requests are requests to render a particular page. Such requests may 
include additional elements on the path, which will be treated as activation 
context (see ComponentEvent Dispatcher below). Generally speaking, the 
activation context is the primary key of some related entity object. This 
allows the page to reconstruct the state it will need to successfully render 
itself.</p><p>The event handler method for the activate event may return a 
value; this is treated the same as the return value from 
 a component action request; typically this will result in a redirect to 
another page. In this way, the activate event can perform simple validation at 
the page level ("can the user see this page?").</p><p>Page render URLs consist 
of the logical name of the page plus additional path elements for the 
activation context. The dispatcher here strips terms off of the path until it 
finds a known page name. Thus, "/mypage/27" would look first for a page whose 
name was "mypage/27", then look for a page name "mypage". Assuming the second 
search was successful, the page would be activated with the context "27". If no 
logical page name can be identified, control passes to the next 
dispatcher.</p><h3 
id="RequestProcessing-ComponentEventDispatcher">ComponentEvent 
Dispatcher</h3><p>The ComponentEvent dispatcher is used to trigger events in 
components.</p><p>The URL identifies the name of the page, then a series of 
component ids (the path from the page down to the specific component), then the 
name
  of the event to be triggered on the component. The remaining path elements 
are used as the context for the <em>event</em> (not for the page activation, 
which does not currently apply). For example, "/griddemo.FOO.BAR/3" would 
locate page "griddemo", then component "FOO.BAR", and trigger an event named 
"action" (the default event type, which is omitted from the URL), with the 
context "3".</p><p>If the page in question has an activation context, it is 
supplied as an additional query parameter on the link.</p><p>In cases where the 
event type is not the default, "action", it will appear between the nested 
component id and the event context, preceded by a colon. Example: 
"/example/foo.bar:magic/99" would trigger an event of type "magic". This is not 
common in the vanilla Tapestry framework, but will likely be more common as 
Ajax features (which would not use the normal request logic) are 
implemented.</p><p>The response from a component action request is typically, 
but not universally, u
 sed to send a redirect to the client; the redirect URL is a page render URL to 
display the response to the event. This is detailed under <a  
href="request-processing.html">Request Processing</a>.</p><h2 
id="RequestProcessing-RequestGlobalsService">RequestGlobals Service</h2><p>The 
RequestGlobals service has a life cycle of per-thread; this means that a 
separate instance exists for every thread, and therefore, for every request. 
The terminators of the two handler pipelines store the request/response pairs 
into the RequestGlobals service.</p><h2 
id="RequestProcessing-RequestService">Request Service</h2><p>The Request 
service is a <a  href="request-processing.html">shadow</a> of the 
RequestGlobals services' request property. That is, any methods invoked on this 
service are delegated to the request object stored inside the 
RequestGlobals.</p><h2 id="RequestProcessing-Overview">Overview</h2><p>The 
following diagram provides an overview of how the different pipelines, filters 
and dispatch
 ers interact when processing an incoming request.</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource confluence-content-image-border" 
src="https://cwiki-test.apache.org/confluence/download/attachments/22872133/tapestry_request_processing_800.png?version=1&amp;modificationDate=1299128361000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/22872133/tapestry_request_processing_800.png?version=1&amp;modificationDate=1299128361000&amp;api=v2";></span></p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/response-compression.html
==============================================================================
--- websites/production/tapestry/content/response-compression.html (original)
+++ websites/production/tapestry/content/response-compression.html Sat Feb  3 
16:21:22 2018
@@ -36,13 +36,26 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div></div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div>
+
+</div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form 
enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";> 
- <input type="text" name="q"> 
- <input type="submit" value="Search"> 
-</form></div><div class="emblem" style="float:left"><p><a  
href="index.html"><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div><div
 class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Response Compression</h1></div></div>
+            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";>
+  <input type="text" name="q">
+  <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a  href="index.html"><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Response Compression</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -54,25 +67,49 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>Starting in Tapestry 5.1, the 
framework automatically GZIP <strong>compresses</strong> content streamed to 
the client. This can significantly reduce the amount of network traffic for a 
Tapestry application, at the cost of extra processing time on the server to 
compress the response stream.</p><div class="aui-label" style="float:right" 
title="Related Articles"><h3>Related Articles</h3><ul 
class="content-by-label"><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="request-processing.html">Request Processing</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="configuration.html">Configuration</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="assets.html">Assets</a> 
-  </div> </li></ul></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="configuration.html">Configuration</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  cla
 ss="external-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="page-navigation.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 id="ConfluenceContent"><p>Starting in Tapestry 5.1, the 
framework automatically GZIP <strong>compresses</strong> content streamed to 
the client. This can significantly reduce the amount of network traffic for a 
Tapestry application, at the cost of extra processing time on the server to 
compress the response stream.</p><div class="aui-label" style="float:right" 
title="Related Articles">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="request-processing.html">Request 
Processing</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="configuration.html">Configuration</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="assets.html">Assets</a>
+                
+                        
+                    </div>
+    </li></ul>
+</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>
       </div>
 
       <div class="clearer"></div>


Reply via email to