Modified: websites/production/tapestry/content/strategybuilder-service.html
==============================================================================
--- websites/production/tapestry/content/strategybuilder-service.html (original)
+++ websites/production/tapestry/content/strategybuilder-service.html Sun Apr
26 21:22:55 2020
@@ -84,11 +84,13 @@
+
+
<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>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="shadowbuilder-service.html">ShadowBuilder
Service</a>
@@ -97,25 +99,25 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="strategybuilder-service.html">StrategyBuilder Service</a>
+ <a
href="pipelinebuilder-service.html">PipelineBuilder Service</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="pipelinebuilder-service.html">PipelineBuilder Service</a>
+ <a
href="strategybuilder-service.html">StrategyBuilder Service</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="chainbuilder-service.html">ChainBuilder
Service</a>
@@ -127,12 +129,12 @@
<p>Another of the Gang Of Four patterns, the strategy pattern as implemented
in Tapestry IoC is a kind of late binding.</p><p>The idea is that
<em>adapters</em> for objects are accessed based on the <em>actual type</em> of
an object. These adapters supply additional functionality. The adapters are
located using a StrategyRegistry (<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/util/StrategyRegistry.html">API</a>).</p><p>The
lookup of adapters is based on an inheritance search; thus providing an
adapter for type java.util.Map will match any object that implements the Map
interface. The inheritance search works its way up the class hierarchy looking
for a matching registration. If nothing is found, then all the interfaces
directly or indirectly implemented by the selector class are checked.
java.lang.Object is always the final match.</p><p>A runtime exception is thrown
if no match can be found.</p><p>As a special case, the value nul
l is searched for as if it were an instance of the class void.</p><p>The
StrategyBuilder service (<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/StrategyBuilder.html">API</a>)
creates a service implementation around a strategy registry.</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 StrategyBuilder
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public interface
StrategyBuilder
{
<S> S build(StrategyRegistry<S> registry);
}</pre>
</div></div><p>For a given interface (and matching StrategyRegistry), a
service implementation is created. The service interface is determined from the
strategy registry.</p><p>The first parameter of each method is the
<em>selector</em>. Its type is used to locate an adapter.</p><p>The
corresponding method of the adapter is then invoked, passing all
parameters.</p><p>Every method of the service interface should take at least
one parameter. Generally, such interfaces have only one or two methods.</p><h1
id="StrategyBuilderService-Example">Example</h1><p>You will usually have a
service configuration for defining the adapter registry.</p><p>You convert the
configuration into a StrategyRegistry, and use that to build the final
service:</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 static MyStrategyService build(Map<Class,
MyStrategyService> configuration,
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static
MyStrategyService build(Map<Class, MyStrategyService> configuration,
@InjectService("StrategyBuilder")
StrategyBuilder builder)
{
Modified:
websites/production/tapestry/content/supporting-informal-parameters.html
==============================================================================
--- websites/production/tapestry/content/supporting-informal-parameters.html
(original)
+++ websites/production/tapestry/content/supporting-informal-parameters.html
Sun Apr 26 21:22:55 2020
@@ -84,38 +84,40 @@
+
+
<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>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="enum-parameter-recipe.html">Enum Parameter
Recipe</a>
+ <a
href="supporting-informal-parameters.html">Supporting Informal Parameters</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="supporting-informal-parameters.html">Supporting Informal Parameters</a>
+ <a href="default-parameter.html">Default Parameter</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="default-parameter.html">Default Parameter</a>
+ <a href="enum-parameter-recipe.html">Enum Parameter
Recipe</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="component-parameters.html">Component
Parameters</a>
@@ -127,7 +129,7 @@
<p>Any component that closely emulates a particular HTML element
<strong><em>should</em></strong> support informal parameters, because it gives
users of your component the ability to easily add HTML attributes to the HTML
that your component emits. You'll find that most of the built-in Tapestry
components, such as Form, Label and TextField, do exactly that.</p><p>To
support informal parameters, a component class should use either the @<a
class="external-link"
href="http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/annotations/SupportsInformalParameters.html">SupportsInformalParameters</a>
annotation or the RenderInformals mixin. Otherwise, providing informal
parameters to a component will do nothing: any additional parameters will be
ignored.</p><h3
id="SupportingInformalParameters-Approach1:@SupportsInformalParameters">Approach
1: @SupportsInformalParameters</h3><p>In the example below we create an Img
component, a custom replacement for the <img> tag. Its sr
c parameter will be an asset. We'll use the @SupportsInformalParameters
annotation to tell Tapestry that the component should support informal
parameters.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Img.java</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">@SupportsInformalParameters
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">@SupportsInformalParameters
public class Img
{
@Parameter(required=true, allowNull=false,
defaultPrefix=BindingConstants.ASSET)
@@ -146,7 +148,7 @@ public class Img
}
</pre>
</div></div><p>The call to renderInformalParameters() is what converts and
outputs the informal parameters. It should occur <em>after</em> your code has
rendered attributes into the element (earlier written attributes will
<em>not</em> be overwritten by later written attributes).</p><p>Returning false
from beginRender() ensures that the body of the component is not rendered,
which makes sense for an <img> tag, which has no body.</p><h3
id="SupportingInformalParameters-Approach2:RenderInformals">Approach 2:
RenderInformals</h3><p>Another, equivalent, approach is to use the <a
class="external-link"
href="http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/corelib/mixins/RenderInformals.html">RenderInformals</a>
mixin (:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Img.java</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class Img
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class Img
{
@Parameter(required=true, allowNull=false,
defaultPrefix=BindingConstants.ASSET)
private Asset src;
@@ -167,7 +169,7 @@ public class Img
}
</pre>
</div></div><p>This variation splits the rendering of the tag in two pieces,
so that the RenderInformals mixin can operate (after beginRender() and before
beforeRenderBody()).</p><h3
id="SupportingInformalParameters-Approach3:Extendthe"Any"component">Approach
3: Extend the "Any" component</h3><p>Another approach is to have your
component class <em>extend</em> Tapestry's Any component, which already
supports informal parameters:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>Img.java</b></div><div class="codeContent
panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class Img extends Any { ... }</pre>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class Img extends
Any { ... }</pre>
</div></div><p> </p><p> </p><p> </p><p> </p></div>
</div>
Modified: websites/production/tapestry/content/switching-cases.html
==============================================================================
--- websites/production/tapestry/content/switching-cases.html (original)
+++ websites/production/tapestry/content/switching-cases.html Sun Apr 26
21:22:55 2020
@@ -82,7 +82,7 @@
<p>In cases where you have to distinguish multiple cases, the
<code>Delegate</code> component comes in. It delegates rendering to some other
component, for example a <code>Block</code>. For each case you have, you
basically wrap the content inside a <code>Block</code> that doesn't get
rendered by default. You then place a Delegate component on your page and point
it to a method inside your page class that will decide which of your Blocks
should be rendered.</p><p>Imagine for example a use case, where you want to
distinguish between 4 cases and you have an int property called
<code>whichCase</code> that should be tested against. Your page template would
look as follows:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>SwitchMe.tml</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<body>
<h1>Switch</h1>
@@ -107,7 +107,7 @@
</html>
</pre>
</div></div><p>You can see, that the <code>Delegate</code> component's
<code>to</code> parameter is bound to the case property of your page class. In
your page class you therefore have a <code>getCase()</code> method that is
responsible for telling the <code>Delegate</code> component which component
should be rendered. For that we are injecting references to the <code>Block}}s
defined in your page template into the page class and return the according
{{Block</code> in the <code>getCase()</code> method.</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>SwitchMe.java</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class SwitchMe
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class SwitchMe
{
@Persist
private int whichCase;
Modified: websites/production/tapestry/content/symbols.html
==============================================================================
--- websites/production/tapestry/content/symbols.html (original)
+++ websites/production/tapestry/content/symbols.html Sun Apr 26 21:22:55 2020
@@ -85,38 +85,40 @@
+
+
<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>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="application-module-class-cheat-sheet.html">Application Module Class Cheat
Sheet</a>
+ <a href="response-compression.html">Response
Compression</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="ioc-cookbook-service-configurations.html">IoC cookbook - Service
Configurations</a>
+ <a href="symbols.html">Symbols</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="symbols.html">Symbols</a>
+ <a
href="application-module-class-cheat-sheet.html">Application Module Class Cheat
Sheet</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="tapestry-ioc-configuration.html">Tapestry
IoC Configuration</a>
@@ -125,16 +127,16 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="response-compression.html">Response
Compression</a>
+ <a
href="ioc-cookbook-service-configurations.html">IoC cookbook - Service
Configurations</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="configuration.html">Configuration</a>
@@ -146,16 +148,16 @@
<h2 id="Symbols-Syntax">Syntax</h2><p>The syntax of symbols is based on Ant
expressions. That is, the name is surrounded by ${ and } characters:</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;">${some.symbol.name}
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">${some.symbol.name}
</pre>
</div></div><p>The value on the inside is the <em>symbol name</em>. By
convention, the symbol name is segmented with periods (for example,
"tapestry.production-mode").</p><h2 id="Symbols-Built-inSymbols">Built-in
Symbols</h2><p class="confluence-link">The <a
href="configuration.html">Configuration</a> page lists most of the symbol names
used by Tapestry's built-in services.</p><h2
id="Symbols-UsingSymbolsinyourServices">Using Symbols in your
Services</h2><p>Symbols are used inside the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Value.html">Value</a>
and @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html">InjectService</a>
annotations.</p><p>For example:</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 static MyService build(
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static MyService
build(
@InjectService("${some-service-id}") Collaborator collab)
{
return . . . ;
}</pre>
</div></div><p>Here, the symbol name, <code>some-service-id</code> is a
service id, such as <code>WackyCollaborator</code>.</p><p>Although not shown
here, it is possible to use multiple symbols inside the string, or mix literal
text with symbols.</p><h2 id="Symbols-InjectingValuesfromSymbols">Injecting
Values from Symbols</h2><p>You may also inject symbol values. For example, if
you are interested in whether the application is in production mode or
developer mode:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class MyService implements MyServiceInterface
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class MyService
implements MyServiceInterface
{
public MyService(@Value("${tapestry.production-mode}") boolean
productionMode, ...)
{
@@ -163,7 +165,7 @@
. . .
</pre>
</div></div><p>Here Tapestry has <a href="type-coercion.html">coerced</a> the
"tapestry.production-mode" symbol to a boolean to be injected.</p><p>As an
alternative, the @Symbol annotation, may be used:</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class MyService implements MyServiceInterface
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class MyService
implements MyServiceInterface
{
public MyService(@Symbol(SymbolConstants.PRODUCTION_MODE) boolean
productionMode, ...)
{
@@ -171,7 +173,7 @@
. . .
</pre>
</div></div><p>This is very useful when a constant value is defined for the
symbol; it means that the compiler can catch a typo, rather than detecting it a
runtime.</p><p><strong>Note:</strong> When injecting a symbol as a
<em>string</em> into a service, you must use the @Inject annotation as well as
@Value or @Symbol; otherwise Tapestry will inject the service's service
id.</p><h2 id="Symbols-SymbolsinComponentClassesandTemplates">Symbols in
Component Classes and Templates</h2><p>It's easy to use a symbol in a component
class:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> @Inject
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> @Inject
@Symbol(SymbolConstants.PRODUCTION_MODE)
private boolean productionMode;
. . .
@@ -181,16 +183,16 @@
}
}</pre>
</div></div><p>You can even use them directly in a component template, using
the "symbol" binding prefix:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:if test="!symbol:tapestry.production-mode">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:if
test="!symbol:tapestry.production-mode">
<p>WARNING: We're running in development mode (slower, and less
secure)</p>
</t:if></pre>
</div></div><h2 id="Symbols-SymbolResolution">Symbol Resolution</h2><p>Symbols
are resolved by the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/SymbolSource.html">SymbolSource</a>
service. The SymbolSource service checks against an ordered list of <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/SymbolProvider.html">SymbolProvider</a>
objects.</p><p>You may employ additional symbol providers by contributing to
the SymbolSource service configuration, which is an ordered list of
SymbolProviders.</p><p>By default, there are three providers:</p><h3
id="Symbols-SystemPropertiesProvider">SystemProperties Provider</h3><p>The
first provider allows JVM System Properties to provide symbol values. This
allows the use of the <strong>java</strong> command's <strong>-D</strong>
option to provide runtime overrides. This is most often used when testing code,
rather than in pro
duction. SystemProperties is always checked first.</p><h3
id="Symbols-ApplicationDefaultsProvider">ApplicationDefaults
Provider</h3><p>Values not found as System Properties are searched for in the
ApplicationDefaults. This service, ApplicationDefaults, may be configured using
a mapped configuration to provide values.</p><p>From the previous
example:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent
pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> public void
contributeApplicationDefaults(MappedConfiguration<String, String>
configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public void
contributeApplicationDefaults(MappedConfiguration<String, String>
configuration)
{
configuration.add("some-service-id", "WackyCollaborator");
}</pre>
</div></div><h3 id="Symbols-FactoryDefaultsProvider">FactoryDefaults
Provider</h3><p>This is the same as ApplicationDefaults, but checked only if a
value is not satisfied by SystemProperties or
ApplicationDefaults.</p><p>Libraries will typically set reasonable defaults as
contributions to the FactoryDefaults service configuration. Individual
applications may hard code overrides of those defaults using
ApplicationDefaults. Individual developers may override even those defaults by
setting JVM System Properties.</p><p>FactoryDefaults is always checked last
when resolving symbol names to symbol values.</p><h2
id="Symbols-RecursiveSymbols">Recursive Symbols</h2><p>It is possible and valid
to define one symbol in terms of one or more other symbols.</p><div class="code
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> public void
contributeFactoryDefaults(MappedConfiguration<String, String>
configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public void
contributeFactoryDefaults(MappedConfiguration<String, String>
configuration)
{
configuration.add("report.url",
"http://${report.host}:${report.port}/${report.path}");
configuration.add("report.host", "www.myreportsite.com");
@@ -198,7 +200,7 @@
configuration.add("report.path", "/report.cgi");
}</pre>
</div></div><p>The ordinary default for <code>report.url</code> will be:
<code><span
class="nolink">http://www.myreportsite.com:80/report.cgi</span></code></p><p>However,
this can be changed by making an overriding contribution to the
ApplicationDefaults service configuration.</p><p>Tapestry checks that no symbol
is directly or indirectly dependent on itself. For example, the following
contribution is illegal:</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 void
contributeApplicationDefaults(MappedConfiguration<String, String>
configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public void
contributeApplicationDefaults(MappedConfiguration<String, String>
configuration)
{
configuration.add("report.path", "${report.url}/report.cgi");
}</pre>
Modified: websites/production/tapestry/content/tapestry-for-jsf-users.html
==============================================================================
--- websites/production/tapestry/content/tapestry-for-jsf-users.html (original)
+++ websites/production/tapestry/content/tapestry-for-jsf-users.html Sun Apr 26
21:22:55 2020
@@ -85,20 +85,22 @@
+
+
<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>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="tapestry-for-jsf-users.html">Tapestry for
JSF Users</a>
+ <a href="getting-started.html">Getting Started</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="tapestry-tutorial.html">Tapestry Tutorial</a>
@@ -107,28 +109,28 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="principles.html">Principles</a>
+ <a href="introduction.html">Introduction</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="getting-started.html">Getting Started</a>
+ <a href="tapestry-for-jsf-users.html">Tapestry for
JSF Users</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="introduction.html">Introduction</a>
+ <a href="principles.html">Principles</a>
</div>
@@ -137,7 +139,7 @@
<p>Since almost all modern JSF applications use Facelets as their view
technology, we assume the use of Facelets here when discussing JSF
features.</p><p>JSF is a rich, mature web framework specification, and there
are lots of smart people who use it productively. This guide isn't intended as
a pro-versus-con comparison or as advocacy of any kind. Instead, it just
attempts to make transitions between the two frameworks easier, regardless of
the reason for doing so.</p><h2
id="TapestryforJSFUsers-Side-by-sideComparison">Side-by-side
Comparison</h2><p>JSF and Tapestry have a lot of superficial similarities, so
the first steps in that transition are all about relating similar concepts,
terms and components in your mind:</p><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Concepts & Terminology</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><
p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Java class associated with a page or
component</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>"Backing
Bean"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>"<a
href="component-classes.html">Component Class</a>"</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Component
attributes/parameters</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>"attributes"</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>"<a
href="component-parameters.html">parameters</a>"</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Common
Attributes/Parameters</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>HTML Attribute used for invisible
instrumentation</p></td><td colspan="1" rowspan="1" class
="confluenceTd"><p>jsfc="someComponentType"</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a
href="component-templates.html">t:type="someComponentType"</a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>CSS "class" attribute
name</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>styleClass</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>class</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Alternating "zebra" striped rows</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>rowclasses="class1,class2"</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>class="${cycle:class1,class2}" using <a
class="external-link"
href="https://wiki.apache.org/tapestry/Tapestry5HowToAddBindingPrefixCycle">cycle
binding prefix</a>, or with CSS: .rowClass:nth-child(even) {background-color:
#e8e8e8;}</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Output and Messages</p></th><th colspan="1
" rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Escaped HTML from property</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><h:outputText
value="myBean.myValue"/></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${myValue}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Raw HTML from property</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>#{myBean.myValue}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/OutputRaw.html"><t:outputRaw
value="myValue"/></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Error messages</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:message> and <h:messages></p></td><td
colspan="1" row
span="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Error.html"><t:error></a>
and <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Errors.html"><t:errors></a>
(for forms) or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Alerts.html"><t:alerts></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Image display</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:graphicImage></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>use standard <img> tag, but see
<a href="assets.html">Assets</a><br clear="none"></em></p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Conditionals and
Looping</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF</p></th><th colspa
n="1" rowspan="1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Render-time loop</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><ui:repeat></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Loop.html"><t:loop></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Compile-time loop</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><c:forEach></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Loop.html"><t:loop></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Conditional</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><c:if
test="#{myBean.myValue}"></p></td><td colspan="1" rows
pan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html"><t:if
test="myValue"></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Conditional</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:fragment
rendered="#{myBean.someCondition}"/>...</ui:fragment></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html"><t:if
test="someCondition">...</t:if></a></p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Switch</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><c:choose><c:when ...
></c:choose></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>See <a href="switching-cases.html">Switching
Cases</a></p></td></tr><tr><td colspan="1" rowspan="1" c
lass="confluenceTd"><p>Server-side comment</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:remove></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a
href="component-templates.html"><t:remove></a></p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Links and Buttons</p></th><th
colspan="1" rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Navigational link</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><h:link
outcome="nextpage.xhtml"/></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/PageLink.html"><t:pagelink
page="nextpage"/></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Event-triggering link, without form submission</p></
td><td colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/ActionLink.html"><t:actionLink></a>
or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/EventLink.html"><t:eventLink></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Form submission
link</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:commandLink></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/LinkSubmit.html"><t:linkSubmit></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Form submission
button</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><
;h:commandButton></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Submit.html"><t:submit></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Link to Javascript
file</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:outputScript></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em><script> or use @Import in
component class</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Link to CSS file</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:outputStylesheet></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em><style> or use @Import in
component class</em></p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Grids, Tables and Trees</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" ro
wspan="1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Tabular data in <table></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><h:datatable></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Grid.html"><t:grid></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Table used for
layout</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:panelGrid> with
<h:panelGroup></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>use standard <table>
tag</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Hierarchical tree</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>depends on component library</em></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link" hr
ef="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Tree.html"><t:tree></a></p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Form
Tags/Components</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Form</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:form></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html"><t:form></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Single-line text input
field</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputText></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/curren
t/apidocs/org/apache/tapestry5/corelib/components/TextField.html"><t:textField></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Password field</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputSecret></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/PasswordField.html"><t:passwordfield></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Select menu</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectOneMenu></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Select.html"><t:select></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Checkbox</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><h:
selectBooleanCheckbox></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checkbox.html"><t:checkbox></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Checkbox list</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectManyCheckbox></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checklist.html"><t:checklist></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Radio button list</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectOneRadio></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/RadioGroup.html"><t:r
adioGroup></a> with <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Radio.html"><t:radio></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Multiple select
menu</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectManyListbox></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>not available</em> (but see Palette and
Checklist)</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Hidden field</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputHidden></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Hidden.html"><t:hidden></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>textarea tag</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><h:inputTextarea
></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextArea.html"><t:textArea></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Label tag</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><h:outputLabel
for="..."></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Label.html"><t:label
for="..."></a></p></td></tr></tbody></table></div><p>Some important
notes:</p><ul><li>With Tapestry, you don't use the ${...} syntax with
parameters of components. Just use a bare expression within the quotes. For
example: <t:textfield value="myProperty"> instead of <t:textfield
value="${myProperty}">, because in the latter case the expression is
converted to a read-only string before the te
xtfield component gets it.</li></ul><h2
id="TapestryforJSFUsers-HelloWorldComparison">Hello World
Comparison</h2><p>Faces templates and Tapestry templates are superficially
quite similar.</p><div class="sectionColumnWrapper"><div
class="sectionMacro"><div class="sectionMacroRow"><div class="columnMacro"><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader
panelHeader pdl" style="border-bottom-width: 1px;"><b>JSF template
(helloworld.xhtml)</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html xmlns="http://www.w3.org/1999/xhtml"
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<p><h:outputText value="#{helloWorldBean.greeting} /></p>
@@ -145,14 +147,14 @@
</html>
</pre>
</div></div></div><div class="columnMacro"><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>Tapestry template
(HelloWorld.tml)</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<body>
<p>${greeting}</p>
</body>
</html>
</pre>
</div></div></div></div></div></div><p>Though these are very similar, notice
some differences:</p><ul><li>The #{...} syntax in JSF does not encode the
underlying string, so you have to use the <h:outputText> tag if your data
may contain HTML reserved characters such as <, >, or &. In contrast,
the ${...} syntax in Tapestry <strong>does</strong> encode the underlying
string.</li><li>In JSF, backing beans are not necessarily related one-to-one
with page templates. Often several templates use the same backing bean, and one
template may reference multiple backing beans. In Tapestry, they are always
related one-to-one, and therefore you don't have to specify which component
class your ${...} expressions are referencing.</li></ul><div
class="sectionColumnWrapper"><div class="sectionMacro"><div
class="sectionMacroRow"><div class="columnMacro"><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>J
SF Backing Bean (HelloWorldBean.java)</b></div><div class="codeContent
panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">@ManagedBean
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">@ManagedBean
@RequestScoped
public class HelloWorldBean {
public String getGreeting() {
@@ -161,14 +163,14 @@ public class HelloWorldBean {
}
</pre>
</div></div></div><div class="columnMacro"><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>Tapestry page class
(HelloWorld.java)</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class HelloWorld {
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class HelloWorld {
public String getGreeting() {
return "Hello, World!";
}
}
</pre>
</div></div></div></div></div></div><h2
id="TapestryforJSFUsers-Expressionsintemplates">Expressions in
templates</h2><p>JSF uses the Unified Expression Language with the #{...} or
${...} syntax for accessing Backing Bean properties. For its part, Tapestry
uses the ${...} syntax with a similar but intentionally limited expression
language called <a href="property-expressions.html">Property Expressions</a>.
Both allow easy access to properties via the usual JavaBean conventions, but
with Tapestry you don't have to specify which class the expression starts at
(because it always starts at the component class corresponding to the
template). Some comparisons:</p><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p> </p></td><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF Syntax</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry Syntax</p></th></tr><tr><td colspan="1"
rowspan="1" class="conflue
nceTd"><p>Property (calls getEmployeeName() or setEmployeeName())</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.employeeName}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${employeeName}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Boolean property (calls
isHourly() or setHourly())</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.hourly}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${hourly}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Property chain</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>#{employeeBean.address.street}</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>${address.street}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Null-safe property chain</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.address.street}</p></td><td colspan="1"
rowspan="1" class="confluenceTd
"><p>${address?.street}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>5th element in a List</p></td><td colspan="1"
rowspan="1"
class="confluenceTd"><p>#{employeeBean.employees[5].name}</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>${employees.get(5).name}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Negation</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>#{!
employeeBean.hourly}</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${! hourly}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Arithmetic & relational
operators</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>+-*/% div
mod</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Relational operators</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>== != ne < lt > gt <= le >=
ge</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Ternary operator</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{myBean.foo < 0 ? 'bar' : 'baz'}</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Method calling</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{myBean.employees.size()}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${employees.size()}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Iterated Range</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><em>not
avaialble</em></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${1..10}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Iterated Range (calculated)</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>not avaialb
le</em></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${1..groupList.size()}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>List</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>not available</em></p></td><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></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Map</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>not available</em></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${ { 'id':'4039','type':'hourly' }
}</p></td></tr></tbody></table></div><p>Features shown as <em>not
available</em> above are absent by design, because (in both Tapestry and JSF)
it is considered best to keep complex logic in the component class rather than
in the template.</p><h2
id="TapestryforJSFUsers-EventHandling&PageNavigation">Event Handling &
Page Navigation</h2><h3 id="TapestryforJSFUsers-Eventhandling">Event
handling</h3><p>In JSF, you specify the event via the <code>action</code>
parameter (for example, <h:commandButton value="Submit"
action="employeeBean.saveChanges">). For Tapestry, event handler methods are
found by method naming conventions (onSomeEvent() or by method annotations
(@Event), based on a combination of the "t:id" attribute and event name, and
the action name used depends on the component. For example, the
"<t:actionlink>" component in Tapestry emits an "action" event when
clicked, and you handle that event in your "onAction()" method.</p><h2
id="TapestryforJSFUsers-Validation">Validation</h2><p>Tapestry applications can
use JSR 303 Bean Validation annotations that JSF users should be familiar
with:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class Employee {
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class Employee {
@Validate("required,minlength=2,maxlength=100")
private String lastName;
@NotNull @Email private String email;
Modified:
websites/production/tapestry/content/tapestry-inversion-of-control-faq.html
==============================================================================
--- websites/production/tapestry/content/tapestry-inversion-of-control-faq.html
(original)
+++ websites/production/tapestry/content/tapestry-inversion-of-control-faq.html
Sun Apr 26 21:22:55 2020
@@ -78,11 +78,11 @@
<div id="content">
<div id="ConfluenceContent"><h1
id="TapestryInversionofControlFAQ-TapestryInversionofControlContainer">Tapestry
Inversion of Control Container</h1><p>Main article: <a
href="tapestry-inversion-of-control-faq.html">Tapestry IoC</a></p><h2
id="TapestryInversionofControlFAQ-Contents">Contents</h2><p><style
type="text/css">/*<![CDATA[*/
-div.rbtoc1587536393230 {padding: 0px;}
-div.rbtoc1587536393230 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1587536393230 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1587935991602 {padding: 0px;}
+div.rbtoc1587935991602 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1587935991602 li {margin-left: 0px;padding-left: 0px;}
-/*]]>*/</style></p><div class="toc-macro rbtoc1587536393230">
+/*]]>*/</style></p><div class="toc-macro rbtoc1587935991602">
<ul class="toc-indentation"><li><a
href="#TapestryInversionofControlFAQ-WhydoIneedtodefineaninterfaceformyservices?Whycan'tIjustusetheclassitself?">Why
do I need to define an interface for my services? Why can't I just use the
class itself?</a></li><li><a
href="#TapestryInversionofControlFAQ-Myservicestartsathread;howdoIknowwhentheapplicationisshuttingdown,tostopthatthread?">My
service starts a thread; how do I know when the application is shutting down,
to stop that thread?</a></li><li><a
href="#TapestryInversionofControlFAQ-HowdoImakemyservicestartupwiththerestoftheapplication,ratherthanlazily?">How
do I make my service startup with the rest of the application, rather than
lazily?</a></li></ul>
</div><p> </p><div class="aui-label" style="float:right" title="Related
Articles">
Modified: websites/production/tapestry/content/tapestry-ioc-configuration.html
==============================================================================
--- websites/production/tapestry/content/tapestry-ioc-configuration.html
(original)
+++ websites/production/tapestry/content/tapestry-ioc-configuration.html Sun
Apr 26 21:22:55 2020
@@ -84,38 +84,40 @@
+
+
<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>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="application-module-class-cheat-sheet.html">Application Module Class Cheat
Sheet</a>
+ <a href="response-compression.html">Response
Compression</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="ioc-cookbook-service-configurations.html">IoC cookbook - Service
Configurations</a>
+ <a href="symbols.html">Symbols</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="symbols.html">Symbols</a>
+ <a
href="application-module-class-cheat-sheet.html">Application Module Class Cheat
Sheet</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="tapestry-ioc-configuration.html">Tapestry
IoC Configuration</a>
@@ -124,16 +126,16 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="response-compression.html">Response
Compression</a>
+ <a
href="ioc-cookbook-service-configurations.html">IoC cookbook - Service
Configurations</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="configuration.html">Configuration</a>
@@ -145,18 +147,18 @@
<p>One of the key concepts in Tapestry IoC is <em>distributed
configuration</em>. The <em>distributed</em> part refers to the fact that
<em>any module</em> may configure a service. Distributed configuration is the
key feature of Tapestry IoC that supports extensibility and
modularity.</p><p>Modules configure a service by <em>contributing</em> to
service configurations. This may seem esoteric but is really pretty simple.
We'll explain with an example.</p><p>Let's say you've written a bunch of
different services, each of which does something specific for a particular type
of file (identified by the file's extension), and each implements the same
interface, which we'll call FileServicer. And now let's say you need a central
service that selects the one of your FileServicer implementations based on a
given file extension. You start by providing a <a
href="defining-tapestry-ioc-services.html">service builder method</a>:</p><div
class="code panel pdl" style="border-width: 1px;"><div clas
s="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> public static FileServiceDispatcher
buildFileServicerDispatcher(Map<String,FileServicer> contributions)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static
FileServiceDispatcher
buildFileServicerDispatcher(Map<String,FileServicer> contributions)
{
return new FileServiceDispatcherImpl(contributions);
} </pre>
</div></div><p>In order to provide a value for the contribution parameter,
Tapestry will <em>collect</em> contributions from service contribution methods.
It will ensure that the keys and values match the generic types shown (String
for the key, FileServicer for the value). The map will be assembled and passed
into the service builder method, and from there, into the
FileServiceDispatcherImpl constructor.</p><p>So where do the values come from?
Your service contributor methods, methods whose names start with
"contribute":</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 static void
contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer>
configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static void
contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer>
configuration)
{
configuration.add("txt", new TextFileServicer());
configuration.add("pdf", new PDFFileServicer());
} </pre>
</div></div><p>Or, instead of instantiating those services ourselves, we could
<a href="injection-in-detail.html">inject</a> them:</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 static void
contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer>
configuration,
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static void
contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer>
configuration,
@InjectService("TextFileServicer") FileServicer textFileServicer,
@InjectService("PDFFileServicer") FileServicer pdfFileServicer)
@@ -165,7 +167,7 @@
configuration.add("pdf", pdfFileServicer);
} </pre>
</div></div><p>The <strong>extensibility</strong> comes from the fact that
multiple modules may all contribute to the same service configuration:</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 static void
contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer>
configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static void
contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer>
configuration)
{
configuration.add("doc", new WordFileServicer());
configuration.add("ppt", new PowerPointFileServicer());
@@ -177,7 +179,7 @@
</div>If you prefer annotations over naming conventions you can use the @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Contribute.html">Contribute</a>
annotation. As of version 5.2 this annotation that may be placed on a
contributor method of a module instead of starting the methods name with
"contribute". The value of the annotation is the type of the service to
contribute into.<p>The primary reasons to use @Contribute and marker
annotations is twofold:</p><ul><li>There is no longer a linkage between the
contribution method name and the service id, which is much more refactoring
safe: if you change the service interface name, or the ID of the service, your
method will still be invoked when using @Contribute.</li></ul><ul><li>It makes
it much easier for an <span class="confluence-link">override</span> of the
service to get the configuration intended for the original
service.</li></ul><p>The following example is an annotat
ion-based alternative for the contribution method above.</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;">@Contribute(FileServiceDispatcher.class)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default"
data-theme="Default">@Contribute(FileServiceDispatcher.class)
public static void
arbitraryMethodName(MappedConfiguration<String,FileServicer>
configuration)
{
configuration.add("doc", new WordFileServicer());
@@ -185,7 +187,7 @@ public static void arbitraryMethodName(M
}
</pre>
</div></div><p>If you have several implementations of a service interface, you
have to disambiguate the services. For this purpose the marker annotations
should be placed on the contributor method.</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;">@Contribute(FileServiceDispatcher.class)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default"
data-theme="Default">@Contribute(FileServiceDispatcher.class)
@Red @Blue
public static void
arbitraryMethodName(MappedConfiguration<String,FileServicer>
configuration)
{
@@ -194,7 +196,7 @@ public static void arbitraryMethodName(M
}
</pre>
</div></div><p>In this example, the method will only be invoked when
constructing a service configuration where the service itself has both the Red
and Blue marker annotations. Tapestry knows which annotations are marker
annotations, and which marker annotations apply to the service, via the @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Marker.html">Marker</a>
annotation on the service implementation.</p><p>If the special @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Local.html">Local</a>
annotation is present, then the contribution is made only to the configuration
of a service being constructed in the same module.</p><p>Note that it
<em>is</em> possible for the same contribution method to be invoked to
contribute to the configuration of multiple different services.</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelConten
t pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> @Contribute(FileServiceDispatcher.class)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">
@Contribute(FileServiceDispatcher.class)
@Local
public static void
arbitraryMethodName(MappedConfiguration<String,FileServicer>
configuration)
{
@@ -203,7 +205,7 @@ public static void arbitraryMethodName(M
}
</pre>
</div></div><h1 id="TapestryIoCConfiguration-ConfigurationTypes">Configuration
Types</h1><p>There are three different styles of configurations (with matching
contributions):</p><ul><li><strong>Unordered Collection</strong> –
Contributions are simply added in and order is not
important.</li><li><strong>Ordered List</strong> – Contributions are
provided as an ordered list. Contributions must establish the order by giving
each contributed object a unique id, by establishing forward and backward
dependencies between the values.</li><li><strong>Map</strong> –
Contributions provide unique keys and corresponding values.</li></ul><h2
id="TapestryIoCConfiguration-UnorderedCollection">Unordered Collection</h2><p>A
service builder method can collect an unordered list of values by defining a
parameter of type java.util.Collection. Further, you should parameterize the
type of collection. Tapestry will identify the parameterized type and ensure
that all contributions match.</p><
p>One thing to remember is that the order in which contributions occur is
unspecified. There will be a possibly large number of modules, each having zero
or more methods that contribute into the service. The order in which these
methods are invoked is unknown.</p><p>For example, here's a kind of Startup
service that needs some Runnable objects. It doesn't care what order the
Runnable objects are executed in.</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 static Runnable buildStartup(final
Collection<Runnable> configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static Runnable
buildStartup(final Collection<Runnable> configuration)
{
return new Runnable()
{
@@ -215,13 +217,13 @@ public static void arbitraryMethodName(M
};
} </pre>
</div></div><p>Here we don't even need a separate class for the
implementation, we use an inner class for the implementation. The point is, the
configuration is provided to the builder method, which passes it along to the
implementation of the service.</p><p>On the contribution side, a service
contribution method sees a <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/Configuration.html">Configuration</a>
object:</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 static void
contributeStartup(Configuration<Runnable> configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static void
contributeStartup(Configuration<Runnable> configuration)
{
configuration.add(new JMSStartup());
configuration.add(new FileSystemStartup());
} </pre>
</div></div><p>The Configuration interface defines just a single method:
<code>add()</code>. This is very intentional: the only thing you can do is add
new items. If we passed in a Collection, you might be tempted to check it for
values, or remove them ... but that flies in the face of the fact that the
order of execution of these service contribution methods is entirely
unknown.</p><p>For readability, we've parameterized the configuration parameter
of the method, constraining it to instances of java.lang.Runnable, so as to
match the corresponding parameter. This is optional, but often very helpful. In
any case, attempting to contribute an object that doesn't extend or implement
the type (Runnable) will result in a runtime warning (and the value will be
ignored).</p><p>Tapestry supports only this simple form of parameterized types.
Java generics supports a wider form, "wildcards", that Tapestry doesn't
understand.</p><p><span class="confluence-anchor-link"
id="TapestryIoCConfigurati
on-Ordered_List"></span></p><h2
id="TapestryIoCConfiguration-OrderedList">Ordered List</h2><p>Ordered lists are
much more common. With an ordered list, the contributions are sorted into a
proper order before being provided to the service builder method.</p><p>Again,
the order in which service contribution methods are invoked is unknown.
Therefore, the order in which objects are added to the configuration is not
known. Instead, we enforce an order on the items <em>after</em> all the
contributions have been added. As with <a
href="tapestry-ioc-decorators.html">service decorators</a>, we set the order by
giving each contributed object a unique id, and identifying (by id) which items
must preceded it in the list, and which must follow.</p><p>So, if we changed
our Startup service to require a specific order for startup:</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 static Runnable buildStartup(final
List<Runnable> configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static Runnable
buildStartup(final List<Runnable> configuration)
{
return new Runnable()
{
@@ -233,7 +235,7 @@ public static void arbitraryMethodName(M
};
} </pre>
</div></div><p>Notice that the service builder method is shielded from the
details of how the items are ordered. It doesn't have to know about IDs and
pre- and post-requisites. By using a parameter type of List, we've triggered
Tapestry to collect all the ordering information.</p><p>For our service
contribution methods, we must provide a parameter of type <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/OrderedConfiguration.html">OrderedConfiguration</a>:</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 static void
contributeStartup(OrderedConfiguration<Runnable> configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static void
contributeStartup(OrderedConfiguration<Runnable> configuration)
{
configuration.add("JMS", new JMSStartup());
configuration.add("FileSystem", new FileSystemStartup(),
"after:CacheSetup");