Author: buildbot
Date: Mon Feb 19 03:21:26 2018
New Revision: 1025579

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    websites/production/tapestry/content/google-app-engine.html
    
websites/production/tapestry/content/ioc-cookbook-overriding-ioc-services.html
    websites/production/tapestry/content/ioc-cookbook-patterns.html
    
websites/production/tapestry/content/ioc-cookbook-service-configurations.html
    websites/production/tapestry/content/performance-and-clustering.html
    websites/production/tapestry/content/using-select-with-a-list.html

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

Modified: websites/production/tapestry/content/google-app-engine.html
==============================================================================
--- websites/production/tapestry/content/google-app-engine.html (original)
+++ websites/production/tapestry/content/google-app-engine.html Mon Feb 19 
03:21:26 2018
@@ -86,7 +86,7 @@
              configuration.add(IOCSymbols.THREAD_POOL_ENABLED, "false");
              ...
 &#160;&#160;&#160;&#160; }</pre>
-</div></div><p>NOTE: Setting production mode to true is generally only 
desirable in production and QA/testing environments, but you can override that 
symbol with a JVM system property 
(<code>-Dtapestry.production-mode=false</code>) in those environments.</p><h2 
id="GoogleAppEngine-SerializableObjects">Serializable Objects</h2><ul><li>Make 
sure all objects that you store in the servlet session -- particularly those 
annotated with @SessionState and&#160;@SessionAttribute&#160;&#8211; are 
actually serializable types. Otherwise you may see strange behavior in which 
objects seem to lose their session values.</li></ul><h2 
id="GoogleAppEngine-FileUploads">File Uploads</h2><ul><li>If you use the 
Tapestry-upload module (or any file upload mechanism, for that matter), you'll 
need to be sure that it is configured to <em>not</em> store temporary uploaded 
files on the file system.&#160; See <a  href="google-app-engine.html">Google 
App Engine</a>&#160;&#8211; particularly the <code>upload.reposit
 ory-threshold</code> symbol, which should be set to a large 
value.</li></ul><h2 id="GoogleAppEngine-OtherConsiderations">Other 
Considerations</h2><p>Other than the above settings, Tapestry should provide no 
impediment to running your app under Google App Engine. However, you still need 
to adhere to all of GAE's usual constraints (as with any app, Tapestry or 
otherwise). Please carefully read Google's documentation for general guidelines 
for creating an app that is compatible with GAE.</p></div>
+</div></div><p>NOTE: Setting production mode to true is generally only 
desirable in production and QA/testing environments, but you can override that 
symbol with a JVM system property 
(<code>-Dtapestry.production-mode=false</code>) in those environments.</p><h2 
id="GoogleAppEngine-SerializableObjects">Serializable Objects</h2><ul><li>Make 
sure all objects that you store in the servlet session -- particularly those 
annotated with @SessionState and&#160;@SessionAttribute&#160;&#8211; are 
actually serializable types. Otherwise you may see strange behavior in which 
objects seem to lose their session values.</li></ul><h2 
id="GoogleAppEngine-FileUploads">File Uploads</h2><ul><li>If you use the 
Tapestry-upload module (or any file upload mechanism, for that matter), you'll 
need to be sure that it is configured to <em>not</em> store temporary uploaded 
files on the file system.&#160; See&#160;<a  
href="uploading-files.html">Uploading Files</a> &#8211; particularly the 
<code>upload.repository-
 threshold</code> symbol, which should be set to a large value.</li></ul><h2 
id="GoogleAppEngine-OtherConsiderations">Other Considerations</h2><p>Other than 
the above settings, Tapestry should provide no impediment to running your app 
under Google App Engine. However, you still need to adhere to all of GAE's 
usual constraints (as with any app, Tapestry or otherwise). Please carefully 
read Google's documentation for general guidelines for creating an app that is 
compatible with GAE.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: 
websites/production/tapestry/content/ioc-cookbook-overriding-ioc-services.html
==============================================================================
--- 
websites/production/tapestry/content/ioc-cookbook-overriding-ioc-services.html 
(original)
+++ 
websites/production/tapestry/content/ioc-cookbook-overriding-ioc-services.html 
Mon Feb 19 03:21:26 2018
@@ -77,14 +77,14 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><h1 
id="IoCCookbook-OverridingIoCServices-OverridingTapestryIoCServices">Overriding 
Tapestry IoC Services</h1><p>Tapestry is designed to be easy to customize, and 
the IoC container is the key to that customizability.</p><p>One of Tapestry's 
most important activities is resolving injected objects; that is, when Tapestry 
is building an object or service and sees a constructor parameter or a field, 
it must decide what value to plug in. Most of the time, the injected object is 
a service defined elsewhere within the Tapestry IoC container.</p><p>However, 
there are cases where you might want to override how Tapestry operates in some 
specific way.</p><p>The strategy used to determine what object gets injected is 
<a  href="ioc-cookbook-overriding-ioc-services.html">defined inside Tapestry 
IoC itself</a>; thus we can take advantage of several features of the Tapestry 
IoC container in order to take control over specific injections.</p><h2 
id="IoCCoo
 kbook-OverridingIoCServices-ContributingaServiceOverride">Contributing a 
Service Override</h2><p>In most cases, services are injected by matching just 
the type; there is no @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html";>InjectService</a>
 annotation, just a method or constructor parameter whose type matches the 
