Author: buildbot
Date: Fri Feb 16 03:21:19 2018
New Revision: 1025456
Log:
Production update by buildbot for tapestry
Modified:
websites/production/tapestry/content/assets.html
websites/production/tapestry/content/cache/main.pageCache
websites/production/tapestry/content/class-reloading.html
websites/production/tapestry/content/component-classes.html
websites/production/tapestry/content/component-reference.html
websites/production/tapestry/content/component-templates.html
websites/production/tapestry/content/project-layout.html
Modified: websites/production/tapestry/content/assets.html
==============================================================================
--- websites/production/tapestry/content/assets.html (original)
+++ websites/production/tapestry/content/assets.html Fri Feb 16 03:21:19 2018
@@ -145,10 +145,10 @@
</div>
-<p>Assets can be in one of three places within a Tapestry app:</p><ol><li>In
the <strong>web application's context folder</strong>, stored inside the web
application WAR file in the usual JEE fashion. In a project following Maven's
directory layout conventions, this would be src/main/webapp or a subdirectory
of it (but <em>not</em> under src/main/webapp/WEB-INF).</li><li>For
Tapestry 5.4 and later: under <strong><code>META-INF</code></strong><code>,
with JavaScript modules under <strong>META-INF/modules</strong> and other
assets under <strong>META-INF/assets</strong>. This would be
src/main/resources/META-INF/modules
and <code>src/main/resources/META-INF/assets</code> if following Maven
directory conventions.</code></li><li>On the <strong>classpath</strong>, with
your Java class files. <em>This is deprecated in Tapestry 5.4 and later (with a
warning).</em> If following Maven directory conventions, this would correspond
to a package-named subdirectory under src/main/resourc
es/, such as src/main/resources/com/example/myapp/pages).</li></ol><h3
id="Assets-ReferencingAssetsfromTemplates">Referencing Assets from
Templates</h3><p>For referencing assets from templates, two <a
href="assets.html">binding prefixes</a> exist: "context:" and "asset:". The
"context:" prefix matches assets in the web application's context folder, and
the "asset:" prefix is for assets from the classpath.</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width:
1px;"><b>src/main/webapp/com/example/myapp/images/tapestry_banner.gif</b></div><div
class="codeContent panelContent pdl">
+<p>Assets can be in one of three places within a Tapestry app:</p><ol><li>In
the <strong>web application's context folder</strong>, stored inside the web
application WAR file in the usual JEE fashion. In a project following Maven's
directory layout conventions, this would be src/main/webapp or a subdirectory
of it (but <em>not</em> under src/main/webapp/WEB-INF).</li><li>For
Tapestry 5.4 and later: under <strong><code>META-INF</code></strong><code>,
with JavaScript modules under <strong>META-INF/modules</strong> and other
assets under <strong>META-INF/assets</strong>. This would be
src/main/resources/META-INF/modules
and <code>src/main/resources/META-INF/assets</code> if following Maven
directory conventions.</code></li><li>On the <strong>classpath</strong>, with
your Java class files. <em>This is deprecated in Tapestry 5.4 and later (with a
warning).</em> If following Maven directory conventions, this would correspond
to a package-named subdirectory under src/main/resourc
es/, such as src/main/resources/com/example/myapp/pages).</li></ol><h3
id="Assets-ReferencingAssetsfromTemplates">Referencing Assets from
Templates</h3><p>For referencing assets from templates, two <a
href="component-parameters.html">binding prefixes</a> exist: "context:" and
"asset:". The "context:" prefix matches assets in the web application's context
folder, and the "asset:" prefix is for assets from the classpath.</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader
panelHeader pdl" style="border-bottom-width:
1px;"><b>src/main/webapp/com/example/myapp/images/tapestry_banner.gif</b></div><div
class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><img src="${context:images/tapestry_banner.gif}"/>
</pre>
-</div></div><div class="confluence-information-macro
confluence-information-macro-information"><span class="aui-icon aui-icon-small
aui-iconfont-info confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>This is an example of using a
<em>template expansion</em> inside an ordinary element (rather than a
component).</p></div></div><p>If you don't provide either prefix, "asset:" is
assumed.</p><p>Also note that in older code you may occasionally see
${asset:context:...}. That means the same thing as ${context:...}.</p><h3
id="Assets-AssetsinComponentClasses">Assets in Component Classes</h3><p>Assets
are available to your code as instances of the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Asset.html">Asset</a>
interface.</p><p>Components access assets via <a
href="assets.html">injection</a>, using the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5
/ioc/annotations/Inject.html">Inject</a> annotation, which allows Assets to be
injected into components as read-only properties. The path to the resource is
specified using the Path annotation:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><div class="confluence-information-macro
confluence-information-macro-information"><span class="aui-icon aui-icon-small
aui-iconfont-info confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>This is an example of using a
<em>template expansion</em> inside an ordinary element (rather than a
component).</p></div></div><p>If you don't provide either prefix, "asset:" is
assumed.</p><p>Also note that in older code you may occasionally see
${asset:context:...}. That means the same thing as ${context:...}.</p><h3
id="Assets-AssetsinComponentClasses">Assets in Component Classes</h3><p>Assets
are available to your code as instances of the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Asset.html">Asset</a>
interface.</p><p>Components access assets via <a
href="injection.html">injection</a>, using the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapest
ry5/ioc/annotations/Inject.html">Inject</a> annotation, which allows Assets to
be injected into components as read-only properties. The path to the resource
is specified using the Path annotation:</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
@Path("context:images/tapestry_banner.gif")
private Asset banner;
@@ -163,7 +163,7 @@ private Asset icon;
@Path("${skin.root}/style.css")
private Asset style;
</pre>
-</div></div><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>The use of the <code>${...</code>}
syntax here is a <em>symbol expansion</em> (because it occurs in an annotation
in Java code), rather than a <em>template expansion</em> (which occurs only in
Tapestry template files).</p></div></div><p>An override of the skin.root symbol
would affect all references to the named asset.</p><h3
id="Assets-LocalizationofAssets">Localization of Assets</h3><p>Main Article: <a
href="assets.html">Assets</a></p><p>Assets are localized; Tapestry will search
for a variation of the file appropriate to the effective locale for the
request. In the previous example, a German user of the application may see a
file named <code>edit_de.png</code> (if such a file exists).</p><h3
id="Assets-NewAssetDomains">New Asset Domains</h3><p>I
f you wish to create new domains for assets, for example to allow assets to be
stored on the file system or in a database, you may define a new <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/AssetFactory.html">AssetFactory</a>
and contribute it to the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/AssetSource.html">AssetSource</a>
service configuration.</p><h3
id="Assets-AssetFingerprinting(Tapestry5.3andearlier)">Asset Fingerprinting
(Tapestry 5.3 and earlier)</h3><p>Tapestry creates a new URL for assets
(whether context or classpath). The URL is of the form
/assets/<strong>version</strong>/<strong>folder</strong>/<strong>path</strong>.</p><ul><li><strong>version</strong>:
Application version number, defined by the
<code>tapestry.application-version</code> symbol in your application module
(normally AppModule.java). The default is a random hex number.</li><li><strong>
folder</strong>: Identifies the library containing the asset, or "ctx" for a
context asset, or "stack" (used when combining multiple JavaScript files into a
single virtual asset).</li><li><strong>path</strong>: The path below the root
package of the library to the specific asset file.</li></ul><h3
id="Assets-AssetFingerprinting(Tapestry5.4andlater)">Asset
Fingerprinting<span> (Tapestry 5.4 and later)</span></h3><p>Tapestry 5.4
changes how Asset URLs are constructed. The version number is now
a <em>content fingerprint</em>, a hash of the actual content of the
asset.</p><p>Assets get a far-future expires header. It is no longer necessary
or desirable to change the application version number.</p><p>During development
or production, if an asset is changed in any way, it will have a new content
fingerprint and will appear, to the browser, to be an entirely new immutable
resource.</p><h3 id="Assets-CSSLinkRewriting">CSS Link Rewriting</h3><p>It is
frequently the case that CSS fi
les will include links to other files, such as background images, using
the <code>url</code>() value syntax. Under 5.4, the URL for the CSS file
and the targeted file would be broken, due to the inclusions of the CSS file's
content hash fingerprint. To fix this, Tapestry parses CSS files, locates
the <code>url()</code> directives, and rewrites the URLs to be absolute
(including the targeted file's content hash fingerprint).</p><h3
id="Assets-PerformanceNotes">Performance Notes</h3><p>Assets are expected to be
entirely static (not changing while the application is deployed). This allows
Tapestry to perform some important performance optimizations.</p><p>Tapestry
GZIP compresses the content of all assets – if the asset is compressible,
the client supports it, and you don't <a href="assets.html">explicitly disable
it</a>.</p><p><span>Further, the asset will get a </span><em>far future expires
header</em><span>, which will encourage the client browser to cache the asset
.</span></p><p>For Talestry 5.3 and earlier, you should have an explicit
application version number for any production application. Client browsers will
aggressively cache downloaded assets; they will usually not even send a request
to see if the asset has changed once the asset is downloaded the first time.
Because of this it is <em>very important</em> that each new deployment of your
application has a new <a href="assets.html">version number</a>, to force
existing clients to re-download all assets.</p><h3
id="Assets-AssetSecurity">Asset Security</h3><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>This applies to how Tapestry 5.3
and earlier manage classpath assets; Tapestry 5.4 introduces another system
which doesn't have this issue.</p></div></div><p>Because Tapestry directly
exposes files on the classp
ath to the clients, some thought has gone into ensuring that malicious clients
are not able to download assets that should not be visible to them.</p><p>First
off all, there's a package limitation: classpath assets are only visible if
there's a <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/LibraryMapping.html">LibraryMapping</a>
for them, and the library mapping substitutes for the initial folders on the
classpath. Since the most secure assets, things like
<code>hibernate.cfg.xml</code> are located in the unnamed package, they are
always off limits.</p><p>But what about other files on the classpath? Imagine
this scenario:</p><ul><li>Your Login page exposes a classpath asset,
<code>icon.png</code>.</li><li><p>A malicious client copies the URL,
<code>/assets/1.0.0/app/pages/icon.png (</code><span>which would indicate that
the Login page is actually inside a library, which is unlikely. More likely,
icon.png is a context asset a
nd the malicious user guessed the path for Login.class by looking at the
Tapestry source code.) </span><span>and changes the file name to
</span><code>Login.class</code><span>.</span></p></li><li><p>The client
decompiles the class file and spots your secret emergency password: goodbye
security! (<span>Never create such back doors, of
course!)</span></p></li></ul><p>Fortunately, this can't happen. Files with
extension ".class" are secured; they must be accompanied in the URL with a
query parameter that is the MD5 hash of the file's contents. If the query
parameter is absent, or doesn't match the actual file's content, the request is
rejected.</p><p>When your code exposes an Asset that is secured, Tapestry
generates a URL that automatically includes MD5 hash query parameter. The
malicious user is locked out of access to the files. (The only way they could
generate the MD5 hash is if<span> they somehow already have the files, in which
case they don't need to download them again an
yway.)</span></p><p>By default, Tapestry secures file extensions ".class',
".tml" and ".properties". The list can be extended by contributing to the <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ResourceDigestGenerator.html">ResourceDigestGenerator</a>
service:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>AppModule.java (partial)</b></div><div class="codeContent panelContent
pdl">
+</div></div><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>The use of the <code>${...</code>}
syntax here is a <em>symbol expansion</em> (because it occurs in an annotation
in Java code), rather than a <em>template expansion</em> (which occurs only in
Tapestry template files).</p></div></div><p>An override of the skin.root symbol
would affect all references to the named asset.</p><h3
id="Assets-LocalizationofAssets">Localization of Assets</h3><p>Main Article: <a
href="localization.html">Localization</a></p><p>Assets are localized; Tapestry
will search for a variation of the file appropriate to the effective locale for
the request. In the previous example, a German user of the application may see
a file named <code>edit_de.png</code> (if such a file exists).</p><h3
id="Assets-NewAssetDomains">New Asset Doma
ins</h3><p>If you wish to create new domains for assets, for example to allow
assets to be stored on the file system or in a database, you may define a new
<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/AssetFactory.html">AssetFactory</a>
and contribute it to the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/AssetSource.html">AssetSource</a>
service configuration.</p><h3
id="Assets-AssetFingerprinting(Tapestry5.3andearlier)">Asset Fingerprinting
(Tapestry 5.3 and earlier)</h3><p>Tapestry creates a new URL for assets
(whether context or classpath). The URL is of the form
/assets/<strong>version</strong>/<strong>folder</strong>/<strong>path</strong>.</p><ul><li><strong>version</strong>:
Application version number, defined by the
<code>tapestry.application-version</code> symbol in your application module
(normally AppModule.java). The default is a random hex number.</li>
<li><strong>folder</strong>: Identifies the library containing the asset, or
"ctx" for a context asset, or "stack" (used when combining multiple JavaScript
files into a single virtual asset).</li><li><strong>path</strong>: The path
below the root package of the library to the specific asset file.</li></ul><h3
id="Assets-AssetFingerprinting(Tapestry5.4andlater)">Asset
Fingerprinting<span> (Tapestry 5.4 and later)</span></h3><p>Tapestry 5.4
changes how Asset URLs are constructed. The version number is now
a <em>content fingerprint</em>, a hash of the actual content of the
asset.</p><p>Assets get a far-future expires header. It is no longer necessary
or desirable to change the application version number.</p><p>During development
or production, if an asset is changed in any way, it will have a new content
fingerprint and will appear, to the browser, to be an entirely new immutable
resource.</p><h3 id="Assets-CSSLinkRewriting">CSS Link Rewriting</h3><p>It is
frequently the case
that CSS files will include links to other files, such as background images,
using the <code>url</code>() value syntax. Under 5.4, the URL for the CSS
file and the targeted file would be broken, due to the inclusions of the CSS
file's content hash fingerprint. To fix this, Tapestry parses CSS files,
locates the <code>url()</code> directives, and rewrites the URLs to be
absolute (including the targeted file's content hash fingerprint).</p><h3
id="Assets-PerformanceNotes">Performance Notes</h3><p>Assets are expected to be
entirely static (not changing while the application is deployed). This allows
Tapestry to perform some important performance optimizations.</p><p>Tapestry
GZIP compresses the content of all assets – if the asset is compressible,
the client supports it, and you don't <a href="configuration.html">explicitly
disable it</a>.</p><p><span>Further, the asset will get a </span><em>far future
expires header</em><span>, which will encourage the client browser
to cache the asset.</span></p><p>For Talestry 5.3 and earlier, you should
have an explicit application version number for any production application.
Client browsers will aggressively cache downloaded assets; they will usually
not even send a request to see if the asset has changed once the asset is
downloaded the first time. Because of this it is <em>very important</em> that
each new deployment of your application has a new <a
href="configuration.html">version number</a>, to force existing clients to
re-download all assets.</p><h3 id="Assets-AssetSecurity">Asset
Security</h3><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>This applies to how Tapestry 5.3
and earlier manage classpath assets; Tapestry 5.4 introduces another system
which doesn't have this issue.</p></div></div><p>Because Tapestry directly e
xposes files on the classpath to the clients, some thought has gone into
ensuring that malicious clients are not able to download assets that should not
be visible to them.</p><p>First off all, there's a package limitation:
classpath assets are only visible if there's a <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/LibraryMapping.html">LibraryMapping</a>
for them, and the library mapping substitutes for the initial folders on the
classpath. Since the most secure assets, things like
<code>hibernate.cfg.xml</code> are located in the unnamed package, they are
always off limits.</p><p>But what about other files on the classpath? Imagine
this scenario:</p><ul><li>Your Login page exposes a classpath asset,
<code>icon.png</code>.</li><li><p>A malicious client copies the URL,
<code>/assets/1.0.0/app/pages/icon.png (</code><span>which would indicate that
the Login page is actually inside a library, which is unlikely. More likely, ico
n.png is a context asset and the malicious user guessed the path for
Login.class by looking at the Tapestry source code.) </span><span>and
changes the file name to
</span><code>Login.class</code><span>.</span></p></li><li><p>The client
decompiles the class file and spots your secret emergency password: goodbye
security! (<span>Never create such back doors, of
course!)</span></p></li></ul><p>Fortunately, this can't happen. Files with
extension ".class" are secured; they must be accompanied in the URL with a
query parameter that is the MD5 hash of the file's contents. If the query
parameter is absent, or doesn't match the actual file's content, the request is
rejected.</p><p>When your code exposes an Asset that is secured, Tapestry
generates a URL that automatically includes MD5 hash query parameter. The
malicious user is locked out of access to the files. (The only way they could
generate the MD5 hash is if<span> they somehow already have the files, in which
case they don't need
to download them again anyway.)</span></p><p>By default, Tapestry secures
file extensions ".class', ".tml" and ".properties". The list can be extended by
contributing to the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/ResourceDigestGenerator.html">ResourceDigestGenerator</a>
service:</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 static void
contributeResourceDigestGenerator(Configuration<String> configuration)
{
configuration.add("xyz");
@@ -184,7 +184,7 @@ private Asset style;
<version>5.4</version>
</dependency>
</pre>
-</div></div></div></div></div></div><p> </p><p>By adding this dependency,
all your JavaScript and CSS files will be minimized when <a
href="assets.html">PRODUCTION_MODE=true</a>. You can force the minimization of
these files, by changing the value of the constant
SymbolConstants.MINIFICATION_ENABLED in 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">
+</div></div></div></div></div></div><p> </p><p>By adding this dependency,
all your JavaScript and CSS files will be minimized when <a
href="configuration.html">PRODUCTION_MODE=true</a>. You can force the
minimization of these files, by changing the value of the constant
SymbolConstants.MINIFICATION_ENABLED in 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;">@Contribute(SymbolProvider.class)
@ApplicationDefaults
public static void
contributeApplicationDefaults(MappedConfiguration<String, String>
configuration)
Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.
Modified: websites/production/tapestry/content/class-reloading.html
==============================================================================
--- websites/production/tapestry/content/class-reloading.html (original)
+++ websites/production/tapestry/content/class-reloading.html Fri Feb 16
03:21:19 2018
@@ -110,7 +110,7 @@
</div>
-<p>One of the best features of Tapestry is automatic reloading of changed
classes and templates. <em>Page and component</em> classes will automatically
reload when changed. Likewise, changes to component templates and other related
resources will also be picked up immediately. In addition, starting in version
5.2, your service classes will also be reloaded automatically after changes (if
you're using <a href="class-reloading.html">Tapestry IoC</a>).</p><h2
id="ClassReloading-TemplateReloading">Template Reloading</h2><p>When a template
changes, all page instances (as well as the hierarchy of components below them)
are discarded and reconstructed with the new template. However, classes are not
reloaded in this case.</p><h2 id="ClassReloading-ClassReloading">Class
Reloading</h2><p>On a change to <em>any</em> loaded class from inside a
controlled package (or any sub-package of a controlled package), Tapestry will
discard all page instances, and discard the class loader.</p><p><a href=
"class-reloading.html">Persistent field data</a> on the pages will usually not
be affected (as it is stored separately, usually in the session). This allows
you to make fairly significant changes to a component class even while the
application continues to run.</p><h2
id="ClassReloading-PackagesScanned">Packages Scanned</h2><p>Only certain
classes are subject to reload. Reloading is based on package name; the packages
that are reloaded are derived from the <a
href="class-reloading.html">application configuration</a>.</p><p>If your root
package is <code>org.example.myapp</code>, then only classes in the following
packages (and their sub-packages) will be scanned for automatic
reloads:</p><ul><li>org.example.myapp.pages</li><li>org.example.myapp.components</li><li>org.example.myapp.mixins</li><li>org.example.myapp.base</li><li>org.example.myapp.services
(Tapestry 5.2 and later, with restrictions)</li></ul><p>Starting in Tapestry
5.2, live class reloading includes service implementati
on classes. There are some limitations to this. See <a
href="service-implementation-reloading.html">Service Implementation
Reloading</a> for more details.</p><h2 id="ClassReloading-FileSystemOnly">File
System Only</h2><p>Reloading of classes and other files applies only to files
that are actually on the file system, and not files obtained from JAR files.
This is perfect during development, where the files in question are in your
local workspace. In a deployed application, you are somewhat subject to the
implementation of your servlet container or application server.</p><h2
id="ClassReloading-ClassLoaderIssues">Class Loader Issues</h2><p>Tapestry uses
an extra class loader to load page and component classes.</p><p>When a change
to an underlying Java class file is detected, Tapestry discards the class
loader and any pooled page instances.</p><p>You should be careful to not hold
any references to Tapestry pages or components in other code, such as Tapestry
IoC services. Holding s
uch references can cause significant memory leaks, as they can prevent the
class loader from being reclaimed by the garbage collector.</p><h2
id="ClassReloading-ClassCastExceptions">ClassCastExceptions</h2><p>Tapestry's
class loader architecture can cause minor headaches when you make use of a
services layer, or any time that you pass component instances to objects that
are not themselves components.</p><p>In such cases you may see
ClassCastException errors. This is because the same class name, say
org.example.myapp.pages.Start, exists as two different class instances. One
class instance is loaded by the web application's default class loader. A
second class instance has been loaded <em>and transformed</em> by Tapestry's
reloading class loader.</p><p>Ordinary classes, such as Tapestry IoC Services,
will be loaded by the default class loader and expect instances to be loaded by
the same class loader (or a parent).</p><p>The solution to this problem is to
introduce an interface; the c
omponent class should implement the interface, and the service should expect
an instance of the interface, rather than a specific type.</p><p>It is
important that the interface be loaded by the default class loader. It should
not be in the pages or components package, but instead be in another package,
such as services.</p><h2 id="ClassReloading-HandlingReloadsinyourCode">Handling
Reloads in your Code</h2><p>On occasion, you may need to know when
invalidations occur, to clear your own cache. For example, if you have a
binding that creates new classes, the way <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PropertyConduitSource.html">PropertyConduitSource</a>
does, you need to discard any cached classes or instances when a change is
detected in component classes.</p><p>You do this by registering a listener with
the correct <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tpaestry5/services/
InvalidationEventHub.html">InvalidationEventHub</a> service.</p><p>For
example, your service may be in the business of creating new classes based on
component classes, and keep a cache of those classes:</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<p>One of the best features of Tapestry is automatic reloading of changed
classes and templates. <em>Page and component</em> classes will automatically
reload when changed. Likewise, changes to component templates and other related
resources will also be picked up immediately. In addition, starting in version
5.2, your service classes will also be reloaded automatically after changes (if
you're using <a href="ioc.html">Tapestry IoC</a>).</p><h2
id="ClassReloading-TemplateReloading">Template Reloading</h2><p>When a template
changes, all page instances (as well as the hierarchy of components below them)
are discarded and reconstructed with the new template. However, classes are not
reloaded in this case.</p><h2 id="ClassReloading-ClassReloading">Class
Reloading</h2><p>On a change to <em>any</em> loaded class from inside a
controlled package (or any sub-package of a controlled package), Tapestry will
discard all page instances, and discard the class loader.</p><p><a
href="class-reloa
ding.html">Persistent field data</a> on the pages will usually not be affected
(as it is stored separately, usually in the session). This allows you to make
fairly significant changes to a component class even while the application
continues to run.</p><h2 id="ClassReloading-PackagesScanned">Packages
Scanned</h2><p>Only certain classes are subject to reload. Reloading is based
on package name; the packages that are reloaded are derived from the <a
href="configuration.html">application configuration</a>.</p><p>If your root
package is <code>org.example.myapp</code>, then only classes in the following
packages (and their sub-packages) will be scanned for automatic
reloads:</p><ul><li>org.example.myapp.pages</li><li>org.example.myapp.components</li><li>org.example.myapp.mixins</li><li>org.example.myapp.base</li><li>org.example.myapp.services
(Tapestry 5.2 and later, with restrictions)</li></ul><p>Starting in Tapestry
5.2, live class reloading includes service implementation classes. Th
ere are some limitations to this. See <a
href="service-implementation-reloading.html">Service Implementation
Reloading</a> for more details.</p><h2 id="ClassReloading-FileSystemOnly">File
System Only</h2><p>Reloading of classes and other files applies only to files
that are actually on the file system, and not files obtained from JAR files.
This is perfect during development, where the files in question are in your
local workspace. In a deployed application, you are somewhat subject to the
implementation of your servlet container or application server.</p><h2
id="ClassReloading-ClassLoaderIssues">Class Loader Issues</h2><p>Tapestry uses
an extra class loader to load page and component classes.</p><p>When a change
to an underlying Java class file is detected, Tapestry discards the class
loader and any pooled page instances.</p><p>You should be careful to not hold
any references to Tapestry pages or components in other code, such as Tapestry
IoC services. Holding such references
can cause significant memory leaks, as they can prevent the class loader from
being reclaimed by the garbage collector.</p><h2
id="ClassReloading-ClassCastExceptions">ClassCastExceptions</h2><p>Tapestry's
class loader architecture can cause minor headaches when you make use of a
services layer, or any time that you pass component instances to objects that
are not themselves components.</p><p>In such cases you may see
ClassCastException errors. This is because the same class name, say
org.example.myapp.pages.Start, exists as two different class instances. One
class instance is loaded by the web application's default class loader. A
second class instance has been loaded <em>and transformed</em> by Tapestry's
reloading class loader.</p><p>Ordinary classes, such as Tapestry IoC Services,
will be loaded by the default class loader and expect instances to be loaded by
the same class loader (or a parent).</p><p>The solution to this problem is to
introduce an interface; the component class
should implement the interface, and the service should expect an instance of
the interface, rather than a specific type.</p><p>It is important that the
interface be loaded by the default class loader. It should not be in the pages
or components package, but instead be in another package, such as
services.</p><h2 id="ClassReloading-HandlingReloadsinyourCode">Handling Reloads
in your Code</h2><p>On occasion, you may need to know when invalidations occur,
to clear your own cache. For example, if you have a binding that creates new
classes, the way <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PropertyConduitSource.html">PropertyConduitSource</a>
does, you need to discard any cached classes or instances when a change is
detected in component classes.</p><p>You do this by registering a listener with
the correct <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tpaestry5/services/InvalidationEv
entHub.html">InvalidationEventHub</a> service.</p><p>For example, your service
may be in the business of creating new classes based on component classes, and
keep a cache of those classes:</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 MyServiceImpl implements MyService,
InvalidationEventListener
{
public final Map<String,Class> cache = new
ConcurrentHashMap<String,Class>();
@@ -131,7 +131,7 @@
</div></div><p>This is the intent of service builder methods; to do more than
just injecting dependencies.</p><h2
id="ClassReloading-CheckingForUpdates">Checking For Updates</h2><p>The built in
InvalidationEventHub services provide notifications of changes to component
classes, to component templates, and to component message catalogs. If you wish
to check some other resources (for example, files in a directory of the file
system or rows in a database table), you should register as an <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListener.html">UpdateListener</a>
with the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListenerHub.html">UpdateListenerHub</a>
service.</p><p>Periodically (the frequency is configurable), UpdateListeners
are notified that they should check for updates. Typically, UpdateListeners are
also InvalidationEventHubs (or provide Invali
dationEventHubs), so that other interested parties can be alerted when
underlying data changes.</p><h2
id="ClassReloading-TroubleshootingLiveClassReloading">Troubleshooting Live
Class Reloading</h2><h3 id="ClassReloading-QuickChecklist">Quick
Checklist</h3><ul><li>"Production Mode" must be false (in Tapestry 5.3 and
later)</li><li>The class must be one that Tapestry instantiates (a page,
component, or mixin class, or a Tapestry IOC service implementation that
implements an interface)</li><li>Turn on "Build Automatically" in your IDE, or
remember to build manually.</li><li>Turn <em>off</em> JVM hot code swapping, if
your servlet container supports it.</li><li>Eclipse: Uncheck the "derived"
checkbox for the Target dir (in the Project Explorer view, right click on
"target", select properties, uncheck "derived" on the Resource
tab)</li></ul><p>Some of these issues are described in more detail
below.</p><h3 id="ClassReloading-IfLiveClassReloadingdoesn'twork">If Live Class
Reloading doesn
't work</h3><h4 id="ClassReloading-ProductionMode">Production
Mode</h4><p>Starting with Tapestry 5.3, Live Class Reloading only works when
not in "Production Mode". Check your application module (usually
AppModule.java) to be sure you have:</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;">configuration.add(SymbolConstants.PRODUCTION_MODE,
"false");
</pre>
-</div></div><p>and that this isn't being overridden to "true" on your
application's startup command line.</p><h4
id="ClassReloading-BuildPathIssues">Build Path Issues</h4><p>Live Class
Reloading can fail if your build path isn't set correctly, and the exact
configuration may differ between Maven plugin versions and Eclipse versions.
The build process must be set to create classes in a folder which is in the
servlet container's classpath.</p><p>Live Class Reloading won't work correctly
with vanilla Tomcat without some tweaks (see below).</p><p>Non-Tapestry filters
can interfere with LCR. Try disabling other filters in your web.xml file to see
if that helps.</p><h4 id="ClassReloading-BuildingAutomatically">Building
Automatically</h4><p>Although LCR allows you to see changes without restarting
your app, you still need to "build" your project (to compile the Java source
into byte code). Your IDE can be set to do this automatically every time you
save a file. (In Eclipse, this is done us
ing <code>Project > Build Automatically</code>.) Alternatively, you can
manually trigger a build after you save a file. (In Eclipse, this is done using
<code>Project > Build</code>, or by pressing <code>Control-B</code>.)</p><h4
id="ClassReloading-TurnoffJVMhotcodeswapping&automaticrestarts">Turn off
JVM hot code swapping & automatic restarts</h4><p>Many servlet containers,
including Tomcat and Jetty, support various forms of hot code swapping and/or
automatic restarts when file changes are detected. These are generally
<strong>much slower</strong> than LCR and usually should be turned off with
Tapestry applications. If you're using RunJettyRun plugin for Eclipse, for
example, edit your Run Configuration, and on the Jetty tab, click Show Advanced
Options and uncheck the Enable Scanner checkbox.</p><h3
id="ClassReloading-TomcatSpecifics">Tomcat Specifics</h3><p>See <a
class="external-link"
href="http://docs.codehaus.org/display/TYNAMO/Developing+with+Tomcat+and+Eclipse
" rel="nofollow">these Tomcat-specific hints</a></p><h3
id="ClassReloading-IfLiveClassReloadingworksbutisslow">If Live Class Reloading
works but is slow</h3><p>If LCR works for you but is slow (more than a second
or two), consider the following.</p><ul><li>Be sure your project source files
(your workspace in Eclipse, for example), are on a local drive, NOT a network
location. Network drives are always slower, and the file system scanning needed
for LCR can add a noticable lag if I/O is slow. If you use Maven, be sure to
put your local repository (e.g. ~/.m2/repository) on a local drive for similar
reasons.</li><li><p>Java 7 and below: Since LCR adds classes to your PermGen
space, you may be running low on PermGen memory (and may eventually get a
"java.lang.OutOfMemoryError: PermGen space" error). Try increasing PermGen size
with a JVM argument of something like -XX:MaxPermSize=400m. (PermGen
settings are not relevant for Java 8 and
above.)</p></li></ul><p> </p></div>
+</div></div><p>and that this isn't being overridden to "true" on your
application's startup command line.</p><h4
id="ClassReloading-BuildPathIssues">Build Path Issues</h4><p>Live Class
Reloading can fail if your build path isn't set correctly, and the exact
configuration may differ between Maven plugin versions and Eclipse versions.
The build process must be set to create classes in a folder which is in the
servlet container's classpath.</p><p>Live Class Reloading won't work correctly
with vanilla Tomcat without some tweaks (see below).</p><p>Non-Tapestry filters
can interfere with LCR. Try disabling other filters in your web.xml file to see
if that helps.</p><h4 id="ClassReloading-BuildingAutomatically">Building
Automatically</h4><p>Although LCR allows you to see changes without restarting
your app, you still need to "build" your project (to compile the Java source
into byte code). Your IDE can be set to do this automatically every time you
save a file. (In Eclipse, this is done us
ing <code>Project > Build Automatically</code>.) Alternatively, you can
manually trigger a build after you save a file. (In Eclipse, this is done using
<code>Project > Build</code>, or by pressing <code>Control-B</code>.)</p><h4
id="ClassReloading-TurnoffJVMhotcodeswapping&automaticrestarts">Turn off
JVM hot code swapping & automatic restarts</h4><p>Many servlet containers,
including Tomcat and Jetty, support various forms of hot code swapping and/or
automatic restarts when file changes are detected. These are generally
<strong>much slower</strong> than LCR and usually should be turned off with
Tapestry applications. If you're using RunJettyRun plugin for Eclipse, for
example, edit your Run Configuration, and on the Jetty tab, click Show Advanced
Options and uncheck the Enable Scanner checkbox.</p><h3
id="ClassReloading-TomcatSpecifics">Tomcat Specifics</h3><p>See <a
class="external-link"
href="http://www.tynamo.org/Developing+with+Tomcat+and+Eclipse/" rel="nofollow">
these Tomcat-specific hints</a></p><h3
id="ClassReloading-IfLiveClassReloadingworksbutisslow">If Live Class Reloading
works but is slow</h3><p>If LCR works for you but is slow (more than a second
or two), consider the following.</p><ul><li>Be sure your project source files
(your workspace in Eclipse, for example), are on a local drive, NOT a network
location. Network drives are always slower, and the file system scanning needed
for LCR can add a noticable lag if I/O is slow. If you use Maven, be sure to
put your local repository (e.g. ~/.m2/repository) on a local drive for similar
reasons.</li><li><p>Java 7 and below: Since LCR adds classes to your PermGen
space, you may be running low on PermGen memory (and may eventually get a
"java.lang.OutOfMemoryError: PermGen space" error). Try increasing PermGen size
with a JVM argument of something like -XX:MaxPermSize=400m. (PermGen
settings are not relevant for Java 8 and
above.)</p></li></ul><p> </p></div>
</div>
<div class="clearer"></div>
Modified: websites/production/tapestry/content/component-classes.html
==============================================================================
--- websites/production/tapestry/content/component-classes.html (original)
+++ websites/production/tapestry/content/component-classes.html Fri Feb 16
03:21:19 2018
@@ -145,7 +145,7 @@
</div>
-<p>In most cases, each component class will have a corresponding <a
href="component-classes.html">component template</a>. However, it is also
possible for a component class to emit all of its markup itself, without using
a template.</p><p><em>For Tapestry 4 Users: Component classes in Tapestry 5 are
much easier than in Tapestry 4. There are no base classes to extend from, the
classes are concrete (not abstract), and there's no XML file. There is still a
bit of configuration in the form of Java annotations, but those now go directly
onto fields of your class, rather than on abstract getters and
setters.</em></p><h2 id="ComponentClasses-CreatingaTrivialComponent">Creating a
Trivial Component</h2><p>Creating a page or component in Tapestry 5 is a
breeze. There are only a few constraints:</p><ul><li>There must be a public
Java class.</li><li>The class must be in the correct package (see
below).</li><li>The class must have a public, no-arguments constructor. (The
default one provided by
the compiler is fine.)</li></ul><p>Here's a minimal component that outputs a
fixed message, using a <a href="component-classes.html">template</a> with a
matching file name:</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>HelloWorld.java</b></div><div class="codeContent panelContent pdl">
+<p>In most cases, each component class will have a corresponding <a
href="component-templates.html">component template</a>. However, it is also
possible for a component class to emit all of its markup itself, without using
a template.</p><p><em>For Tapestry 4 Users: Component classes in Tapestry 5 are
much easier than in Tapestry 4. There are no base classes to extend from, the
classes are concrete (not abstract), and there's no XML file. There is still a
bit of configuration in the form of Java annotations, but those now go directly
onto fields of your class, rather than on abstract getters and
setters.</em></p><h2 id="ComponentClasses-CreatingaTrivialComponent">Creating a
Trivial Component</h2><p>Creating a page or component in Tapestry 5 is a
breeze. There are only a few constraints:</p><ul><li>There must be a public
Java class.</li><li>The class must be in the correct package (see
below).</li><li>The class must have a public, no-arguments constructor. (The
default one provided
by the compiler is fine.)</li></ul><p>Here's a minimal component that outputs
a fixed message, using a <a href="component-classes.html">template</a> with a
matching file name:</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>HelloWorld.java</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">package org.example.myapp.components;
public class HelloWorld
{
@@ -171,13 +171,13 @@ public class HelloWorld
}
}
</pre>
-</div></div><p>In this example, just like the first one, the component's only
job is to write out a fixed message. The @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/BeginRender.html">BeginRender</a>
annotation is a type of <em><a href="component-classes.html">render phase
annotation</a></em>, a method annotation that instructs Tapestry when and under
what circumstances to invoke methods of your class.</p><p>These methods are not
necessarily public; they can have any access level you like (unlike in Tapestry
4). By convention they usually have package-private access level (the
default).</p><h2 id="ComponentClasses-ComponentPackages">Component
Packages</h2><p>Component classes must exist within an appropriate package
(this is necessary for runtime code transformation and class reloading to
operate).</p><p>These packages exist under the application's root package, as
follows:</p><ul><li>For pages, place classes in <em>root
</em>.<strong>pages</strong>. Page names are mapped to classes within this
package.</li><li>For mixins, place classes in
<em>root</em>.<strong>mixins</strong>. Mixin types are mapped to classes within
this package.</li><li>For other components, place classes in
<em>root</em>.<strong>components</strong>. Component types are mapped to
classes within this package.</li></ul><p>In addition, it is common for an
application to have base classes, often <em>abstract</em> base classes, that
should not be directly referenced. These should <em>not</em> go in the
<strong>pages</strong>, <strong>components</strong> or <strong>mixins</strong>
packages, because they then look like valid pages, components or mixins.
Instead, use the <em>root</em>.<strong>base</strong> package to store such base
classes.</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="conflue
nce-information-macro-body"><p>Only component classes should go in any of
these controlled packages; classes representing data, or interfaces, or
anything that isn't precisely a component class, must go elsewhere. Any
top-level class in any of the controlled packages will be transformed at
runtime. The only exception is inner classes (anonymous or not), which are
loaded by the same class loader as the component class loader, but not
transformed as components.</p></div></div><h2
id="ComponentClasses-Sub-Folders/Sub-Packages">Sub-Folders /
Sub-Packages</h2><p>Classes do not have to go directly inside the package
(pages, components, mixins, etc.). It is valid to create a sub-package to store
some of the classes. The sub-package name becomes part of the page name or
component type. Thus you might define a page component
<code>com.example.myapp.pages.admin.CreateUser</code> and the logical page name
(which often shows up inside URLs) will be
<strong>admin/CreateUser</strong>.</p><p>Tapes
try performs some simple optimizations of the logical page name (or component
type, or mixin type). It checks to see if the package name is either a prefix
or a suffix of the unqualified class name (case insensitively, of course) and
removes the prefix or suffix if so. The net result is that a class name such as
<code>com.example.myapp.pages.user.EditUser</code> will have a page name of
<code>user/Edit</code> (instead of user<code>/EditUser</code>). The goal here
is to provide shorter, more natural URLs.</p><h2
id="ComponentClasses-IndexPages">Index Pages</h2><p>One special simplification
exists for Index pages: if the logical page name is Index after removing the
package name from the unqualified class name, it will map to the root of that
folder. A class such as <code>com.example.myapp.pages.user.IndexUser</code> or
<code>com.example.myapp.pages.user.UserIndex</code> will have a page name of
<code>user/</code>.</p><p>In previous versions of Tapestry there was also the
concept of a
start page configured with the <code><a
href="component-classes.html">tapestry.start-page-name</a></code> configuration
symbol (defaults to "start"). If a page with a name as configured with that
symbol exists at the root level, this page is used as the root URL. This has
precedence over an existing Index page. If for example you have a page class
<code>com.example.myapp.pages.Start</code> it will map to
<code>/</code>.</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>Use of start-pages is discouraged
and support for it will eventually be removed. Use an Index page
instead.</p></div></div><h2 id="ComponentClasses-Pagesvs.Components">Pages vs.
Components</h2><p>The distinction between pages and component is very, very
small. The primary difference is the package name:
<em>root</em>.<strong>pages</strong>
.<em>PageName</em> for pages, and
<em>root</em>.<strong>components</strong>.<em>ComponentType</em> for
components. Conceptually, page components are simply the <em>root
component</em> of a page's component tree.</p><p><em>For Tapestry 4 users:
there was a much greater distinction in Tapestry 4 between pages and
components, which showed up as separate interfaces and a hierarchy of abstract
implementations to extend your classes from.</em></p><h2
id="ComponentClasses-ClassTransformation">Class Transformation</h2><p>Tapestry
uses your class as a starting point. It <em>transforms</em> your class at
runtime. This is necessary for a number of reasons, including to address how
Tapestry shares pages between requests.</p><p>For the most part, these
transformations are both sensible and invisible. In a few limited cases, they
comprise a marginally <a class="external-link"
href="http://www.joelonsoftware.com/printerFriendly/articles/LeakyAbstractions.html"
rel="nofollow">leaky abstractio
n</a> – for instance, the scope restrictions on instance variables
described below – but the programming model in general supports a very
high level of developer productivity.</p><p>Because transformation doesn't
occur until <em>runtime</em>, the build stage of your application is not
affected by the fact that you are creating a Tapestry application. Further,
your classes are absolutely simple POJOs during unit testing.</p><h2
id="ComponentClasses-LiveClassReloading">Live Class Reloading</h2><p>Main
Article: <a href="class-reloading.html">Class Reloading</a></p><p>Component
classes are monitored for changes by the framework. <a
href="component-classes.html">Classes are reloaded when changed</a>. This
allows you to build your application with a speed approaching that of a
scripting environment, without sacrificing any of the power of the Java
platform.</p><p>And it's fast! You won't even notice that this magic class
reloading has occurred.</p><p>The net result: sup
er productivity — change your class, see the change instantly. This is
designed to be a blend of the best of scripting environments (such as Python or
Ruby) with all the speed and power of Java backing it up.</p><p>However, class
reloading <em>only</em> applies to component classes (pages, components and
mixins) and, starting in 5.2, Tapestry IOC-based service implementations (with
some restrictions). Other classes, such as service interfaces, entity/model
classes, and other data objects, are loaded by the normal class loader and not
subject to live class reloading.</p><h2
id="ComponentClasses-InstanceVariables">Instance Variables</h2><p>Tapestry
components may have instance variables (unlike Tapestry 4, where you had to use
<em>abstract properties</em>).</p><p>Since release 5.3.2, instance variables
may be protected, or package private (that is, no access modifier). Under
specific circumstances they may even be public (public fields must either be
final, or have the @<a clas
s="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Retain.html">Retain</a> annotation).</p><p><span>Be
aware that you will need to either provide getter and setter methods to access
your classes' instance variables, or else annotate the fields
with</span><span> @</span><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Property.html">Property</a>.</p><h2
id="ComponentClasses-TransientInstanceVariables">Transient Instance
Variables</h2><p>Unless an instance variable is decorated with an annotation,
it will be a <em>transient</em> instance variable. This means that its value
resets to its default value at the end of reach request (when the <a
href="component-classes.html">page is detached from the request</a>).</p><div
class="confluence-information-macro confluence-information-macro-note"><p
class="title">About initialization</p><span class="aui-icon aui-icon-small aui-
iconfont-warning confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Never initialize an instance field
to a <em>mutable</em> object at the point of declaration. If this is done, the
instance created from that initializer becomes the default value for that field
and is reused inside the component on every request. This could cause state to
inadvertently be shared between different sessions in an
application.</p></div></div>
+</div></div><p>In this example, just like the first one, the component's only
job is to write out a fixed message. The @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/BeginRender.html">BeginRender</a>
annotation is a type of <em><a href="component-rendering.html">render phase
annotation</a></em></p><p>, a method annotation that instructs Tapestry when
and under what circumstances to invoke methods of your class.</p><p>These
methods are not necessarily public; they can have any access level you like
(unlike in Tapestry 4). By convention they usually have package-private access
level (the default).</p><h2 id="ComponentClasses-ComponentPackages">Component
Packages</h2><p>Component classes must exist within an appropriate package
(this is necessary for runtime code transformation and class reloading to
operate).</p><p>These packages exist under the application's root package, as
follows:</p><ul><li>For pages, place classes in
<em>root</em>.<strong>pages</strong>. Page names are mapped to classes within
this package.</li><li>For mixins, place classes in
<em>root</em>.<strong>mixins</strong>. Mixin types are mapped to classes within
this package.</li><li>For other components, place classes in
<em>root</em>.<strong>components</strong>. Component types are mapped to
classes within this package.</li></ul><p>In addition, it is common for an
application to have base classes, often <em>abstract</em> base classes, that
should not be directly referenced. These should <em>not</em> go in the
<strong>pages</strong>, <strong>components</strong> or <strong>mixins</strong>
packages, because they then look like valid pages, components or mixins.
Instead, use the <em>root</em>.<strong>base</strong> package to store such base
classes.</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>Only component classes should go in
any of these controlled packages; classes representing data, or interfaces, or
anything that isn't precisely a component class, must go elsewhere. Any
top-level class in any of the controlled packages will be transformed at
runtime. The only exception is inner classes (anonymous or not), which are
loaded by the same class loader as the component class loader, but not
transformed as components.</p></div></div><h2
id="ComponentClasses-Sub-Folders/Sub-Packages">Sub-Folders /
Sub-Packages</h2><p>Classes do not have to go directly inside the package
(pages, components, mixins, etc.). It is valid to create a sub-package to store
some of the classes. The sub-package name becomes part of the page name or
component type. Thus you might define a page component
<code>com.example.myapp.pages.admin.CreateUser</code> and the logical page name
(which often shows up inside URLs) will be <strong>admin/CreateUser</strong>.</p
><p>Tapestry performs some simple optimizations of the logical page name (or
>component type, or mixin type). It checks to see if the package name is
>either a prefix or a suffix of the unqualified class name (case
>insensitively, of course) and removes the prefix or suffix if so. The net
>result is that a class name such as
><code>com.example.myapp.pages.user.EditUser</code> will have a page name of
><code>user/Edit</code> (instead of user<code>/EditUser</code>). The goal here
>is to provide shorter, more natural URLs.</p><h2
>id="ComponentClasses-IndexPages">Index Pages</h2><p>One special
>simplification exists for Index pages: if the logical page name is Index
>after removing the package name from the unqualified class name, it will map
>to the root of that folder. A class such as
><code>com.example.myapp.pages.user.IndexUser</code> or
><code>com.example.myapp.pages.user.UserIndex</code> will have a page name of
><code>user/</code>.</p><p>In previous versions of Tapestry there was also the
>con
cept of a start page configured with the <code><a
href="configuration.html">tapestry.start-page-name</a></code> configuration
symbol (defaults to "start"). If a page with a name as configured with that
symbol exists at the root level, this page is used as the root URL. This has
precedence over an existing Index page. If for example you have a page class
<code>com.example.myapp.pages.Start</code> it will map to
<code>/</code>.</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>Use of start-pages is discouraged
and support for it will eventually be removed. Use an Index page
instead.</p></div></div><h2 id="ComponentClasses-Pagesvs.Components">Pages vs.
Components</h2><p>The distinction between pages and component is very, very
small. The primary difference is the package name:
<em>root</em>.<strong>pages</st
rong>.<em>PageName</em> for pages, and
<em>root</em>.<strong>components</strong>.<em>ComponentType</em> for
components. Conceptually, page components are simply the <em>root
component</em> of a page's component tree.</p><p><em>For Tapestry 4 users:
there was a much greater distinction in Tapestry 4 between pages and
components, which showed up as separate interfaces and a hierarchy of abstract
implementations to extend your classes from.</em></p><h2
id="ComponentClasses-ClassTransformation">Class Transformation</h2><p>Tapestry
uses your class as a starting point. It <em>transforms</em> your class at
runtime. This is necessary for a number of reasons, including to address how
Tapestry shares pages between requests.</p><p>For the most part, these
transformations are both sensible and invisible. In a few limited cases, they
comprise a marginally <a class="external-link"
href="http://www.joelonsoftware.com/printerFriendly/articles/LeakyAbstractions.html"
rel="nofollow">leaky abstr
action</a> – for instance, the scope restrictions on instance
variables described below – but the programming model in general supports
a very high level of developer productivity.</p><p>Because transformation
doesn't occur until <em>runtime</em>, the build stage of your application is
not affected by the fact that you are creating a Tapestry application. Further,
your classes are absolutely simple POJOs during unit testing.</p><h2
id="ComponentClasses-LiveClassReloading">Live Class Reloading</h2><p>Main
Article: <a href="class-reloading.html">Class Reloading</a></p><p>Component
classes are monitored for changes by the framework. <a
href="class-reloading.html">Classes are reloaded when changed</a>. This allows
you to build your application with a speed approaching that of a scripting
environment, without sacrificing any of the power of the Java
platform.</p><p>And it's fast! You won't even notice that this magic class
reloading has occurred.</p><p>The net result:
super productivity — change your class, see the change instantly. This
is designed to be a blend of the best of scripting environments (such as Python
or Ruby) with all the speed and power of Java backing it up.</p><p>However,
class reloading <em>only</em> applies to component classes (pages, components
and mixins) and, starting in 5.2, Tapestry IOC-based service implementations
(with some restrictions). Other classes, such as service interfaces,
entity/model classes, and other data objects, are loaded by the normal class
loader and not subject to live class reloading.</p><h2
id="ComponentClasses-InstanceVariables">Instance Variables</h2><p>Tapestry
components may have instance variables (unlike Tapestry 4, where you had to use
<em>abstract properties</em>).</p><p>Since release 5.3.2, instance variables
may be protected, or package private (that is, no access modifier). Under
specific circumstances they may even be public (public fields must either be
final, or have the @<a c
lass="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Retain.html">Retain</a> annotation).</p><p><span>Be
aware that you will need to either provide getter and setter methods to access
your classes' instance variables, or else annotate the fields
with</span><span> @</span><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Property.html">Property</a>.</p><h2
id="ComponentClasses-TransientInstanceVariables">Transient Instance
Variables</h2><p>Unless an instance variable is decorated with an annotation,
it will be a <em>transient</em> instance variable. This means that its value
resets to its default value at the end of reach request (when the <a
href="page-life-cycle.html">page is detached from the
request</a></p><p>).</p><div class="confluence-information-macro
confluence-information-macro-note"><p class="title">About
initialization</p><span class="aui-icon aui-icon-sm
all aui-iconfont-warning confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Never initialize an instance field
to a <em>mutable</em> object at the point of declaration. If this is done, the
instance created from that initializer becomes the default value for that field
and is reused inside the component on every request. This could cause state to
inadvertently be shared between different sessions in an
application.</p></div></div>
<div class="aui-message aui-message-warning">
Deprecated since 5.2 |
For Tapestry 5.1 and earlier, in the rare event that you have a variable that
can keep its value between requests and you would like to defeat that reset
logic, then you can add a @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Retain.html">Retain</a>
annotation to the field. You should take care that no client-specific data is
stored into such a field, since on a later request the same page
<em>instance</em> may be used for a different user. Likewise, on a later
request for the <em>same</em> client, a <em>different</em> page instance may be
used.
-</div><p>Use <a href="component-classes.html">persistent fields</a> to hold
client-specific information from one request to the next.</p><p>Further, final
fields are (in fact) final, and will not be reset between requests.</p><h2
id="ComponentClasses-Constructors">Constructors</h2><p>Tapestry will
instantiate your class using the default, no arguments constructor. Other
constructors will be ignored.</p><h2
id="ComponentClasses-Injection">Injection</h2><p>Main Article: <a
href="injection.html">Injection</a></p><p>Injection of dependencies occurs at
the field level, via additional annotations. At runtime, fields that contain
injections become read-only.</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div><p>Use <a href="persistent-page-data.html">persistent fields</a> to
hold client-specific information from one request to the next.</p><p>Further,
final fields are (in fact) final, and will not be reset between
requests.</p><h2
id="ComponentClasses-Constructors">Constructors</h2><p>Tapestry will
instantiate your class using the default, no arguments constructor. Other
constructors will be ignored.</p><h2
id="ComponentClasses-Injection">Injection</h2><p>Main Article: <a
href="injection.html">Injection</a></p><p>Injection of dependencies occurs at
the field level, via additional annotations. At runtime, fields that contain
injections become read-only.</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 // inject a resource
private ComponentResources componentResources;
@@ -191,7 +191,7 @@ private Asset banner;
@Inject // inject a service
private AjaxResponseRenderer ajaxResponseRenderer;
</pre>
-</div></div><h2 id="ComponentClasses-Parameters">Parameters</h2><p>Main
Article: <a href="component-parameters.html">Component
Parameters</a></p><p>Component parameters are private fields of your component
class annotated with @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Parameter.html">Parameter</a>.
Component parameters represent a two-way binding of a field of your component
and a property or resource of its containing component or page.</p><h2
id="ComponentClasses-PersistentFields">Persistent Fields</h2><p>Main Article:
<a href="persistent-page-data.html">Persistent Page Data</a></p><p>Most fields
in component classes are automatically cleared at the end of each request.
However, fields may be annotated so that they retain their value across
requests, using the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html">Persist</a>
annotation.</p><h2 i
d="ComponentClasses-Embedded_ComponentsEmbeddedComponents"><span
class="confluence-anchor-link"
id="ComponentClasses-Embedded_Components"></span>Embedded
Components</h2><p>Components often contain other components. Components inside
another component's template are called <em>embedded components</em>. The
containing component's <a href="component-classes.html">template</a> will
contain special elements, in the Tapestry namespace, identifying where the the
embedded components go.</p><p>You can define the type of component inside
template, or you can create an instance variable for the component and use the
@<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html">Component</a>
annotation to define the component type and parameters.</p><p>Example:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelContent pdl">
+</div></div><h2 id="ComponentClasses-Parameters">Parameters</h2><p>Main
Article: <a href="component-parameters.html">Component
Parameters</a></p><p>Component parameters are private fields of your component
class annotated with @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Parameter.html">Parameter</a>.
Component parameters represent a two-way binding of a field of your component
and a property or resource of its containing component or page.</p><h2
id="ComponentClasses-PersistentFields">Persistent Fields</h2><p>Main Article:
<a href="persistent-page-data.html">Persistent Page Data</a></p><p>Most fields
in component classes are automatically cleared at the end of each request.
However, fields may be annotated so that they retain their value across
requests, using the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html">Persist</a>
annotation.</p><h2 i
d="ComponentClasses-Embedded_ComponentsEmbeddedComponents"><span
class="confluence-anchor-link"
id="ComponentClasses-Embedded_Components"></span>Embedded
Components</h2><p>Components often contain other components. Components inside
another component's template are called <em>embedded components</em>. The
containing component's <a href="component-templates.html">template</a> will
contain special elements, in the Tapestry namespace, identifying where the the
embedded components go.</p><p>You can define the type of component inside
template, or you can create an instance variable for the component and use the
@<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html">Component</a>
annotation to define the component type and parameters.</p><p>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;">package org.example.app.pages;
import org.apache.tapestry5.annotations.Component;