Modified: websites/production/tapestry/content/security-faq.html
==============================================================================
--- websites/production/tapestry/content/security-faq.html (original)
+++ websites/production/tapestry/content/security-faq.html Tue Sep 26 19:20:27
2017
@@ -27,16 +27,6 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
- <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
- <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
- <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
- <script>
- SyntaxHighlighter.defaults['toolbar'] = false;
- SyntaxHighlighter.all();
- </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -77,56 +67,12 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><h2
id="SecurityFAQ-SecurityFAQ">Security FAQ</h2><p> </p><div
class="aui-label" style="float:right" title="Related Articles">
-
-
-
-
-
-
-
-
-<h3>Related Articles</h3>
-
-<ul class="content-by-label"><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="security-faq.html">Security FAQ</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="https.html">HTTPS</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="security.html">Security</a>
-
-
- </div>
- </li></ul>
-</div>
-
-
-<h3
id="SecurityFAQ-Thebuilt-inDashboardpagearevisibleinmyproductionapplicationandIdon'twantthemtobe,whatcanIdo?">The
built-in Dashboard page are visible in my production application and I don't
want them to be, what can I do?</h3><p>First off all, don't panic: the <a
href="development-dashboard.html">Developer Dashboard</a> page is marked with
the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/WhitelistAccessOnly.html">WhitelistAccessOnly</a>
annotation, which makes it invisible to clients that are not on the whitelist.
Try accessing the page from a different workstation and you may find that the
pages are not visible after all.</p><p>Sometimes, in production, a firewall or
proxy may make it look like the client web browser originates from localhost;
in that situation, you may want to disable the logic that puts localhost onto
the whitelist. This determination is made by the contributions to the <a
class="external-link
"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/security/ClientWhitelist.html">ClientWhitelist</a>
service. Tapestry makes a contribution with id "LocalhostOnly", which one of
your modules can override:</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(ClientWhitelist.class)
+ <div
id="ConfluenceContent"><p><plain-text-body>{scrollbar}</plain-text-body></p><h2
id="SecurityFAQ-SecurityFAQ">Security FAQ</h2><p> </p><parameter
ac:name="style">float:right</parameter><parameter ac:name="title">Related
Articles</parameter><parameter
ac:name="class">aui-label</parameter><rich-text-body><parameter
ac:name="showLabels">false</parameter><parameter
ac:name="showSpace">false</parameter><parameter ac:name="title">Related
Articles</parameter><parameter ac:name="cql">label = "security" and space =
currentSpace()</parameter></rich-text-body><h3
id="SecurityFAQ-Thebuilt-inDashboardpagearevisibleinmyproductionapplicationandIdon'twantthemtobe,whatcanIdo?">The
built-in Dashboard page are visible in my production application and I don't
want them to be, what can I do?</h3><p>First off all, don't panic: the <a
href="development-dashboard.html">Developer Dashboard</a> page is marked with
the @<a class="external-link" href="http://tapestry.apache.org/curre
nt/apidocs/org/apache/tapestry5/annotations/WhitelistAccessOnly.html">WhitelistAccessOnly</a>
annotation, which makes it invisible to clients that are not on the whitelist.
Try accessing the page from a different workstation and you may find that the
pages are not visible after all.</p><p>Sometimes, in production, a firewall or
proxy may make it look like the client web browser originates from localhost;
in that situation, you may want to disable the logic that puts localhost onto
the whitelist. This determination is made by the contributions to the <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/security/ClientWhitelist.html">ClientWhitelist</a>
service. Tapestry makes a contribution with id "LocalhostOnly", which one of
your modules can override:</p><plain-text-body>
@Contribute(ClientWhitelist.class)
public static void
turnOffLocalhostInProduction(OrderedConfiguration<WhitelistAnalyzer>
configuration,
@Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode) {
if (productionMode) { configuration.override("LocalhostOnly", null); }
}
-</pre>
-</div></div><p></p></div>
+</plain-text-body><p><plain-text-body>{scrollbar}</plain-text-body></p></div>
</div>
<div class="clearer"></div>
Modified: websites/production/tapestry/content/security.html
==============================================================================
--- websites/production/tapestry/content/security.html (original)
+++ websites/production/tapestry/content/security.html Tue Sep 26 19:20:27 2017
@@ -27,16 +27,6 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
- <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
- <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
- <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
- <script>
- SyntaxHighlighter.defaults['toolbar'] = false;
- SyntaxHighlighter.all();
- </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -77,61 +67,10 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><p>Tapestry has a number of
<strong>security</strong> features designed to harden your application against
unwanted intrusion and denial of service.</p><p> </p><div
class="aui-label" style="float:right" title="Related Articles">
-
-
-
-
-
-
-
-
-<h3>Related Articles</h3>
-
-<ul class="content-by-label"><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="security.html">Security</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a
href="integrating-with-spring-framework.html">Integrating with Spring
Framework</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="security-faq.html">Security FAQ</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="https.html">HTTPS</a>
-
-
- </div>
- </li></ul>
-</div>
-
-
-<p> </p><h2 id="Security-HTTPS-onlyPages">HTTPS-only Pages</h2><p>Main
Article: <a href="https.html">HTTPS</a></p><p>Tapestry provides several
annotations and configuration settings that you can use to <span
style="text-align: justify;line-height: 1.4285715;">ensure that all access to
certain pages (or all pages) occurs only via the encrypted HTTPS
protocol</span><span style="text-align: justify;line-height: 1.4285715;">.
See <a href="https.html">HTTPS</a> for details.</span></p><h2
id="Security-ControllingPageAccess"><span style="text-align:
justify;line-height: 1.4285715;">Controlling Page Access</span></h2><p></p><div
class="navmenu" style="float:right; background:#eee; margin:3px; padding:0 1em">
-<p> <strong>JumpStart Demo:</strong><br clear="none">
- <a class="external-link"
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/infrastructure/protectingpages"
rel="nofollow">Protecting Pages</a></p></div><span style="text-align:
justify;line-height: 1.4285715;">For simple access control needs, you can
contribute a <span><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ComponentRequestFilter.html">ComponentRequestFilter</a>
with your custom logic that decides which pages should be accessed by which
users. The <a class="external-link"
href="https://tapestry-app.apache.org/hotels/">Tapestry Hotel Booking </a>app
demonstrates this approach with an <code>@AnonymousAccess</code> annotation
along with a ComponentRequestFilter
named <code>AuthenticationFilter.java</code>. The filter enforces security
by intercepting all requests to pages that don't have that annotation, and it
redirects those requests to the login page. <a class="external-link"
href="http:
//jumpstart.doublenegative.com.au/jumpstart/examples/infrastructure/protectingpages"
rel="nofollow">JumpStart</a> has a similar demo.<br
clear="none"></span></span><p><span style="line-height: 1.4285715;text-align:
justify;">For more advanced needs see the Security Framework Integration
section below.</span></p><h2 id="Security-White-listedPages">White-listed
Pages</h2><p>Pages whose component classes are annotated with @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/WhitelistAccessOnly.html">WhitelistAccessOnly</a> will
only be displayed to users (clients) that are on the <em>whitelist</em>.
By default the whitelist consists only of clients whose fully-qualified domain
name is "localhost" (or the IP address equivalent, 127.0.0.1 or
0:0:0:0:0:0:0:1), but you can customize this by contributing to the
ClientWhitelist service in your application's module class (usually
AppModule.java):</p><div class="
code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader
pdl" style="border-bottom-width: 1px;"><b>AppModule.java (partial) –
simple inline example</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> @Contribute(ClientWhitelist.class)
+ <div id="ConfluenceContent"><p>Tapestry has a number of
<strong>security</strong> features designed to harden your application against
unwanted intrusion and denial of service.</p><p> </p><parameter
ac:name="style">float:right</parameter><parameter ac:name="title">Related
Articles</parameter><parameter
ac:name="class">aui-label</parameter><rich-text-body><parameter
ac:name="showLabels">false</parameter><parameter
ac:name="showSpace">false</parameter><parameter ac:name="title">Related
Articles</parameter><parameter ac:name="cql">label in ("spring","security") and
space = currentSpace()</parameter></rich-text-body><p> </p><h2
id="Security-HTTPS-onlyPages">HTTPS-only Pages</h2><p>Main Article: <a
href="https.html">HTTPS</a></p><p>Tapestry provides several annotations and
configuration settings that you can use to <span style="text-align:
justify;line-height: 1.4285715;">ensure that all access to certain pages (or
all pages) occurs only via the encrypted
HTTPS protocol</span><span style="text-align: justify;line-height:
1.4285715;">. See <a href="https.html">HTTPS</a> for
details.</span></p><h2 id="Security-ControllingPageAccess"><span
style="text-align: justify;line-height: 1.4285715;">Controlling Page
Access</span></h2><p><plain-text-body>{float:right|background=#eee|padding=0
1em}
+ *JumpStart Demo:*
+ [Protecting
Pages|http://jumpstart.doublenegative.com.au/jumpstart/examples/infrastructure/protectingpages]
+{float}</plain-text-body><span style="text-align: justify;line-height:
1.4285715;">For simple access control needs, you can contribute a <span><a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ComponentRequestFilter.html">ComponentRequestFilter</a>
with your custom logic that decides which pages should be accessed by which
users. The <a class="external-link"
href="https://tapestry-app.apache.org/hotels/">Tapestry Hotel Booking </a>app
demonstrates this approach with an <code>@AnonymousAccess</code> annotation
along with a ComponentRequestFilter
named <code>AuthenticationFilter.java</code>. The filter enforces security
by intercepting all requests to pages that don't have that annotation, and it
redirects those requests to the login page. <a class="external-link"
href="http://jumpstart.doublenegative.com.au/jumpstart/examples/infrastructure/protectingpages"
rel="nofollow">JumpStart</a> has a similar demo.<br clear="no
ne"></span></span></p><p><span style="line-height: 1.4285715;text-align:
justify;">For more advanced needs see the Security Framework Integration
section below.</span></p><h2 id="Security-White-listedPages">White-listed
Pages</h2><p>Pages whose component classes are annotated with @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/WhitelistAccessOnly.html">WhitelistAccessOnly</a> will
only be displayed to users (clients) that are on the <em>whitelist</em>.
By default the whitelist consists only of clients whose fully-qualified domain
name is "localhost" (or the IP address equivalent, 127.0.0.1 or
0:0:0:0:0:0:0:1), but you can customize this by contributing to the
ClientWhitelist service in your application's module class (usually
AppModule.java):</p><parameter ac:name="language">java</parameter><parameter
ac:name="title">AppModule.java (partial) -- simple inline
example</parameter><plain-text-body>
@Contribute(ClientWhitelist.class)
public static void
provideWhitelistAnalyzer(OrderedConfiguration<WhitelistAnalyzer>
configuration)
{
configuration.add("MyCustomAnalyzer", new WhitelistAnalyzer()
@@ -142,10 +81,7 @@
return true;
}
}, "before:*");
- }</pre>
-</div></div><p> </p><p>Sometimes, in production, a firewall or proxy may
make it look like the client web browser originates from localhost, with the
consequence that whitelisted pages may be visible to all users. See the <a
href="security.html">Security FAQ</a> for how to deal with this.</p><h2
id="Security-AssetSecurity">Asset Security</h2><p>Main Article: <a
href="assets.html">Assets</a></p><p>Tapestry serves assets (static content such
as CSS files, images, and JavaScript, many of which are on the classpath
alongside your compiled class files) to the client. Because of this, great
care has gone into ensuring that certain file types cannot be served to the
client. By default, file ending with ".class', ".tml" and ".properties" can be
served to the client only if the request includes the file's MD5 checksum. As
you would expect, that blacklist can be extended. See <a
href="assets.html">Asset Security</a> for more information.</p><h2
id="Security-Protect
ingSerializedObjectDataontheClient">Protecting Serialized Object Data on the
Client</h2><p><span style="color: rgb(0,0,0);">As of version 5.3.6, Tapestry
integrates a </span><a class="external-link"
href="http://en.wikipedia.org/wiki/HMAC" rel="nofollow" style="text-decoration:
underline;text-align: justify;">hash-based message authentication code</a><span
style="color: rgb(0,0,0);"> (HMAC) into serialized Java object data that
it sends to the client (generally, this means the </span><code
style="text-align: justify;">t:formdata</code><span style="color:
rgb(0,0,0);"> hidden field used by the Form component). This ensures that
the hidden binary object data is guaranteed to be unaltered when it returns to
the server upon form (or AJAX) submission. The HMAC pass phrase is set using
the <a href="configuration.html">tapestry.hmac-passphrase</a>
configuration symbol. If you don't set that value, you'll see a warning message
in the browser, like this: </spa
n></p><div class="preformatted panel" style="border-width: 1px;"><div
class="preformattedContent panelContent">
-<pre>The symbol 'tapestry.hmac-passphrase' has not been configured. This is
used to configure hash-based message authentication of Tapestry data stored in
forms, or in the URL. You application is less secure, and more vulnerable to
denial-of-service attacks, when this symbol is not configured.</pre>
-</div></div><p><span style="color: rgb(0,0,0);">The solution is to set the
tapestry.hmac-passphrase to some value (any fixed, private string, such as 30
to 40 random-looking characters, will do) in your application's module class
(usually AppModule.java).</span></p><h2
id="Security-CrossSiteRequestForgery(CSRF)"><span style="color:
rgb(83,145,38);font-size: 20.0px;line-height: 1.5;">Cross Site Request Forgery
(CSRF)</span></h2><p>Cross Site Request Forgery is a type of security
vulnerability in which legitimate, authorized users may be made to unwittingly
submit malicious requests to your web application.</p><p><a
class="external-link"
href="https://github.com/porscheinformatik/tapestry-csrf-protection"
rel="nofollow">Tapestry-csrf-protection</a> is a 3rd party module that has
several features for preventing CSRF attacks. It protects
all <span>component event handlers (event links, forms, etc.) by adding
a </span><span>CSRF token to event links and adds a CSRF token
as a hidden field to all forms. </span><span>Tokens are generated on a
per-session basis.</span></p><h2
id="Security-SecurityFrameworkIntegration"><span style="line-height:
1.5;">Security Framework Integration</span></h2><p>Tapestry does not lock you
into a specific authentication/authorization implementation. There are
integration modules available for the more popular open source Java security
frameworks. A popular choice among Tapestry users is <a class="external-link"
href="http://www.tynamo.org/tapestry-security+guide/"
rel="nofollow">tapestry-security (based on Apache Shiro) from Tynamo.org</a>.
It is always kept up-to-date with the latest Tapestry versions and offers
several supporting security modules (e.g. <a class="external-link"
href="http://www.tynamo.org/tapestry-security-jpa+guide/"
rel="nofollow">tapestry-security-jpa</a>, <a class="external-link"
href="http://www.tynamo.org/tynamo-federatedaccounts+guide/"
rel="nofollow">tynamo-federatedaccounts</a>). There's
also an <a class="external-link"
href="http://www.localhost.nu/java/tapestry-spring-security"
rel="nofollow">integration module available for Spring Security</a> but lately,
it hasn't kept up with the latest versions of Tapestry 5.</p><p>Additional
information:</p><ul><li><a class="external-link"
href="http://www.tynamo.org/tynamo-federatedaccounts+guide/"
rel="nofollow">Tynamo-federatedaccounts</a> <span style="color:
rgb(0,0,0);">is an add-on to the </span><a class="external-link"
href="http://www.tynamo.org/tapestry-security+guide/"
rel="nofollow">tapestry-security</a><span style="color:
rgb(0,0,0);"> module, providing federated (third-party) authentication
with Facebook, Twitter or Google.</span></li></ul><ul><li><span
style="line-height: 1.4285715;">To include OpenID with Spring Security in your
application, see the following Wiki entry: </span><a
class="external-link"
href="http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId"
style="l
ine-height:
1.4285715;">http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId</a></li></ul><p> </p></div>
+ }</plain-text-body><p> </p><p>Sometimes, in production, a firewall or
proxy may make it look like the client web browser originates from localhost,
with the consequence that whitelisted pages may be visible to all users. See
the <a href="security.html">Security FAQ</a> for how to deal with
this.</p><h2 id="Security-AssetSecurity">Asset Security</h2><p>Main
Article: <a href="assets.html">Assets</a></p><p>Tapestry serves assets
(static content such as CSS files, images, and JavaScript, many of which are on
the classpath alongside your compiled class files) to the client. Because
of this, great care has gone into ensuring that certain file types cannot be
served to the client. By default, file ending with ".class', ".tml" and
".properties" can be served to the client only if the request includes the
file's MD5 checksum. As you would expect, that blacklist can be extended.
See <a href="assets.html">Asset Security</a> for more information.</p><h2
id="Secur
ity-ProtectingSerializedObjectDataontheClient">Protecting Serialized Object
Data on the Client</h2><p><span style="color: rgb(0,0,0);">As of version 5.3.6,
Tapestry integrates a </span><a class="external-link"
href="http://en.wikipedia.org/wiki/HMAC" rel="nofollow" style="text-decoration:
underline;text-align: justify;">hash-based message authentication code</a><span
style="color: rgb(0,0,0);"> (HMAC) into serialized Java object data that
it sends to the client (generally, this means the </span><code
style="text-align: justify;">t:formdata</code><span style="color:
rgb(0,0,0);"> hidden field used by the Form component). This ensures that
the hidden binary object data is guaranteed to be unaltered when it returns to
the server upon form (or AJAX) submission. The HMAC pass phrase is set using
the <a href="configuration.html">tapestry.hmac-passphrase</a>
configuration symbol. If you don't set that value, you'll see a warning message
in the browser, like this:
 </span></p><plain-text-body>The symbol 'tapestry.hmac-passphrase' has
not been configured. This is used to configure hash-based message
authentication of Tapestry data stored in forms, or in the URL. You application
is less secure, and more vulnerable to denial-of-service attacks, when this
symbol is not configured.</plain-text-body><p><span style="color:
rgb(0,0,0);">The solution is to set the tapestry.hmac-passphrase to some value
(any fixed, private string, such as 30 to 40 random-looking characters, will
do) in your application's module class (usually AppModule.java).</span></p><h2
id="Security-CrossSiteRequestForgery(CSRF)"><span style="color:
rgb(83,145,38);font-size: 20.0px;line-height: 1.5;">Cross Site Request Forgery
(CSRF)</span></h2><p>Cross Site Request Forgery is a type of security
vulnerability in which legitimate, authorized users may be made to unwittingly
submit malicious requests to your web application.</p><p><a
class="external-link" href="https://github.co
m/porscheinformatik/tapestry-csrf-protection"
rel="nofollow">Tapestry-csrf-protection</a> is a 3rd party module that has
several features for preventing CSRF attacks. It protects
all <span>component event handlers (event links, forms, etc.) by adding
a </span><span>CSRF token to event links and adds a CSRF token as a hidden
field to all forms. </span><span>Tokens are generated on a per-session
basis.</span></p><h2 id="Security-SecurityFrameworkIntegration"><span
style="line-height: 1.5;">Security Framework Integration</span></h2><p>Tapestry
does not lock you into a specific authentication/authorization implementation.
There are integration modules available for the more popular open source Java
security frameworks. A popular choice among Tapestry users is <a
class="external-link" href="http://www.tynamo.org/tapestry-security+guide/"
rel="nofollow">tapestry-security (based on Apache Shiro) from Tynamo.org</a>.
It is always kept up-to-date with the latest Tapestry
versions and offers several supporting security modules (e.g. <a
class="external-link" href="http://www.tynamo.org/tapestry-security-jpa+guide/"
rel="nofollow">tapestry-security-jpa</a>, <a class="external-link"
href="http://www.tynamo.org/tynamo-federatedaccounts+guide/"
rel="nofollow">tynamo-federatedaccounts</a>). There's also an <a
class="external-link"
href="http://www.localhost.nu/java/tapestry-spring-security"
rel="nofollow">integration module available for Spring Security</a> but lately,
it hasn't kept up with the latest versions of Tapestry 5.</p><p>Additional
information:</p><ul><li><a class="external-link"
href="http://www.tynamo.org/tynamo-federatedaccounts+guide/"
rel="nofollow">Tynamo-federatedaccounts</a> <span style="color:
rgb(0,0,0);">is an add-on to the </span><a class="external-link"
href="http://www.tynamo.org/tapestry-security+guide/"
rel="nofollow">tapestry-security</a><span style="color:
rgb(0,0,0);"> module, providing federated (third-pa
rty) authentication with Facebook, Twitter or
Google.</span></li></ul><ul><li><span style="line-height: 1.4285715;">To
include OpenID with Spring Security in your application, see the following Wiki
entry: </span><a class="external-link"
href="http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId"
style="line-height:
1.4285715;">http://wiki.apache.org/tapestry/Tapestry5HowToSpringSecurityAndOpenId</a></li></ul><p> </p></div>
</div>
<div class="clearer"></div>
Modified: websites/production/tapestry/content/specific-errors-faq.html
==============================================================================
--- websites/production/tapestry/content/specific-errors-faq.html (original)
+++ websites/production/tapestry/content/specific-errors-faq.html Tue Sep 26
19:20:27 2017
@@ -27,16 +27,6 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
- <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
- <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
- <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
- <script>
- SyntaxHighlighter.defaults['toolbar'] = false;
- SyntaxHighlighter.all();
- </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -77,50 +67,7 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><div class="aui-label"
style="float:right" title="Related Articles">
-
-
-
-
-
-
-
-
-<h3>Related Articles</h3>
-
-<ul class="content-by-label"><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="error-page-recipe.html">Error Page Recipe</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="specific-errors-faq.html">Specific Errors
FAQ</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a
href="overriding-exception-reporting.html">Overriding Exception Reporting</a>
-
-
- </div>
- </li></ul>
-</div>
-
-
-<h3
id="SpecificErrorsFAQ-WhydoIgettheexception"Noserviceimplementstheinterfaceorg.apache.tapestry5.internal.InternalComponentResources"whentryingtousetheBeanEditFormcomponent?">Why
do I get the exception "No service implements the interface
org.apache.tapestry5.internal.InternalComponentResources" when trying to use
the BeanEditForm component?</h3><p>This can occur when you choose the wrong
package for your data object, the object edited by the BeanEditForm component.
If you place it in the same package as your pages, Tapestry will treat it like
a page, and perform a number of transformation on it, including adding a new
constructor.</p><p>Only component classes should go in the Tapestry-controlled
packages (<code>pages</code>, <code>components</code>, <code>mixins</code> and
<code>base</code> under your application's root package). By convention, simple
data objects should go in a <code>data</code> package, and Hibernate entities
should go in an <code>entities</code> pac
kage.</p><div class="confluence-information-macro
confluence-information-macro-note"><span class="aui-icon aui-icon-small
aui-iconfont-warning confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>This is likely a bit different in
5.3 than in 5.2 (because 5.3 builds a very different constructor into the
component) and needs to be tested in 5.3 to see what exact exception will
occur.</p></div></div><h3
id="SpecificErrorsFAQ-Igetanerrorabout"Pagedidnotgenerateanymarkupwhenrendered."butIhaveatemplate,whathappened?">I
get an error about "Page did not generate any markup when rendered." but I
have a template, what happened?</h3><p>The most common error here is that the
case of the page class did not match the case of the template. For example, you
might name your class ViewOrders, but name the template vieworders.tml. The
correct name for the template is ViewOrders.tml, matching the case of the Java
class name.</p><p>Worse, you may find tha
t your application works during development (under Windows, which is case
insensitive) but does not work when deployed on a Linux or Unix server, which
may be case sensitive.</p><p>The other cause of this may be that your template
files simply are not being packaged up correctly with the rest of your
application. When in doubt, use the Java <code>jar</code> command to see
exactly whats inside your WAR file. Your page templates should either be in the
root folder of the WAR, or package with the corresponding .class file.</p><h3
id="SpecificErrorsFAQ-MyapplicationfailswiththeerrorPermGen,howdoIfixthis?">My
application fails with the error <strong>PermGen</strong>, how do I fix
this?</h3><p>PermGen refers to the part of the Java memory space devoted to
permanent objects, which are mostly loaded classes. When developing under
Tapestry, many more classes and class loaders are created than normal; this is
part of live class reloading. Because of this, you will want to increase the
amount
of memory Java devotes to this.</p><p>The solution is to add
<code>-XX:MaxPermSize=512m</code> to your command line. You may also want to
increase the regular amount of heap space with <code>-Xmx600M</code>. Of
course, you may need to adjust the amount of memory in each category to match
your actual application, but these are good starting values.</p><p>Java Virtual
Machine arguments can be specified inside an Eclipse launch
configuration:</p><p><span class="confluence-embedded-file-wrapper"><img
class="confluence-embedded-image confluence-thumbnail"
src="specific-errors-faq.data/eclipse-permgen.png"></span></p><h3
id="SpecificErrorsFAQ-WhydoIsometimesgetajava.lang.NoSuchMethodErrorexceptionafterreloadingmypage?">Why
do I sometimes get a <code>java.lang.NoSuchMethodError</code> exception after
reloading my page?</h3><p>Tapestry's live class reloading is not
perfect. <span style="line-height: 1.4285715;">It tends to use a lot of
Java ClassLoaders on top of the normal ClassLoader
s used by the Java Virtual Machine and the servlet container. When you change
non-component classes and interfaces that are referenced by components and
pages, such as to add or change a method, only the component classes are
reloaded. The non-component classes are frozen as they were when they were
</span><em style="line-height: 1.4285715;">first</em><span style="line-height:
1.4285715;"> loaded.</span></p><p>Unfortunately, this is one of the areas where
you must restart your application entirely in order to force the new versions
of the non-component classes to be loaded into memory.</p><h3
id="SpecificErrorsFAQ-Whydomylogscontain"java.lang.RuntimeException:FormsrequirethattherequestmethodbePOSTandthatthet:formdataqueryparameterhavevalues"?">Why
do my logs contain "java.lang.RuntimeException: Forms require that the request
method be POST and that the t:formdata query parameter have
values"?</h3><p>This is caused by someone (or something) submitting the URL of
your form u
sing an HTTP GET instead of POST. Tapestry forms must always use POST
actions.</p><p>Some known scenarios that cause this error:</p><ul><li>Bots
crawling your site</li><li>Web browser auto-complete functions trying to be
helpful</li><li>Users with browser developer tools manually modifying the form
from a POST to a GET to see what will happen.</li><li>Users getting a
validation error on a form, then re-submitting the form by clicking in the URL
address field and hitting Enter.</li><li>In Tapestry versions before 5.4,
(rarely) the use of property names for form fields where the property name
matches a JavaScript property (see <a class="external-link"
href="https://issues.apache.org/jira/browse/TAP5-2066">TAP5-2066</a>).</li></ul><p>In
every known scenario except the last, these errors are harmless and you
probably want to redirect the user to the page the form is on – and avoid
logging an error. That's not too hard to do. Just add code like the following
to your module class (
usually AppModule.java):</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent
pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> /**
+ <div
id="ConfluenceContent"><p><plain-text-body>{scrollbar}</plain-text-body></p><parameter
ac:name="style">float:right</parameter><parameter ac:name="title">Related
Articles</parameter><parameter
ac:name="class">aui-label</parameter><rich-text-body><parameter
ac:name="showLabels">false</parameter><parameter
ac:name="showSpace">false</parameter><parameter ac:name="title">Related
Articles</parameter><parameter ac:name="cql">label = "errors" and space =
currentSpace()</parameter></rich-text-body><h3
id="SpecificErrorsFAQ-WhydoIgettheexception"Noserviceimplementstheinterfaceorg.apache.tapestry5.internal.InternalComponentResources"whentryingtousetheBeanEditFormcomponent?">Why
do I get the exception "No service implements the interface
org.apache.tapestry5.internal.InternalComponentResources" when trying to use
the BeanEditForm component?</h3><p>This can occur when you choose the wrong
package for your data object, the object edited by the BeanEditForm component
. If you place it in the same package as your pages, Tapestry will treat it
like a page, and perform a number of transformation on it, including adding a
new constructor.</p><p>Only component classes should go in the
Tapestry-controlled packages (<code>pages</code>, <code>components</code>,
<code>mixins</code> and <code>base</code> under your application's root
package). By convention, simple data objects should go in a <code>data</code>
package, and Hibernate entities should go in an <code>entities</code>
package.</p><rich-text-body><p>This is likely a bit different in 5.3 than in
5.2 (because 5.3 builds a very different constructor into the component) and
needs to be tested in 5.3 to see what exact exception will
occur.</p></rich-text-body><h3
id="SpecificErrorsFAQ-Igetanerrorabout"Pagedidnotgenerateanymarkupwhenrendered."butIhaveatemplate,whathappened?">I
get an error about "Page did not generate any markup when rendered." but I
have a template, what happened?</h3><p>Th
e most common error here is that the case of the page class did not match the
case of the template. For example, you might name your class ViewOrders, but
name the template vieworders.tml. The correct name for the template is
ViewOrders.tml, matching the case of the Java class name.</p><p>Worse, you may
find that your application works during development (under Windows, which is
case insensitive) but does not work when deployed on a Linux or Unix server,
which may be case sensitive.</p><p>The other cause of this may be that your
template files simply are not being packaged up correctly with the rest of your
application. When in doubt, use the Java <code>jar</code> command to see
exactly whats inside your WAR file. Your page templates should either be in the
root folder of the WAR, or package with the corresponding .class file.</p><h3
id="SpecificErrorsFAQ-MyapplicationfailswiththeerrorPermGen,howdoIfixthis?">My
application fails with the error <strong>PermGen</strong>, how do I fix
this?</h3><p>PermGen refers to the part of the Java memory space devoted to
permanent objects, which are mostly loaded classes. When developing under
Tapestry, many more classes and class loaders are created than normal; this is
part of live class reloading. Because of this, you will want to increase the
amount of memory Java devotes to this.</p><p>The solution is to add
<code>-XX:MaxPermSize=512m</code> to your command line. You may also want to
increase the regular amount of heap space with <code>-Xmx600M</code>. Of
course, you may need to adjust the amount of memory in each category to match
your actual application, but these are good starting values.</p><p>Java Virtual
Machine arguments can be specified inside an Eclipse launch
configuration:</p><p><span class="confluence-embedded-file-wrapper"><img
class="confluence-embedded-image confluence-thumbnail"
src="specific-errors-faq.data/eclipse-permgen.png"></span></p><h3
id="SpecificErrorsFAQ-WhydoIsometimesgetajava.lang.NoSuchMeth
odErrorexceptionafterreloadingmypage?">Why do I sometimes get a
<code>java.lang.NoSuchMethodError</code> exception after reloading my
page?</h3><p>Tapestry's live class reloading is not perfect. <span
style="line-height: 1.4285715;">It tends to use a lot of Java ClassLoaders on
top of the normal ClassLoaders used by the Java Virtual Machine and the servlet
container. When you change non-component classes and interfaces that are
referenced by components and pages, such as to add or change a method, only the
component classes are reloaded. The non-component classes are frozen as they
were when they were </span><em style="line-height: 1.4285715;">first</em><span
style="line-height: 1.4285715;"> loaded.</span></p><p>Unfortunately, this is
one of the areas where you must restart your application entirely in order to
force the new versions of the non-component classes to be loaded into
memory.</p><h3
id="SpecificErrorsFAQ-Whydomylogscontain"java.lang.RuntimeException:Formsrequir
ethattherequestmethodbePOSTandthatthet:formdataqueryparameterhavevalues"?">Why
do my logs contain "java.lang.RuntimeException: Forms require that the request
method be POST and that the t:formdata query parameter have
values"?</h3><p>This is caused by someone (or something) submitting the URL of
your form using an HTTP GET instead of POST. Tapestry forms must always use
POST actions.</p><p>Some known scenarios that cause this error:</p><ul><li>Bots
crawling your site</li><li>Web browser auto-complete functions trying to be
helpful</li><li>Users with browser developer tools manually modifying the form
from a POST to a GET to see what will happen.</li><li>Users getting a
validation error on a form, then re-submitting the form by clicking in the URL
address field and hitting Enter.</li><li>In Tapestry versions before 5.4,
(rarely) the use of property names for form fields where the property name
matches a JavaScript property (see <a class="external-link"
href="https://issues.apac
he.org/jira/browse/TAP5-2066">TAP5-2066</a>).</li></ul><p>In every known
scenario except the last, these errors are harmless and you probably want to
redirect the user to the page the form is on – and avoid logging an
error. That's not too hard to do. Just add code like the following to your
module class (usually AppModule.java):</p><parameter
ac:name="language">java</parameter><parameter ac:name="title">AppModule.java
(partial)</parameter><plain-text-body> /**
* Redirect the user to the intended page when browsing through
* tapestry forms through browser history or over-eager autocomplete
*/
@@ -145,8 +92,7 @@
response.sendRedirect(uri);
}
};
- }</pre>
-</div></div><p><em>Thanks to <a class="external-link"
href="http://mail-archives.apache.org/mod_mbox/tapestry-users/201110.mbox/%[email protected]%3E">Lenny
Primak</a> for the above code. A slightly less fragile approach is <a
class="external-link"
href="https://mail-archives.apache.org/mod_mbox/tapestry-users/201509.mbox/%3ccae26fnjevncyv52kms-kpsewwnaln9pg6lg60xzkxuhs0ut...@mail.gmail.com%3E">described
here</a>. When <a class="external-link"
href="https://issues.apache.org/jira/browse/TAP5-1733">TAP5-1733</a> is fixed a
much less fragile solution may be possible.</em></p><p> </p></div>
+ }</plain-text-body><p><em>Thanks to <a class="external-link"
href="http://mail-archives.apache.org/mod_mbox/tapestry-users/201110.mbox/%[email protected]%3E">Lenny
Primak</a> for the above code. A slightly less fragile approach is <a
class="external-link"
href="https://mail-archives.apache.org/mod_mbox/tapestry-users/201509.mbox/%3ccae26fnjevncyv52kms-kpsewwnaln9pg6lg60xzkxuhs0ut...@mail.gmail.com%3E">described
here</a>. When <a class="external-link"
href="https://issues.apache.org/jira/browse/TAP5-1733">TAP5-1733</a> is fixed a
much less fragile solution may be
possible.</em></p><p> <plain-text-body>{scrollbar}</plain-text-body></p></div>
</div>
<div class="clearer"></div>
Modified: websites/production/tapestry/content/switching-cases.html
==============================================================================
--- websites/production/tapestry/content/switching-cases.html (original)
+++ websites/production/tapestry/content/switching-cases.html Tue Sep 26
19:20:27 2017
@@ -27,16 +27,6 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
- <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
- <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
- <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
- <script>
- SyntaxHighlighter.defaults['toolbar'] = false;
- SyntaxHighlighter.all();
- </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -77,10 +67,10 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><p> </p><h1
id="SwitchingCases-SwitchingCases">Switching Cases</h1><p>With Tapestry's
<code>If</code> component you can only test one condition at a time. In order
to distinguish multiple cases, you'd have to write complex nested if/else
constructs in your page template and have a checker method for each test inside
your page class.</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/lang/ifnotnegateswitchelseunless"
rel="nofollow">If, Not, Negate, Switch, Else, Unless</a></p></div>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>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_1_0.xsd">
+ <div id="ConfluenceContent"><p> </p><parameter
ac:name="hidden">true</parameter><parameter
ac:name="atlassian-macro-output-type">BLOCK</parameter><rich-text-body><p>Performing
the equivalent of a "switch" statement in your component template using blocks
and a delegate</p></rich-text-body><h1
id="SwitchingCases-SwitchingCases">Switching Cases</h1><p>With Tapestry's
<code>If</code> component you can only test one condition at a time. In order
to distinguish multiple cases, you'd have to write complex nested if/else
constructs in your page template and have a checker method for each test inside
your page class.<plain-text-body>{float:right|background=#eee|padding=0 1em}
+ *JumpStart Demo:*
+ [If, Not, Negate, Switch, Else,
Unless|http://jumpstart.doublenegative.com.au/jumpstart/examples/lang/ifnotnegateswitchelseunless]
+{float}</plain-text-body>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><parameter ac:name="language">xml</parameter><parameter
ac:name="title">SwitchMe.tml</parameter><plain-text-body><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
<body>
<h1>Switch</h1>
@@ -103,9 +93,7 @@
</t:block>
</body>
</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
+</plain-text-body><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><parameter
ac:name="language">java</parameter><parameter
ac:name="title">SwitchMe.java</parameter><plain-text-body>public class SwitchMe
{
@Persist
private int whichCase;
@@ -130,8 +118,7 @@
}
}
}
-</pre>
-</div></div><p>Happy switching!</p></div>
+</plain-text-body><p>Happy switching!</p></div>
</div>
<div class="clearer"></div>
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
Tue Sep 26 19:20:27 2017
@@ -27,16 +27,6 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
- <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
- <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
- <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
- <script>
- SyntaxHighlighter.defaults['toolbar'] = false;
- SyntaxHighlighter.all();
- </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -77,59 +67,7 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><h2
id="TapestryInversionofControlFAQ-TapestryInversionofControlContainer">Tapestry
Inversion of Control Container</h2><p>Main article: <a
href="ioc.html">Tapestry IoC</a></p><p> </p><div class="aui-label"
style="float:right" title="Related Articles">
-
-
-
-
-
-
-
-
-<h3>Related Articles</h3>
-
-<ul class="content-by-label"><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="ioc.html">IOC</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="ioc-cookbook.html">IoC cookbook</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a href="tapestry-ioc-overview.html">Tapestry IoC
Overview</a>
-
-
- </div>
- </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
-
- <div class="details">
- <a
href="tapestry-inversion-of-control-faq.html">Tapestry Inversion of Control
FAQ</a>
-
-
- </div>
- </li></ul>
-</div>
-
-
-<h3
id="TapestryInversionofControlFAQ-WhydoIneedtodefineaninterfaceformyservices?Whycan'tIjustusetheclassitself?">Why
do I need to define an interface for my services? Why can't I just use the
class itself?</h3><p>First of all: you can do exactly this, but you lose some
of the functionality that Tapestry's IoC container provides.</p><p>The reason
for the split is so that Tapestry can provide functionality for your service
around the core service implementation. It does this by creating
<em>proxies</em>: Java classes that implement the service interface. The
methods of the proxy will ultimately invoke the methods of your service
implementation.</p><p>One of the primary purposes for proxies is to encapsulate
the service's life cycle: most services are singletons that are created
<em>just in time</em>. Just in time means only as soon as you invoke a method.
What's going on is that the life cycle proxy (the object that gets injected
into pages, components or other service implementation
s) checks on each method invocation to see if the actual service exists yet.
If not, it instantiates and configures it (using proper locking to ensure
thread safety), then delegates the method invocation to the service.</p><p>If
you bind a service class (not a service interface and class), then the service
is fully instantiated the first time it is injected, rather than at that first
method invocation. Further, you can't use decorations or method advice on such
a service.</p><p>The final reason for the service interface / implementation
split is to nudge you towards always coding to an interface, which has manifest
benefits for code structure, robustness, and testability.</p><h3
id="TapestryInversionofControlFAQ-Myservicestartsathread;howdoIknowwhentheapplicationisshuttingdown,tostopthatthread?">My
service starts a thread; how do I know when the application is shutting down,
to stop that thread?</h3><p>This same concern applies to any long-lived
resource (a thread, a database connec
tion, a JMS queue connection) that a service may hold onto. Your code needs to
know when the application has been undeployed and shutdown. This is actually
quite easy, by adding some post-injection logic to your implementation
class.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: true; theme: Default"
style="font-size:12px;">public class MyServiceImpl implements MyService
+ <div
id="ConfluenceContent"><p><plain-text-body>{scrollbar}</plain-text-body></p><h2
id="TapestryInversionofControlFAQ-TapestryInversionofControlContainer">Tapestry
Inversion of Control Container</h2><p>Main article: <a
href="ioc.html">Tapestry IoC</a></p><p> </p><parameter
ac:name="style">float:right</parameter><parameter ac:name="title">Related
Articles</parameter><parameter
ac:name="class">aui-label</parameter><rich-text-body><parameter
ac:name="showLabels">false</parameter><parameter
ac:name="showSpace">false</parameter><parameter ac:name="title">Related
Articles</parameter><parameter ac:name="cql">label = "ioc" and space =
currentSpace()</parameter></rich-text-body><h3
id="TapestryInversionofControlFAQ-WhydoIneedtodefineaninterfaceformyservices?Whycan'tIjustusetheclassitself?">Why
do I need to define an interface for my services? Why can't I just use the
class itself?</h3><p>First of all: you can do exactly this, but you lose some
of the functionality that
Tapestry's IoC container provides.</p><p>The reason for the split is so that
Tapestry can provide functionality for your service around the core service
implementation. It does this by creating <em>proxies</em>: Java classes that
implement the service interface. The methods of the proxy will ultimately
invoke the methods of your service implementation.</p><p>One of the primary
purposes for proxies is to encapsulate the service's life cycle: most services
are singletons that are created <em>just in time</em>. Just in time means only
as soon as you invoke a method. What's going on is that the life cycle proxy
(the object that gets injected into pages, components or other service
implementations) checks on each method invocation to see if the actual service
exists yet. If not, it instantiates and configures it (using proper locking to
ensure thread safety), then delegates the method invocation to the
service.</p><p>If you bind a service class (not a service interface and class),
then
the service is fully instantiated the first time it is injected, rather than
at that first method invocation. Further, you can't use decorations or method
advice on such a service.</p><p>The final reason for the service interface /
implementation split is to nudge you towards always coding to an interface,
which has manifest benefits for code structure, robustness, and
testability.</p><h3
id="TapestryInversionofControlFAQ-Myservicestartsathread;howdoIknowwhentheapplicationisshuttingdown,tostopthatthread?">My
service starts a thread; how do I know when the application is shutting down,
to stop that thread?</h3><p>This same concern applies to any long-lived
resource (a thread, a database connection, a JMS queue connection) that a
service may hold onto. Your code needs to know when the application has been
undeployed and shutdown. This is actually quite easy, by adding some
post-injection logic to your implementation class.</p><parameter
ac:name="controls">true</parameter><parameter ac
:name="linenumbers">true</parameter><plain-text-body>public class
MyServiceImpl implements MyService
{
private boolean shuttingDown;
@@ -156,8 +94,7 @@
});
}
}
-</pre>
-</div></div><p>After Tapestry invokes the constructor of the service
implementation, and after it performs any field injections, it invokes post
injection methods. The methods must be public and return void. Parameters to a
post injection method represent further injections ... in the above example,
the RegistryShutdownHub is injected into the PostInjection method, since it is
only used inside that one method.</p><div class="confluence-information-macro
confluence-information-macro-warning"><span class="aui-icon aui-icon-small
aui-iconfont-error confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>It is <strong>not</strong>
recommended that MyServiceImpl take RegistryShutdownHub as a constructor
parameter and register itself as a listener inside the constructor. Doing so is
an example of <a class="external-link"
href="http://www.ibm.com/developerworks/java/library/j-jtp0618.html"
rel="nofollow">unsafe publishing</a>, a remote but potential thr
ead safety issue.</p></div></div><p>This same technique will work for any kind
of resource that must be cleaned up or destroyed when the registry shuts
down.</p><div class="confluence-information-macro
confluence-information-macro-note"><span class="aui-icon aui-icon-small
aui-iconfont-warning confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Be careful not to invoke methods
on any service proxy objects as they will also be shutting down with the
Registry. A RegistryShutdownListener should not be reliant on anything outside
of itself.</p></div></div><h3
id="TapestryInversionofControlFAQ-HowdoImakemyservicestartupwiththerestoftheapplication,ratherthanlazily?">How
do I make my service startup with the rest of the application, rather than
lazily?</h3><p>Tapestry services are designed to be <em>lazy</em>; they are
only fully realized when needed: when the first method on the service interface
is invoked.</p><p>Sometimes a service does extra work
that is desirable at application startup: examples may be registering message
handlers with a JMS implementation, or setting up indexing. Since the service's
constructor (or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/PostInjection.html">@PostInjection</a>
methods) are not invoked until the service is realized.</p><p>The solution is
the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/EagerLoad.html">@EagerLoad</a>
annotation; service implementation classes marked with this annotation are
loaded when the Registry is first startup, rather than lazily.</p></div>
+</plain-text-body><p>After Tapestry invokes the constructor of the service
implementation, and after it performs any field injections, it invokes post
injection methods. The methods must be public and return void. Parameters to a
post injection method represent further injections ... in the above example,
the RegistryShutdownHub is injected into the PostInjection method, since it is
only used inside that one method.</p><rich-text-body><p>It is
<strong>not</strong> recommended that MyServiceImpl take RegistryShutdownHub as
a constructor parameter and register itself as a listener inside the
constructor. Doing so is an example of <a class="external-link"
href="http://www.ibm.com/developerworks/java/library/j-jtp0618.html"
rel="nofollow">unsafe publishing</a>, a remote but potential thread safety
issue.</p></rich-text-body><p>This same technique will work for any kind of
resource that must be cleaned up or destroyed when the registry shuts
down.</p><rich-text-body><p>Be careful not to
invoke methods on any service proxy objects as they will also be shutting
down with the Registry. A RegistryShutdownListener should not be reliant on
anything outside of itself.</p></rich-text-body><h3
id="TapestryInversionofControlFAQ-HowdoImakemyservicestartupwiththerestoftheapplication,ratherthanlazily?">How
do I make my service startup with the rest of the application, rather than
lazily?</h3><p>Tapestry services are designed to be <em>lazy</em>; they are
only fully realized when needed: when the first method on the service interface
is invoked.</p><p>Sometimes a service does extra work that is desirable at
application startup: examples may be registering message handlers with a JMS
implementation, or setting up indexing. Since the service's constructor (or <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/PostInjection.html">@PostInjection</a>
methods) are not invoked until the service is realized.</p><p>The solutio
n is the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/EagerLoad.html">@EagerLoad</a>
annotation; service implementation classes marked with this annotation are
loaded when the Registry is first startup, rather than
lazily.<plain-text-body>{scrollbar}</plain-text-body></p></div>
</div>
<div class="clearer"></div>
Modified: websites/production/tapestry/content/templating-and-markup-faq.html
==============================================================================
--- websites/production/tapestry/content/templating-and-markup-faq.html
(original)
+++ websites/production/tapestry/content/templating-and-markup-faq.html Tue Sep
26 19:20:27 2017
@@ -27,16 +27,6 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
- <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
- <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
- <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
- <script>
- SyntaxHighlighter.defaults['toolbar'] = false;
- SyntaxHighlighter.all();
- </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -77,52 +67,29 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><h2
id="TemplatingandMarkupFAQ-TemplatingandMarkup">Templating and
Markup</h2><p>Main Article: <a href="component-templates.html">Component
Templates</a></p><h3
id="TemplatingandMarkupFAQ-WhydoIgetaSAXParseExceptionwhenIuseanHTMLentity,suchas&nbsp;inmytemplate?">Why
do I get a SAXParseException when I use an HTML entity, such as
<code>&nbsp;</code> in my template?</h3><p>Tapestry uses a standard SAX
parser to read your templates. This means that your templates must be <em>well
formed</em>: open and close tags must balance, attribute values must be quoted,
and entities must be declared. The easiest way to accomplish this is to add a
DOCTYPE to your the top of your template:</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;"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN"
+ <div
id="ConfluenceContent"><plain-text-body>{scrollbar}</plain-text-body><h2
id="TemplatingandMarkupFAQ-TemplatingandMarkup">Templating and
Markup</h2><p>Main Article: <a href="component-templates.html">Component
Templates</a></p><h3
id="TemplatingandMarkupFAQ-WhydoIgetaSAXParseExceptionwhenIuseanHTMLentity,suchas&nbsp;inmytemplate?">Why
do I get a SAXParseException when I use an HTML entity, such as
<code>&nbsp;</code> in my template?</h3><p>Tapestry uses a standard SAX
parser to read your templates. This means that your templates must be <em>well
formed</em>: open and close tags must balance, attribute values must be quoted,
and entities must be declared. The easiest way to accomplish this is to add a
DOCTYPE to your the top of your template:</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">xml</parameter><plain-text-body><!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-</pre>
-</div></div><p>Part of the DOCTYPE is the declaration of entities such as
<code>&nbsp;</code>.</p><p>Alternately, you can simply use the numeric
version: <code>&#160</code>; This is the exact same character and will
render identically in the browser.</p><p>Starting in release 5.3, Tapestry
introduces an XHTML doctype when no doctype is present; this means that common
HTML entities will work correctly.</p><h3
id="TemplatingandMarkupFAQ-Whydosomeimagesinmypageshowupasbrokenlinks?">Why do
some images in my page show up as broken links?</h3><p>You have to be careful
when using relative URLs inside page templates; the base URL may not always be
what you expect. For example, inside your <code>ViewUser.tml</code> file, you
may have:</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;"> <img class="icon"
src="icons/admin.png"/>${user.name} has Administrative access
-</pre>
-</div></div><p>This makes sense; ViewUser.tml is in the web context, as is the
icons folder. The default URL for this page will be /viewuser (assuming that
ViewUser class is in the  <em>root-package</em>.pages
package).</p><p>However, the ViewUser page might use a page activation context
to identify which user is to be displayed:</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 ViewUser
+</plain-text-body><p>Part of the DOCTYPE is the declaration of entities such
as <code>&nbsp;</code>.</p><p>Alternately, you can simply use the numeric
version: <code>&#160</code>; This is the exact same character and will
render identically in the browser.</p><p>Starting in release 5.3, Tapestry
introduces an XHTML doctype when no doctype is present; this means that common
HTML entities will work correctly.</p><h3
id="TemplatingandMarkupFAQ-Whydosomeimagesinmypageshowupasbrokenlinks?">Why do
some images in my page show up as broken links?</h3><p>You have to be careful
when using relative URLs inside page templates; the base URL may not always be
what you expect. For example, inside your <code>ViewUser.tml</code> file, you
may have:</p><parameter ac:name="controls">true</parameter><parameter
ac:name="language">xml</parameter><plain-text-body> <img class="icon"
src="icons/admin.png"/>${user.name} has Administrative access
+</plain-text-body><p>This makes sense; ViewUser.tml is in the web context, as
is the icons folder. The default URL for this page will be /viewuser (assuming
that ViewUser class is in the  <em>root-package</em>.pages
package).</p><p>However, the ViewUser page might use a page activation context
to identify which user is to be displayed:</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">java</parameter><plain-text-body>public class ViewUser
@Property
@PageActivationContext
private User user;
. . .
-</pre>
-</div></div><p>With a page activation context, the URL for the page will
incorporate the ID of the User object, something like
<code>/viewuser/37371</code>. This is why the relative URL to the
<code>admin.png</code> image is broken: the base path is relative to the page's
URL, not to the page template. (In fact, the page template may not even be in
the web context, it may be stored on the classpath, as component templates
are.)</p><p>One solution would be to predict what the page URL will be, and
adjust the path for that:</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;"> <img class="icon"
src="../icons/admin.png"/>${user.name} has Administrative access
-</pre>
-</div></div><p>But this has its own problems; the page activation context may
vary in length at different times, or the template in question may be a
component used across many different pages, making it difficult to predict what
the correct relative URL would be.</p><p>The <em>best</em> solution for this
situation, one that will be sure to work in all pages and all components, is to
make use of the <code>context:</code> 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;"> <img class="icon"
src="${context:icons/admin.png}"/>${user.name} has Administrative access
-</pre>
-</div></div><p>The src attribute of the <img> tag will now be bound to a
dynamically computed value: the location of the image file relative to the web
application context. This is especially important for components that may be
used on different pages.</p><h3
id="TemplatingandMarkupFAQ-What'sthedifferencebetweenidandt:id?">What's the
difference between <code>id</code> and <code>t:id</code>?</h3><p>You might
occasionally see something like the following in a template:</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:zone id="status" t:id="statusZone">
-</pre>
-</div></div><p>Why two ids? Why are they different?</p><p>The
<code>t:id</code> attribute is the Tapestry component id. This id is unique
within its immediate container. This is the id you might use to inject the
component into your page class:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> @InjectComponent
+</plain-text-body><p>With a page activation context, the URL for the page will
incorporate the ID of the User object, something like
<code>/viewuser/37371</code>. This is why the relative URL to the
<code>admin.png</code> image is broken: the base path is relative to the page's
URL, not to the page template. (In fact, the page template may not even be in
the web context, it may be stored on the classpath, as component templates
are.)</p><p>One solution would be to predict what the page URL will be, and
adjust the path for that:</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">xml</parameter><plain-text-body> <img class="icon"
src="../icons/admin.png"/>${user.name} has Administrative access
+</plain-text-body><p>But this has its own problems; the page activation
context may vary in length at different times, or the template in question may
be a component used across many different pages, making it difficult to predict
what the correct relative URL would be.</p><p>The <em>best</em> solution for
this situation, one that will be sure to work in all pages and all components,
is to make use of the <code>context:</code> binding prefix:</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">xml</parameter><plain-text-body> <img class="icon"
src="${context:icons/admin.png}"/>${user.name} has Administrative access
+</plain-text-body><p>The src attribute of the <img> tag will now be
bound to a dynamically computed value: the location of the image file relative
to the web application context. This is especially important for components
that may be used on different pages.</p><h3
id="TemplatingandMarkupFAQ-What'sthedifferencebetweenidandt:id?">What's the
difference between <code>id</code> and <code>t:id</code>?</h3><p>You might
occasionally see something like the following in a template:</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">xml</parameter><plain-text-body><t:zone id="status"
t:id="statusZone">
+</plain-text-body><p>Why two ids? Why are they different?</p><p>The
<code>t:id</code> attribute is the Tapestry component id. This id is unique
within its immediate container. This is the id you might use to inject the
component into your page class:</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">java</parameter><plain-text-body> @InjectComponent
private Zone statusZone;
-</pre>
-</div></div><p>The other id is the client id, a unique id for the rendered
element within the client-side DOM. JavaScript that needs to access the element
uses this id. For example:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: text; gutter: false; theme: Default"
style="font-size:12px;"> $('status').hide();
-</pre>
-</div></div><p>In many components, the <code>id</code> attribute is an
informal parameter; a value from the template that is blindly echoed into the
output document. In other cases, the component itself has an <code>id</code>
attribute. Often, in the latter case, the Tapestry component id is the
<em>default</em> value for the client id.</p><h3
id="TemplatingandMarkupFAQ-WhydomyimagesandstylesheetsendupwithaweirdURLslike/assets/meta/zeea17aee26bc0cae/layout/layout.css?">Why
do my images and stylesheets end up with a weird URLs like
<code>/assets/meta/zeea17aee26bc0cae/layout/layout.css</code>?</h3><p>Tapestry
doesn't rely on the servlet container to serve up your static assets (images,
stylesheets, flash movies, etc.). Instead, Tapestry processes the requests
itself, streaming assets to the browser.</p><p>Asset content will be GZIP
compressed (if the client supports compression, and the content is
compressible). In addition, Tapestry will set a far-future expires header on
the conten
t. This means that the browser will not ask for the file again, greatly
reducing network traffic.</p><p>The weird hex string is
a <em>fingerprint</em>; it is a hash code computed from the actual content
of the asset. If the asset ever changes, it will have a new fingerprint, and so
will be a new path and a new (immutable) resource. This approach, combined with
a far-future expires header also provided by Tapestry, ensures that clients
aggressively cache assets as they navigate your site, or even between
visits.</p><p><span style="color: rgb(83,145,38);font-size: 16.0px;line-height:
1.5625;">How do I add a CSS class to a Tapestry component?</span></p><p>As they
say, "just do it". The majority of Tapestry components support <em>informal
parameters</em>, meaning that any extra attributes in the element (in the
template) will be rendered out as additional attributes. So, you can apply a
CSS class or style quite easily:</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:textfield t:id="username" class="big-green"/>
-</pre>
-</div></div><p>You can even use template expansions inside the attribute
value:</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:textfield t:id="username"
class="${usernameClass}"/>
-</pre>
-</div></div><p>and</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 String getUsernameClass()
+</plain-text-body><p>The other id is the client id, a unique id for the
rendered element within the client-side DOM. JavaScript that needs to access
the element uses this id. For example:</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">text</parameter><plain-text-body> $('status').hide();
+</plain-text-body><p>In many components, the <code>id</code> attribute is an
informal parameter; a value from the template that is blindly echoed into the
output document. In other cases, the component itself has an <code>id</code>
attribute. Often, in the latter case, the Tapestry component id is the
<em>default</em> value for the client id.</p><h3
id="TemplatingandMarkupFAQ-WhydomyimagesandstylesheetsendupwithaweirdURLslike/assets/meta/zeea17aee26bc0cae/layout/layout.css?">Why
do my images and stylesheets end up with a weird URLs like
<code>/assets/meta/zeea17aee26bc0cae/layout/layout.css</code>?</h3><p>Tapestry
doesn't rely on the servlet container to serve up your static assets (images,
stylesheets, flash movies, etc.). Instead, Tapestry processes the requests
itself, streaming assets to the browser.</p><p>Asset content will be GZIP
compressed (if the client supports compression, and the content is
compressible). In addition, Tapestry will set a far-future expires header on
the
content. This means that the browser will not ask for the file again, greatly
reducing network traffic.</p><p>The weird hex string is
a <em>fingerprint</em>; it is a hash code computed from the actual content
of the asset. If the asset ever changes, it will have a new fingerprint, and so
will be a new path and a new (immutable) resource. This approach, combined with
a far-future expires header also provided by Tapestry, ensures that clients
aggressively cache assets as they navigate your site, or even between
visits.</p><p><span style="color: rgb(83,145,38);font-size: 16.0px;line-height:
1.5625;">How do I add a CSS class to a Tapestry component?</span></p><p>As they
say, "just do it". The majority of Tapestry components support <em>informal
parameters</em>, meaning that any extra attributes in the element (in the
template) will be rendered out as additional attributes. So, you can apply a
CSS class or style quite easily:</p><parameter
ac:name="controls">true</parameter><paramet
er ac:name="language">xml</parameter><plain-text-body> <t:textfield
t:id="username" class="big-green"/>
+</plain-text-body><p>You can even use template expansions inside the attribute
value:</p><parameter ac:name="controls">true</parameter><parameter
ac:name="language">xml</parameter><plain-text-body> <t:textfield
t:id="username" class="${usernameClass}"/>
+</plain-text-body><p>and</p><parameter
ac:name="controls">true</parameter><parameter
ac:name="language">java</parameter><plain-text-body> public String
getUsernameClass()
{
return isUrgent() ? "urgent" : null;
}
-</pre>
-</div></div><p>When an informal parameter is bound to null, then the attribute
is not written out at all.</p><p>You can verify which components support
informal parameters by checking the component reference, or looking for the @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/SupportsInformalParameters.html">SupportsInformalParameters</a>
annotation in the components' source
file.</p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p></p><p></p><p></p><p></p><p></p><p></p><div
class="display-footnotes"></div>
-<p></p><p></p><p></p><p></p><p></p><p> </p><p> </p><p> </p><p> </p></div>
+</plain-text-body><p>When an informal parameter is bound to null, then the
attribute is not written out at all.</p><p>You can verify which components
support informal parameters by checking the component reference, or looking for
the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/SupportsInformalParameters.html">SupportsInformalParameters</a>
annotation in the components' source
file.</p><plain-text-body>{scrollbar}</plain-text-body><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p> </p><p> </p><p> </p><p> </p></div>
</div>
<div class="clearer"></div>
Modified: websites/production/tapestry/content/test-page.html
==============================================================================
--- websites/production/tapestry/content/test-page.html (original)
+++ websites/production/tapestry/content/test-page.html Tue Sep 26 19:20:27 2017
@@ -27,16 +27,6 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
- <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
- <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
- <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
- <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
- <script>
- SyntaxHighlighter.defaults['toolbar'] = false;
- SyntaxHighlighter.all();
- </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -80,51 +70,32 @@
<div id="ConfluenceContent"><p>Test page.</p>
<h2 id="TestPage-TabbedBlockTest">Tabbed Block Test</h2>
-<p></p><p>
-<style type="text/css">
+<p></p><p><plain-text-body>
+<style type="text/css">
DIV.deck DIV.tabBar DIV.tab { position: relative; top: 1px; background: #eee; }
DIV.deck DIV.tabBar DIV.tab#current { position: inherit; background: white; }
DIV.deck DIV.tabBar DIV.tab a { color: black; }
DIV.deck DIV.card {border: 1px solid #ccc; display: table-cell;}
-</style>
-</p><p></p>
+</style>
+</plain-text-body></p><p></p>
<h3 id="TestPage-Tabstest#1–usingCompositionmacro">Tabs test #1 –
using Composition macro</h3>
-<script type="text/javascript">//<![CDATA[
-function debug() { }
-// ]]></script><script type="text/javascript"
src="/confluence/download/resources/org.randombits.confluence.composition:composition-setup/js/browser.js">//<![CDATA[
-// ]]></script><script type="text/javascript"
src="/confluence/download/resources/org.randombits.confluence.composition:composition-setup/js/behaviour.js">//<![CDATA[
-// ]]></script><script type="text/javascript"
src="/confluence/download/resources/org.randombits.confluence.composition:composition-setup/js/memory.js">//<![CDATA[
-// ]]></script><script type="text/javascript"
src="/confluence/download/resources/org.randombits.confluence.composition:composition-setup/js/cloak.js">//<![CDATA[
-// ]]></script><script type="text/javascript">//<![CDATA[
-Cloak.closeHTML = "<img
src=\'/confluence/download/resources/org.randombits.confluence.composition:toggle-cloak/img/navigate_down_10.gif\'/>";
-Cloak.openHTML = "<img
src=\'/confluence/download/resources/org.randombits.confluence.composition:toggle-cloak/img/navigate_right_10.gif\'/>";
-Cloak.toggleZone = true;
-Cloak.memoryDuration = 0;
-Cloak.memoryPrefix = "contentId:24189280";
-Cloak.memoryPath = "/confluence/";
-// ]]></script><style type="text/css">
-.cloakToggle { /* Definition for state toggling image */
-cursor:hand;
-cursor:pointer;
-}
-</style><script type="text/javascript"
src="/confluence/download/resources/org.randombits.confluence.composition:composition-setup/js/transitions.js">//<![CDATA[
-// ]]></script><script type="text/javascript"
src="/confluence/download/resources/org.randombits.confluence.composition:composition-setup/js/deck.js">//<![CDATA[
-// ]]></script><link rel="stylesheet" type="text/css"
href="/confluence/styles/main-action.css?pluginCompleteKey=org.randombits.confluence.composition:composition-setup&stylesheetName=deck&spaceKey=TAPESTRY"><script
type="text/javascript">//<![CDATA[
-Deck.memoryDuration = 0;
-Deck.memoryPrefix = "contentId:24189280";
-Deck.memoryPath = "/confluence/";
-// ]]></script>
+<plain-text-body>{composition-setup}
+deck.tab.active.border=1px solid #ccc
+deck.tab.inactive.border=1px solid #ccc
+deck.tab.spacer=2px
+deck.startHidden=false
+{composition-setup}</plain-text-body>
-<div class="deck" id="deck:myDeck" tablocation="top" style="display: none"
loopcards="false"><div class="cards tabbed">
-<div class="card" label="Tapestry 5.4+" labelrendered="Tapestry 5.4+">
+<plain-text-body>{deck:id=myDeck}</plain-text-body>
+<plain-text-body>{card:label=Tapestry 5.4+}</plain-text-body>
<p>Starting with Tapestry 5.4, you can easily choose whether the foundation
JavaScript framework is jQuery or Prototype.</p>
-</div>
-<div class="card" label="5.0-5.3" labelrendered="5.0-5.3">
+<plain-text-body>{card}</plain-text-body>
+<plain-text-body>{card:label=5.0-5.3}</plain-text-body>
<p>In Tapestry versions prior to 5.4 the Prototype and Scriptaculous libraries
are included by default ... no extra download is required. Tapestry will
automatically link into your pages the prototype.js, scriptaculous.js, and
effects.js libraries, as well as the Tapestry library, tapestry.js (which
largely consists of support for form input validation). Starting with Tapestry
5.3, Underscore is also included.</p>
-</div>
-</div></div>
+<plain-text-body>{card}</plain-text-body>
+<plain-text-body>{deck}</plain-text-body>
<p>This works, but 1) doesn't preview very well (preview shows alternatives as
side-by-side cells in a table, with no header row), and 2) requires additional
processing code to be added to the SiteExporter.</p>
@@ -137,7 +108,7 @@ Deck.memoryPath = "/confluence/";
<h2 id="TestPage-ChildrenTest">Children Test</h2>
-<ul class="childpages-macro"><li><a href="test-page-2.html">Test Page
2</a></li></ul>
+<parameter ac:name="excerpt">true</parameter>
<p>foooo</p></div>
</div>