service's interface.</p><p>In this case, it is very easy to supply your own 
alternate implementation of a service, by <em>contributing</em><em> a Service 
Override</em> in your module class (usually AppModule.java), like this:</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 id="ConfluenceContent"><h1 
id="IoCCookbook-OverridingIoCServices-OverridingTapestryIoCServices">Overriding 
Tapestry IoC Services</h1><p>Tapestry is designed to be easy to customize, and 
the IoC container is the key to that customizability.</p><p>One of Tapestry's 
most important activities is resolving injected objects; that is, when Tapestry 
is building an object or service and sees a constructor parameter or a field, 
it must decide what value to plug in. Most of the time, the injected object is 
a service defined elsewhere within the Tapestry IoC container.</p><p>However, 
there are cases where you might want to override how Tapestry operates in some 
specific way.</p><p>The strategy used to determine what object gets injected is 
<a  href="injection-in-detail.html">defined inside Tapestry IoC itself</a>; 
thus we can take advantage of several features of the Tapestry IoC container in 
order to take control over specific injections.</p><h2 
id="IoCCookbook-OverridingI
 oCServices-ContributingaServiceOverride">Contributing a Service 
Override</h2><p>In most cases, services are injected by matching just the type; 
there is no @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html";>InjectService</a>
 annotation, just a method or constructor parameter whose type matches the 
service's interface.</p><p>In this case, it is very easy to supply your own 
alternate implementation of a service, by <em>contributing</em><em> a Service 
Override</em> in your module class (usually AppModule.java), like this:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 1px;"><b>AppModule.java 
(partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Contribute(ServiceOverride.class)
   public static void 
setupApplicationServiceOverrides(MappedConfiguration&lt;Class,Object&gt; 
configuration)
   {
     configuration.addInstance(SomeServiceType.class, 
SomeServiceTypeOverrideImpl.class);
   }
 </pre>
-</div></div><p>The name of the method is not important, as long as the @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Contribute.html";>Contribute</a>
 annotation is present on the method.</p><p>In this example, we are using 
<code>addInstance()</code> which will instantiate the indicated class and 
handle dependency resolution. (Be careful with this, because in some cases, 
resolving dependencies of the override class can require checking against the 
ServiceOverrides service, and you'll get a runtime exception about 
ServiceOverrides requiring itself!).</p><p>Sometimes you'll want to define the 
override as a service of its own. This is useful if you want to inject a Logger 
specific to the service, or if the overriding implementation needs a <a  
href="ioc-cookbook-overriding-ioc-services.html">service 
configuration</a>:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeHeader panelHeader pdl" style="
 border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div 
class="codeContent panelContent pdl">
+</div></div><p>The name of the method is not important, as long as the @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Contribute.html";>Contribute</a>
 annotation is present on the method.</p><p>In this example, we are using 
<code>addInstance()</code> which will instantiate the indicated class and 
handle dependency resolution. (Be careful with this, because in some cases, 
resolving dependencies of the override class can require checking against the 
ServiceOverrides service, and you'll get a runtime exception about 
ServiceOverrides requiring itself!).</p><p>Sometimes you'll want to define the 
override as a service of its own. This is useful if you want to inject a Logger 
specific to the service, or if the overriding implementation needs a <a  
href="tapestry-ioc-configuration.html">service configuration</a>:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bot
 tom-width: 1px;"><b>AppModule.java (partial)</b></div><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  public static void bind(ServiceBinder binder)
   {
     binder.bind(SomeServiceType.class, 
SomeServiceTypeOverrideImpl.class).withId("SomeServiceTypeOverride");
@@ -96,7 +96,7 @@
     configuration.add(SomeServiceType.class, override);
   }
 </pre>
-</div></div><p>Here we're defining a service using the module's 
<code>bind()</code> method.</p><p>Every service in the IoC container must have 
a unique id, that's why we used the <code>withId()</code> method; if we we 
hadn't, the default service id would have been "SomeServiceType" which is a 
likely conflict with the very service we're trying to override.</p><p>We can 
inject our overriding implementation of SomeServiceType using the special @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Local.html";>Local</a>
 annotation, which indicates that a service within the same module only should 
be injected (that is, services of the indicated type in other modules are 
ignored). Without @Local, there would be a problem because the override 
parameter would need to be resolved using the MasterObjectProvider and, 
ultimately, the ServiceOverride service; this would cause Tapestry to throw an 
exception indicating that ServiceOverride depe
 nds on itself. We defuse that situation by using @Local, which prevents the 
MasterObjectProvider service from being used to resolve the override 
parameter.</p><h2 
id="IoCCookbook-OverridingIoCServices-DecoratingServices">Decorating 
Services</h2><p>Another option is to <a  
href="ioc-cookbook-overriding-ioc-services.html">decorate</a> the existing 
service. Perhaps you want to extend some of the behavior of the service but 
keep the rest.</p><p>Alternately, this approach is useful to override a service 
that is matched using marker annotations.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div 
class="codeContent panelContent pdl">
+</div></div><p>Here we're defining a service using the module's 
<code>bind()</code> method.</p><p>Every service in the IoC container must have 
a unique id, that's why we used the <code>withId()</code> method; if we we 
hadn't, the default service id would have been "SomeServiceType" which is a 
likely conflict with the very service we're trying to override.</p><p>We can 
inject our overriding implementation of SomeServiceType using the special @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Local.html";>Local</a>
 annotation, which indicates that a service within the same module only should 
be injected (that is, services of the indicated type in other modules are 
ignored). Without @Local, there would be a problem because the override 
parameter would need to be resolved using the MasterObjectProvider and, 
ultimately, the ServiceOverride service; this would cause Tapestry to throw an 
exception indicating that ServiceOverride depe
 nds on itself. We defuse that situation by using @Local, which prevents the 
MasterObjectProvider service from being used to resolve the override 
parameter.</p><h2 
id="IoCCookbook-OverridingIoCServices-DecoratingServices">Decorating 
Services</h2><p>Another option is to <a  
href="tapestry-ioc-decorators.html">decorate</a> the existing service. Perhaps 
you want to extend some of the behavior of the service but keep the 
rest.</p><p>Alternately, this approach is useful to override a service that is 
matched using marker annotations.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div 
class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  public SomeServiceType decorateSomeServiceType(final 
SomeServiceType delegate)
   {
     return new SomeServiceType() { . . . };

Modified: websites/production/tapestry/content/ioc-cookbook-patterns.html
==============================================================================
--- websites/production/tapestry/content/ioc-cookbook-patterns.html (original)
+++ websites/production/tapestry/content/ioc-cookbook-patterns.html Mon Feb 19 
03:21:26 2018
@@ -128,7 +128,7 @@
 </div>
 
 
-<p>The basis for these patterns is often the use of <em>service builder 
methods</em>, where a <a  href="ioc-cookbook-patterns.html">configuration</a> 
for the service is combined with a factory to produce the service 
implementation on the fly.</p><p><span class="confluence-anchor-link" 
id="IoCCookbook-Patterns-chainofcommand"></span></p><h1 
id="IoCCookbook-Patterns-ChainofCommandPattern">Chain of Command 
Pattern</h1><p>Main Article: <a  href="ioc-cookbook-patterns.html">Chain of 
Command</a></p><p>Let's look at another example, again from the Tapestry code 
base. The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/InjectionProvider.html";>InjectProvider</a>
 interface is used to process the @Inject annotation on the fields of a 
Tapestry page or component. Many different instances are combined together to 
form a <em>chain of command</em>.</p><p>The interface has only a single method 
(this is far from uncommon):</p><div class="code p
 anel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<p>The basis for these patterns is often the use of <em>service builder 
methods</em>, where a <a  
href="ioc-cookbook-service-configurations.html">configuration</a> for the 
service is combined with a factory to produce the service implementation on the 
fly.</p><p><span class="confluence-anchor-link" 
id="IoCCookbook-Patterns-chainofcommand"></span></p><h1 
id="IoCCookbook-Patterns-ChainofCommandPattern">Chain of Command 
Pattern</h1><p>Main Article: <a  href="chainbuilder-service.html">Chain of 
Command</a></p><p>Let's look at another example, again from the Tapestry code 
base. The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/InjectionProvider.html";>InjectProvider</a>
 interface is used to process the @Inject annotation on the fields of a 
Tapestry page or component. Many different instances are combined together to 
form a <em>chain of command</em>.</p><p>The interface has only a single method 
(this is far from uncommon):</p><div 
 class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public interface InjectionProvider
 {
   boolean provideInjection(String fieldName, Class fieldType, ObjectLocator 
locator,

Modified: 
websites/production/tapestry/content/ioc-cookbook-service-configurations.html
==============================================================================
--- 
websites/production/tapestry/content/ioc-cookbook-service-configurations.html 
(original)
+++ 
websites/production/tapestry/content/ioc-cookbook-service-configurations.html 
Mon Feb 19 03:21:26 2018
@@ -103,7 +103,7 @@
 
   . . .
 }</pre>
-</div></div><p>In many cases, the configuration is simply stored into an 
instance variable; in this example, the value is transformed from a Collection 
to a Set.</p><p>These kinds of unordered configurations are surprisingly rare 
in Tapestry (the only other notable one is for the <a  
href="ioc-cookbook-service-configurations.html">TypeCoercer</a> service). 
However, as you can see, setting up such a configuration is quite easy.</p><h1 
id="IoCcookbook-ServiceConfigurations-OrderedConfigurations">Ordered 
Configurations</h1><p>Ordered configurations are very similar to unordered 
configurations ... the difference is that the configuration is provided to the 
service as a parameter of type List. This is used when the order of operations 
counts. Often these configurations are related to a design pattern such as <a  
href="ioc-cookbook-service-configurations.html">Chain of Command</a> or <a  
href="ioc-cookbook-service-configurations.html">Pipeline</a>.</p><p>Here, the 
example is the <a  class
 ="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Dispatcher.html";>Dispatcher</a>
 interface; a Dispatcher inside Tapestry is roughly equivalent to a servlet, 
though a touch more active. It is passed a Request and decides if the URL for 
the Request is something it can handle; if so it will process the request, send 
a response, and return true.</p><p>Alternately, if the Request can't be 
handled, the Dispatcher returns false.</p><div class="code panel pdl" 
style="border-style: solid;border-width: 1px;"><div class="codeContent 
panelContent pdl">
+</div></div><p>In many cases, the configuration is simply stored into an 
instance variable; in this example, the value is transformed from a Collection 
to a Set.</p><p>These kinds of unordered configurations are surprisingly rare 
in Tapestry (the only other notable one is for the <a  
href="ioc-cookbook-service-configurations.html">TypeCoercer</a> service). 
However, as you can see, setting up such a configuration is quite easy.</p><h1 
id="IoCcookbook-ServiceConfigurations-OrderedConfigurations">Ordered 
Configurations</h1><p>Ordered configurations are very similar to unordered 
configurations ... the difference is that the configuration is provided to the 
service as a parameter of type List. This is used when the order of operations 
counts. Often these configurations are related to a design pattern such as <a  
href="chainbuilder-service.html">Chain of Command</a> or <a  
href="pipelinebuilder-service.html">Pipeline</a>.</p><p>Here, the example is 
the <a  class="external-link" href="http
 
://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Dispatcher.html">Dispatcher</a>
 interface; a Dispatcher inside Tapestry is roughly equivalent to a servlet, 
though a touch more active. It is passed a Request and decides if the URL for 
the Request is something it can handle; if so it will process the request, send 
a response, and return true.</p><p>Alternately, if the Request can't be 
handled, the Dispatcher returns false.</p><div class="code panel pdl" 
style="border-style: solid;border-width: 1px;"><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public void 
contributeMasterDispatcher(OrderedConfiguration&lt;Dispatcher&gt; 
configuration, . . .)
 {
   // Looks for the root path and renders the start page
@@ -122,12 +122,12 @@
 
   configuration.add("ComponentAction", new ComponentActionDispatcher(. . .), 
"after:PageRender");
 }</pre>
-</div></div><p>With an <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/OrderedConfiguration.html";>OrderedConfiguration</a>,
 each contribution gets a name, which must be unique. Here the names are 
RootPath, Asset, PageRender and ComponentAction.</p><p>The add() method takes a 
name, the contributed object for that name, and then zero or more optional 
constraints. The constraints control the ordering. The "after:" constraint 
ensures that the contribution is ordered after the other named contribution, 
the "before:" contribution is the opposite.</p><p>The ordering occurs on the 
complete set of contributions, from all modules.</p><p>Here, we need a specific 
order, used to make sure that the Dispatchers don't get confused about which 
URLs are appropriate ... for example, an asset URL might be 
/assets/tapestry5/tapestry.js. This looks just like a component action URL (for 
page "assets/tapestry5/tapestry" and component "js"). Given that sof
 tware is totally lacking in basic common-sense, we instead use careful 
ordering of the Dispatchers to ensure that AssetDispatcher is checked 
<em>before</em> the ComponentAction dispatcher.</p><h2 
id="IoCcookbook-ServiceConfigurations-ReceivingtheConfiguration.1">Receiving 
the Configuration</h2><p>The configuration, once assembled and ordered, is 
provided as a List.</p><p>The MasterDispatcher service configuration defines a 
<a  href="ioc-cookbook-service-configurations.html">Chain of Command</a> and we 
can provide the implementation using virtually no code:</p><div class="code 
panel pdl" style="border-style: solid;border-width: 1px;"><div 
class="codeContent panelContent pdl">
+</div></div><p>With an <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/OrderedConfiguration.html";>OrderedConfiguration</a>,
 each contribution gets a name, which must be unique. Here the names are 
RootPath, Asset, PageRender and ComponentAction.</p><p>The add() method takes a 
name, the contributed object for that name, and then zero or more optional 
constraints. The constraints control the ordering. The "after:" constraint 
ensures that the contribution is ordered after the other named contribution, 
the "before:" contribution is the opposite.</p><p>The ordering occurs on the 
complete set of contributions, from all modules.</p><p>Here, we need a specific 
order, used to make sure that the Dispatchers don't get confused about which 
URLs are appropriate ... for example, an asset URL might be 
/assets/tapestry5/tapestry.js. This looks just like a component action URL (for 
page "assets/tapestry5/tapestry" and component "js"). Given that sof
 tware is totally lacking in basic common-sense, we instead use careful 
ordering of the Dispatchers to ensure that AssetDispatcher is checked 
<em>before</em> the ComponentAction dispatcher.</p><h2 
id="IoCcookbook-ServiceConfigurations-ReceivingtheConfiguration.1">Receiving 
the Configuration</h2><p>The configuration, once assembled and ordered, is 
provided as a List.</p><p>The MasterDispatcher service configuration defines a 
<a  href="chainbuilder-service.html">Chain of Command</a> and we can provide 
the implementation using virtually no code:</p><div class="code panel pdl" 
style="border-style: solid;border-width: 1px;"><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  public static Dispatcher 
buildMasterDispatcher(List&lt;Dispatcher&gt; configuration, ChainBuilder 
chainBuilder)
   {
     return chainBuilder.build(Dispatcher.class, configuration);
   }</pre>
-</div></div><p><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/ChainBuilder.html";>ChainBuilder</a>
 is a service that <em>builds other services</em>. Here it creates an object of 
type Dispatcher in terms of the list of Dispatchers. This is one of the most 
common uses of service builder methods ... for when the service implementation 
doesn't exist, but can be constructed at runtime.</p><h1 
id="IoCcookbook-ServiceConfigurations-MappedConfigurations">Mapped 
Configurations</h1><p>The last type of service configuration is the mapped 
service configuration. Here we relate a key, often a string, to some value. The 
contributions are ultimately combined to form a Map.</p><p>Tapestry IoC's <a  
href="ioc-cookbook-service-configurations.html">symbol</a> mechanism allows 
configuration values to be defined and perhaps overridden, then provided to 
services via injection, using the @<a  class="external-link" 
href="http://tapestry.apache.org
 /current/apidocs/org/apache/tapestry5/ioc/annotations/Value.html">Value</a> 
annotation.</p><p>The first step is to contribute values.</p><div class="code 
panel pdl" style="border-style: solid;border-width: 1px;"><div 
class="codeContent panelContent pdl">
+</div></div><p><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/ChainBuilder.html";>ChainBuilder</a>
 is a service that <em>builds other services</em>. Here it creates an object of 
type Dispatcher in terms of the list of Dispatchers. This is one of the most 
common uses of service builder methods ... for when the service implementation 
doesn't exist, but can be constructed at runtime.</p><h1 
id="IoCcookbook-ServiceConfigurations-MappedConfigurations">Mapped 
Configurations</h1><p>The last type of service configuration is the mapped 
service configuration. Here we relate a key, often a string, to some value. The 
contributions are ultimately combined to form a Map.</p><p>Tapestry IoC's <a  
href="symbols.html">symbol</a> mechanism allows configuration values to be 
defined and perhaps overridden, then provided to services via injection, using 
the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/
 tapestry5/ioc/annotations/Value.html">Value</a> annotation.</p><p>The first 
step is to contribute values.</p><div class="code panel pdl" 
style="border-style: solid;border-width: 1px;"><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  public static void 
contributeFactoryDefaults(MappedConfiguration&lt;String, String&gt; 
configuration)
   {
     configuration.add(SymbolConstants.FILE_CHECK_INTERVAL, "1000"); // 1 second

Modified: websites/production/tapestry/content/performance-and-clustering.html
==============================================================================
--- websites/production/tapestry/content/performance-and-clustering.html 
(original)
+++ websites/production/tapestry/content/performance-and-clustering.html Mon 
Feb 19 03:21:26 2018
@@ -109,7 +109,7 @@
 </div>
 
 
-<h2 id="PerformanceandClustering-PerformanceTips">Performance Tips</h2><p>But 
even with all of Tapestry's built-in speediness, to really get top performance 
you'll need to be sure you're not hamstringing Tapestry. As a start, use the 
following checklist:</p><ul><li>Ensure (be absolutely sure) that <a  
href="performance-and-clustering.html">Production Mode</a> is turned on in 
production.</li><li>Minimize the use of the HTTPSession (see below), especially 
if you're using clustering.</li><li>Set <a  
href="performance-and-clustering.html">tapestry.clustered-sessions</a> to 
"false" if you aren't using clustering.</li><li>Organize your JavaScript files 
into <a  
href="performance-and-clustering.html">JavaScriptStacks</a>.</li><li>Ensure 
that your static resources (images, CSS, JavaScript) are being cached by the 
browser.<ul><li>Use "asset:" or "context:" <a  
href="performance-and-clustering.html">binding prefixes</a> for all links to 
static resources (images, CSS, JavaScript).</li><li>Make
  sure that your firewall, proxy server, load balancer, front-end web servers, 
and app servers all allow caching of static resources.</li><li>Ensure 
"cache-control" and "vary" HTTP headers are set correctly for your static 
resources.</li><li>Use a client-based tool (like Firebug) to examine the 
requests that your browser makes as you navigate through the site. You should 
<em>not</em> see repeated requests for static 
resources.</li></ul></li><li>Consider using a <a  class="external-link" 
href="http://en.wikipedia.org/wiki/Content_delivery_network"; 
rel="nofollow">Content Delivery Network</a> for static parts of your 
site.</li></ul><p>After all of the above issues are addressed, if you still 
have performance problems, they probably aren't related to Tapestry.</p><h2 
id="PerformanceandClustering-ClusteringversusStickySessions">Clustering versus 
Sticky Sessions</h2><p>For web applications, <strong>clustering</strong> is a 
load-balancing technique in which multiple application servers are 
 set up to behave as one big server. Generally this requires replicating 
HttpSession data across the servers, to ensure that a user's web interactions 
will continue without interruption regardless of which server handles the next 
request. Session replication achieves very high reliability, but it incurs an 
extra performance cost (due to the serializing and deserializing of session 
data and the extra network traffic required).</p><p>In contrast, <strong>Sticky 
Sessions</strong> (also called <em>session persistence</em> or <em>sticky 
persistence</em>) is a load balancing technique in which each session is 
assigned to a particular server for the duration of the session. This approach 
doesn't require copying HTTPSession data between servers, so it's very 
scalable. But if a server goes down, all of its sessions are lost.</p><p>In 
general, the sticky sessions approach is the way to go when possible (that is, 
when performance is more important than session survival). It represents a much 
mo
 re efficient use of resources ... you are scaling <em>out</em> not 
<em>up</em>, which is always cheaper. It also means that you don't have to be 
as careful about what goes into the HTTPSession.</p><p><em>For details on 
setting up clustering and sticky sessions, see the documentation of whatever 
load balancer you are using.</em></p><h2 
id="PerformanceandClustering-Clustering">Clustering</h2><p>Tapestry is designed 
to be "a good citizen" of an application server that supports clustering. It is 
careful about what it writes into the HttpSession. The framework understands 
that the server that receives a request may not be the same one that rendered 
the page initially; this knowledge affects many code paths, and it guides the 
approach Tapestry takes to caching page and component properties.</p><p>Your 
part is to properly manage the objects put into the HttpSession (via 
@SessionAttribute, @SessionState or @Persist; see <a  
href="performance-and-clustering.html">Performance and Clustering</
 a>):</p><ul><li>Don't store anything in the session that you don't have to. 
Principally this means minimizing the use of @Persist (see <a  
href="performance-and-clustering.html">Page Activation</a> and <a  
href="performance-and-clustering.html">Performance and Clustering</a>), storing 
only IDs in the session rather than whole entities.</li><li>Where possible, 
persist only objects that are immutable (i.e., String, or a primitive or 
wrapper type).</li><li>Only put <em>serializable</em> objects into the 
session.</li><li>Make use of the @ImmutableSessionPersistedObject annotation 
and OptimizedSessionPersistedObject interface (both described 
below).</li></ul><p>Again, Tapestry is a good citizen, but from the application 
server's point of view, it's just another servlet application. The heavy 
lifting here is application server specific.</p><p></p><h2 
id="PerformanceandClustering-ClusteringIssues">Clustering Issues</h2><p>The 
Servlet API was designed with the intention that there would be 
 only a modest amount of server-side state, and that the stored values would be 
individual numbers and strings, and thus, immutable.</p><p>However, many web 
applications do not use the HttpSession this way, instead storing large, 
mutable objects in the session. This is not a problem for single servers, but 
in a cluster, anything stored in the session must be serialized to a bytestream 
and distributed to other servers within the cluster, and restored 
there.</p><p>Most application servers perform that serialization and 
distribution whenever HttpSession.setAttribute() is called. This creates a data 
consistency problem for mutable objects, because if you read a mutable session 
object, change its state, but <em>don't</em> invoke setAttribute(), the changes 
will be isolated to just a single server in the cluster.</p><p>Tapestry 
attempts to solve this: any session-persisted object that is read during a 
request will be re-stored back into the HttpSession at the end of the request. 
This ensur
 es that changed internal state of those mutable objects is properly replicated 
around the cluster.</p><p>But while this solution solves the data consistency 
problem, it does so at the expense of performance, since all of those calls to 
setAttribute() result in extra session data being replicated needlessly if the 
internal state of the mutable object hasn't changed.</p><p>Tapestry has 
solutions to this, too:</p><h3 
id="PerformanceandClustering-@ImmutableSessionPersistedObjectAnnotation">@ImmutableSessionPersistedObject
 Annotation</h3><p>Tapestry knows that Java's String, Number and Boolean 
classes are immutable. Immutable objects do not require a re-store into the 
session.</p><p>You can mark your own session objects as immutable (and thus not 
requiring session replication) using the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ImmutableSessionPersistedObject.html";>ImmutableSessionPersistedObject</a>
 annotation.</p><h3 id=
 
"PerformanceandClustering-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject
 Interface</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/OptimizedSessionPersistedObject";>OptimizedSessionPersistedObject</a>
 interface allows an object to control this behavior. An object with this 
interface can track when its mutable state changes. Typically, you should 
extend from the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.html";>BaseOptimizedSessionPersistedObject</a>
 base class.</p><h3 
id="PerformanceandClustering-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer
 Service</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.html";>SessionPersistedObjectAnalyzer</a>
 service is ultimately responsible for determining whethe
 r 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>
+<h2 id="PerformanceandClustering-PerformanceTips">Performance Tips</h2><p>But 
even with all of Tapestry's built-in speediness, to really get top performance 
you'll need to be sure you're not hamstringing Tapestry. As a start, use the 
following checklist:</p><ul><li>Ensure (be absolutely sure) that <a  
href="configuration.html">Production Mode</a> is turned on in 
production.</li><li>Minimize the use of the HTTPSession (see below), especially 
if you're using clustering.</li><li>Set <a  
href="configuration.html">tapestry.clustered-sessions</a> to "false" if you 
aren't using clustering.</li><li>Organize your JavaScript files into <a  
href="legacy-javascript.html">JavaScriptStacks</a>.</li><li>Ensure that your 
static resources (images, CSS, JavaScript) are being cached by the 
browser.<ul><li>Use "asset:" or "context:" <a  
href="component-parameters.html">binding prefixes</a></li><li>&#160;for all 
links to static resources (images, CSS, JavaScript).</li><li>Make sure that 
your firewall, p
 roxy server, load balancer, front-end web servers, and app servers all allow 
caching of static resources.</li><li>Ensure "cache-control" and "vary" HTTP 
headers are set correctly for your static resources.</li><li>Use a client-based 
tool (like Firebug) to examine the requests that your browser makes as you 
navigate through the site. You should <em>not</em> see repeated requests for 
static resources.</li></ul></li><li>Consider using a <a  class="external-link" 
href="http://en.wikipedia.org/wiki/Content_delivery_network"; 
rel="nofollow">Content Delivery Network</a> for static parts of your 
site.</li></ul><p>After all of the above issues are addressed, if you still 
have performance problems, they probably aren't related to Tapestry.</p><h2 
id="PerformanceandClustering-ClusteringversusStickySessions">Clustering versus 
Sticky Sessions</h2><p>For web applications, <strong>clustering</strong> is a 
load-balancing technique in which multiple application servers are set up to 
behave as one big
  server. Generally this requires replicating HttpSession data across the 
servers, to ensure that a user's web interactions will continue without 
interruption regardless of which server handles the next request. Session 
replication achieves very high reliability, but it incurs an extra performance 
cost (due to the serializing and deserializing of session data and the extra 
network traffic required).</p><p>In contrast, <a  class="external-link" 
href="https://en.wikipedia.org/wiki/Load_balancing_(computing)#Persistence" 
rel="nofollow"><strong>Sticky Sessions</strong></a> (also called <em>session 
persistence</em> or <em>sticky persistence</em>) is a load balancing technique 
in which each session is assigned to a particular server for the duration of 
the session. This approach doesn't require copying HTTPSession data between 
servers, so it's very scalable. But if a server goes down, all of its sessions 
are lost.</p><p>In general, the sticky sessions approach is the way to go when 
possibl
 e (that is, when performance is more important than session survival). It 
represents a much more efficient use of resources ... you are scaling 
<em>out</em> not <em>up</em>, which is always cheaper. It also means that you 
don't have to be as careful about what goes into the HTTPSession.</p><p><em>For 
details on setting up clustering and sticky sessions, see the documentation of 
whatever load balancer you are using.</em></p><h2 
id="PerformanceandClustering-Clustering">Clustering</h2><p>Tapestry is designed 
to be "a good citizen" of an application server that supports clustering. It is 
careful about what it writes into the HttpSession. The framework understands 
that the server that receives a request may not be the same one that rendered 
the page initially; this knowledge affects many code paths, and it guides the 
approach Tapestry takes to caching page and component properties.</p><p>Your 
part is to properly manage the objects put into the HttpSession (via 
@SessionAttribute, @Session
 State or @Persist; see <a  href="performance-and-clustering.html">Performance 
and Clustering</a>):</p><ul><li>Don't store anything in the session that you 
don't have to. Principally this means minimizing the use of @Persist (see <a  
href="page-navigation.html">Page Activation</a> and <a  
href="using-select-with-a-list.html">Using Select With a List</a>), storing 
only IDs in the session rather than whole entities.</li><li>Where possible, 
persist only objects that are immutable (i.e., String, or a primitive or 
wrapper type).</li><li>Only put <em>serializable</em> objects into the 
session.</li><li>Make use of the @ImmutableSessionPersistedObject annotation 
and OptimizedSessionPersistedObject interface (both described 
below).</li></ul><p>Again, Tapestry is a good citizen, but from the application 
server's point of view, it's just another servlet application. The heavy 
lifting here is application server specific.</p><p></p><h2 
id="PerformanceandClustering-ClusteringIssues">Clustering Iss
 ues</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 wi
 ll be re-stored back into the HttpSession at the end of the request. This 
ensures that changed internal state of those mutable objects is properly 
replicated around the cluster.</p><p>But while this solution solves the data 
consistency problem, it does so at the expense of performance, since all of 
those calls to setAttribute() result in extra session data being replicated 
needlessly if the internal state of the mutable object hasn't 
changed.</p><p>Tapestry has solutions to this, too:</p><h3 
id="PerformanceandClustering-@ImmutableSessionPersistedObjectAnnotation">@ImmutableSessionPersistedObject
 Annotation</h3><p>Tapestry knows that Java's String, Number and Boolean 
classes are immutable. Immutable objects do not require a re-store into the 
session.</p><p>You can mark your own session objects as immutable (and thus not 
requiring session replication) using the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ImmutableSessionP
 ersistedObject.html">ImmutableSessionPersistedObject</a> annotation.</p><h3 
id="PerformanceandClustering-OptimizedSessionPersistedObjectInterface">OptimizedSessionPersistedObject
 Interface</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/OptimizedSessionPersistedObject";>OptimizedSessionPersistedObject</a>
 interface allows an object to control this behavior. An object with this 
interface can track when its mutable state changes. Typically, you should 
extend from the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.html";>BaseOptimizedSessionPersistedObject</a>
 base class.</p><h3 
id="PerformanceandClustering-SessionPersistedObjectAnalyzerService">SessionPersistedObjectAnalyzer
 Service</h3><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.html";>SessionPersi
 stedObjectAnalyzer</a> service is ultimately responsible for determining 
whether a session persisted object is dirty or not (dirty meaning in need of a 
restore into the session). This is an extensible service where new strategies, 
for new classes, can be introduced.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/using-select-with-a-list.html
==============================================================================
--- websites/production/tapestry/content/using-select-with-a-list.html 
(original)
+++ websites/production/tapestry/content/using-select-with-a-list.html Mon Feb 
19 03:21:26 2018
@@ -77,10 +77,10 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><h1 
id="UsingSelectWithaList-UsingSelectWithaList">Using Select With a 
List</h1><p>The documentation for the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Select.html";>Select
 Component</a> and the <a  href="using-select-with-a-list.html">Tapestry 
Tutorial</a> provide simplistic examples of populating a drop-down menu (as the 
(X)HTML <em>Select</em> element) using comma-delimited strings and enums. 
However, most real-world Tapestry applications need to populate such menus 
using values from a database, commonly in the form of java.util.List objects. 
Doing so generally requires a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/SelectModel.html";>SelectModel</a>
 and a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ValueEncoder.html";>ValueEncoder</a>
 bound to the Select component wi
 th its "model" and "encoder" parameters:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+                <div id="ConfluenceContent"><h1 
id="UsingSelectWithaList-UsingSelectWithaList">Using Select With a 
List</h1><p>The documentation for the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Select.html";>Select
 Component</a> and the <a  href="tapestry-tutorial.html">Tapestry Tutorial</a> 
provide simplistic examples of populating a drop-down menu (as the (X)HTML 
<em>Select</em> element) using comma-delimited strings and enums. However, most 
real-world Tapestry applications need to populate such menus using values from 
a database, commonly in the form of java.util.List objects. Doing so generally 
requires a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/SelectModel.html";>SelectModel</a>
 and a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ValueEncoder.html";>ValueEncoder</a>
 bound to the Select component with its 
 "model" and "encoder" parameters:</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;">&lt;t:select t:id="colorMenu" value="selectedColor" 
model="ColorSelectModel" encoder="colorEncoder" /&gt;
 </pre>
-</div></div><p>In the above example, ColorSelectModel must be of type 
SelectModel, or anything that Tapestry knows how to <a  
href="using-select-with-a-list.html">coerce</a> into a SelectModel, such as a 
List or a Map or a "value=label,value=label,..." delimited string, or anything 
Tapestry knows how to coerce into a List or Map, such as an Array or a 
comma-delimited String.</p><h2 
id="UsingSelectWithaList-SelectModel">SelectModel</h2><p></p><div 
class="navmenu" style="float:right; background:#eee; margin:3px; padding:0 1em">
+</div></div><p>In the above example, ColorSelectModel must be of type 
SelectModel, or anything that Tapestry knows how to <a  
href="parameter-type-coercion.html">coerce</a> into a SelectModel, such as a 
List or a Map or a "value=label,value=label,..." delimited string, or anything 
Tapestry knows how to coerce into a List or Map, such as an Array or a 
comma-delimited String.</p><h2 
id="UsingSelectWithaList-SelectModel">SelectModel</h2><p></p><div 
class="navmenu" style="float:right; background:#eee; margin:3px; padding:0 1em">
 <p>    <strong>JumpStart Demos:</strong><br clear="none">
     <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/select/totalcontrolobject";
 rel="nofollow">Total Control Object Select</a><br clear="none">
     <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/select/id"; 
rel="nofollow">ID Select</a><br clear="none">
@@ -107,7 +107,7 @@ public String toString() {
 </pre>
 </div></div><p>But that is contorting the purpose of the toString() method, 
and if you go to that much trouble you're already half way to the recommended 
practice: creating a ValueEncoder.</p><h2 
id="UsingSelectWithaList-ValueEncoder">ValueEncoder</h2><p>In addition to a 
SelectModel, your Select menu is likely to need a ValueEncoder. While a 
SelectModel is concerned only with how to construct a Select menu, a 
ValueEncoder is used when constructing the Select menu <em>and</em> when 
interpreting the encoded value that is submitted back to the server. A 
ValueEncoder is a converter between the type of objects you want to represent 
as options in the menu and the client-side encoded values that uniquely 
identify them, and vice-versa.</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/select/easyobject";
 rel="nofollow">Easy Object Select</a></p></div>Most commonly, your 
ValueEncoder's toClient() method will return a unique ID (e.g. a database 
primary key, or perhaps a UUID) of the given object, and its toValue() method 
will return the <em>object</em> matching the given ID by doing a database 
lookup (ideally using a service or DAO method).<p>If you're using one of the 
ORM integration modules (<a  
href="using-select-with-a-list.html">Tapestry-Hibernate</a>, <a  
href="using-select-with-a-list.html">Tapestry-JPA</a>, or <a  
class="external-link" 
href="http://code.google.com/p/tapestry5-cayenne/wiki/ValueEncoder"; 
rel="nofollow">Tapestry-Cayenne</a>), the ValueEncoder is automatically 
provided for each of your mapped entity classes. The Hibernate module's 
implementation is typical: the primary key field of the object (converted to a 
String) is used as the client-side value, and
  that same primary key is used to look up the selected object.</p><p>That's 
exactly what you should do in your own ValueEncoders too:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>ColorEncoder.java (perhaps in your 
com.example.myappname.encoders package)</b></div><div class="codeContent 
panelContent pdl">
+    <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/select/easyobject";
 rel="nofollow">Easy Object Select</a></p></div>Most commonly, your 
ValueEncoder's toClient() method will return a unique ID (e.g. a database 
primary key, or perhaps a UUID) of the given object, and its toValue() method 
will return the <em>object</em> matching the given ID by doing a database 
lookup (ideally using a service or DAO method).<p>If you're using one of the 
ORM integration modules (<a  href="hibernate.html">Tapestry-Hibernate</a>, <a  
href="integrating-with-jpa.html">Tapestry-JPA</a>, or <a  class="external-link" 
href="http://code.google.com/p/tapestry5-cayenne/wiki/ValueEncoder"; 
rel="nofollow">Tapestry-Cayenne</a>), the ValueEncoder is automatically 
provided for each of your mapped entity classes. The Hibernate module's 
implementation is typical: the primary key field of the object (converted to a 
String) is used as the client-side value, and that same primary 
 key is used to look up the selected object.</p><p>That's exactly what you 
should do in your own ValueEncoders too:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>ColorEncoder.java (perhaps in your 
com.example.myappname.encoders package)</b></div><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public class ColorEncoder implements 
ValueEncoder&lt;Color&gt;, ValueEncoderFactory&lt;Color&gt; { 
 
     @Inject
@@ -169,7 +169,7 @@ public String toString() {
         configuration.addInstance(SomeOtherType.class, 
SomeOtherTypeEncoder.class);
     }
 </pre>
-</div></div><h2 id="UsingSelectWithaList-WhatifIomittheValueEncoder?">What if 
I omit the ValueEncoder?</h2><p>The Select component's "encoder" parameter is 
optional, but if the "value" parameter is bound to a complex object (not a 
simple String, Integer, etc.) and you don't provide a ValueEncoder with the 
"encoder" parameter (and one isn't provided automatically by, for example, the 
Tapestry Hibernate integration), you'll receive a "Could not find a coercion" 
exception (when you submit the form) as Tapestry tries to convert the selected 
option's encoded value back to the <em>object</em> in your Select's "value" 
parameter. To fix this, you'll either have to 1) provide a ValueEncoder, 2) 
provide a <a  href="using-select-with-a-list.html">Coercion</a>, or 3) use a 
simple value (String, Integer, etc.) for your Select's "value" parameter, and 
then you'll have to add logic in the corresponding onSuccess event listener 
method:</p><div class="code panel pdl" style="border-width: 1px;"><div 
 class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>SelectWithListDemo.tml (partial)</b></div><div class="codeContent 
panelContent pdl">
+</div></div><h2 id="UsingSelectWithaList-WhatifIomittheValueEncoder?">What if 
I omit the ValueEncoder?</h2><p>The Select component's "encoder" parameter is 
optional, but if the "value" parameter is bound to a complex object (not a 
simple String, Integer, etc.) and you don't provide a ValueEncoder with the 
"encoder" parameter (and one isn't provided automatically by, for example, the 
Tapestry Hibernate integration), you'll receive a "Could not find a coercion" 
exception (when you submit the form) as Tapestry tries to convert the selected 
option's encoded value back to the <em>object</em> in your Select's "value" 
parameter. To fix this, you'll either have to 1) provide a ValueEncoder, 2) 
provide a <a  href="type-coercion.html">Coercion</a>, or 3) use a simple value 
(String, Integer, etc.) for your Select's "value" parameter, and then you'll 
have to add logic in the corresponding onSuccess event listener method:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="code
 Header panelHeader pdl" style="border-bottom-width: 
1px;"><b>SelectWithListDemo.tml (partial)</b></div><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;t:select t:id="colorMenu" value="selectedColorId" 
model="ColorSelectModel" /&gt;
 </pre>
 </div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>SelectWithListDemo.java (partial)</b></div><div class="codeContent 
panelContent pdl">
@@ -180,7 +180,7 @@ public String toString() {
        ...
     }
 </pre>
-</div></div><p>But then again, you may as well create a ValueEncoder 
instead.</p><h2 id="UsingSelectWithaList-Whyisthissohard?">Why is this so 
hard?</h2><p>Actually, it's really pretty easy if you follow the examples 
above. But why is Tapestry designed to use SelectModels and ValueEncoders 
anyway? Well, in short, this design allows you to avoid storing (via @Persist, 
@SessionAttribute or @SessionState) the entire (potentially large) list of 
objects in the session or rebuilding the whole list of objects again (though 
only one is needed) when the form is submitted. The chief benefits are reduced 
memory use and <a  href="using-select-with-a-list.html">more scalable 
clustering</a> due to having far less HTTP session data to replicate across the 
nodes of a cluster.</p></div>
+</div></div><p>But then again, you may as well create a ValueEncoder 
instead.</p><h2 id="UsingSelectWithaList-Whyisthissohard?">Why is this so 
hard?</h2><p>Actually, it's really pretty easy if you follow the examples 
above. But why is Tapestry designed to use SelectModels and ValueEncoders 
anyway? Well, in short, this design allows you to avoid storing (via @Persist, 
@SessionAttribute or @SessionState) the entire (potentially large) list of 
objects in the session or rebuilding the whole list of objects again (though 
only one is needed) when the form is submitted. The chief benefits are reduced 
memory use and <a  href="performance-and-clustering.html">more scalable 
clustering</a> due to having far less HTTP session data to replicate across the 
nodes of a cluster.</p></div>
       </div>
 
       <div class="clearer"></div>


Reply via email to